diff --git a/Assets/ARDK.meta b/Assets/ARDK.meta new file mode 100644 index 0000000..3000084 --- /dev/null +++ b/Assets/ARDK.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: d1d8b692fcb9a4b3aaa54c59d88d8e86 +folderAsset: yes +timeCreated: 1525206264 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR.meta b/Assets/ARDK/AR.meta new file mode 100644 index 0000000..779b5d2 --- /dev/null +++ b/Assets/ARDK/AR.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: a967acdd28c574d94bebaec67758ed9d +folderAsset: yes +timeCreated: 1525206338 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/ARError.cs b/Assets/ARDK/AR/ARError.cs new file mode 100644 index 0000000..95be119 --- /dev/null +++ b/Assets/ARDK/AR/ARError.cs @@ -0,0 +1,31 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.AR +{ + /// Possible error values output by an AR session's didFailWithError callback. + public enum ARError + { + /// The ERConfiguration object passed to the Run() method is not supported by the current device. + UnsupportedConfiguration = 100, + + /// A sensor required to run the session is not available. + SensorUnavailable = 101, + + /// A sensor failed to provide the required input. + SensorFailed = 102, + + /// The user has denied your app permission to use the device camera. + CameraUnauthorized = 103, + + /// World tracking has encountered a fatal error. + WorldTrackingFailed = 200, + + /// An invalid reference image was passed in the configuration. + InvalidReferenceImage = 300, + + /// AR features are not available currently, check for availability using the + /// ARCore Availability API. + /// @note This is an Android-only value. + AvailabilityFailure = 400, + } +} diff --git a/Assets/ARDK/AR/ARError.cs.meta b/Assets/ARDK/AR/ARError.cs.meta new file mode 100644 index 0000000..f27f700 --- /dev/null +++ b/Assets/ARDK/AR/ARError.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 56dda44e0b5b04736ab02281ec491a72 +timeCreated: 1525206586 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/ARFrameDisposalPolicy.cs b/Assets/ARDK/AR/ARFrameDisposalPolicy.cs new file mode 100644 index 0000000..505c0e2 --- /dev/null +++ b/Assets/ARDK/AR/ARFrameDisposalPolicy.cs @@ -0,0 +1,12 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.AR +{ + // Maybe this could become a Flags enum about what to retain in the future. + public enum ARFrameDisposalPolicy + { + DisposeOldFrames, + ReleaseImageAndTexturesOfOldFrames, + KeepOldFrames + } +} \ No newline at end of file diff --git a/Assets/ARDK/AR/ARFrameDisposalPolicy.cs.meta b/Assets/ARDK/AR/ARFrameDisposalPolicy.cs.meta new file mode 100644 index 0000000..92dd25a --- /dev/null +++ b/Assets/ARDK/AR/ARFrameDisposalPolicy.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a5944466509a4ef484b205df2db7e566 +timeCreated: 1612503607 \ No newline at end of file diff --git a/Assets/ARDK/AR/ARSessionEventArgs.meta b/Assets/ARDK/AR/ARSessionEventArgs.meta new file mode 100644 index 0000000..2765f71 --- /dev/null +++ b/Assets/ARDK/AR/ARSessionEventArgs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d9bfe534d3c284fc08d498f2d08791db +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/ARSessionEventArgs/ARSessionDeinitializedArgs.cs b/Assets/ARDK/AR/ARSessionEventArgs/ARSessionDeinitializedArgs.cs new file mode 100644 index 0000000..696f1de --- /dev/null +++ b/Assets/ARDK/AR/ARSessionEventArgs/ARSessionDeinitializedArgs.cs @@ -0,0 +1,11 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.AR.ARSessionEventArgs +{ + public struct ARSessionDeinitializedArgs: + IArdkEventArgs + { + } +} diff --git a/Assets/ARDK/AR/ARSessionEventArgs/ARSessionDeinitializedArgs.cs.meta b/Assets/ARDK/AR/ARSessionEventArgs/ARSessionDeinitializedArgs.cs.meta new file mode 100644 index 0000000..46124f4 --- /dev/null +++ b/Assets/ARDK/AR/ARSessionEventArgs/ARSessionDeinitializedArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 374c3efc2ae6f461d90d7b5147add825 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/ARSessionEventArgs/ARSessionFailedArgs.cs b/Assets/ARDK/AR/ARSessionEventArgs/ARSessionFailedArgs.cs new file mode 100644 index 0000000..9f1989d --- /dev/null +++ b/Assets/ARDK/AR/ARSessionEventArgs/ARSessionFailedArgs.cs @@ -0,0 +1,17 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.AR.ARSessionEventArgs +{ + public struct ARSessionFailedArgs: + IArdkEventArgs + { + public readonly ARError Error; + + public ARSessionFailedArgs(ARError error) + { + Error = error; + } + } +} diff --git a/Assets/ARDK/AR/ARSessionEventArgs/ARSessionFailedArgs.cs.meta b/Assets/ARDK/AR/ARSessionEventArgs/ARSessionFailedArgs.cs.meta new file mode 100644 index 0000000..f9aed01 --- /dev/null +++ b/Assets/ARDK/AR/ARSessionEventArgs/ARSessionFailedArgs.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 826acd386d22424994b6bb2b8daeb65d +timeCreated: 1607548748 \ No newline at end of file diff --git a/Assets/ARDK/AR/ARSessionEventArgs/ARSessionInterruptedArgs.cs b/Assets/ARDK/AR/ARSessionEventArgs/ARSessionInterruptedArgs.cs new file mode 100644 index 0000000..c08f4d1 --- /dev/null +++ b/Assets/ARDK/AR/ARSessionEventArgs/ARSessionInterruptedArgs.cs @@ -0,0 +1,11 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.AR.ARSessionEventArgs +{ + public struct ARSessionInterruptedArgs: + IArdkEventArgs + { + } +} diff --git a/Assets/ARDK/AR/ARSessionEventArgs/ARSessionInterruptedArgs.cs.meta b/Assets/ARDK/AR/ARSessionEventArgs/ARSessionInterruptedArgs.cs.meta new file mode 100644 index 0000000..3c85761 --- /dev/null +++ b/Assets/ARDK/AR/ARSessionEventArgs/ARSessionInterruptedArgs.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 73c66c39588848f7a85532a1c892de15 +timeCreated: 1607548606 \ No newline at end of file diff --git a/Assets/ARDK/AR/ARSessionEventArgs/ARSessionInterruptionEndedArgs.cs b/Assets/ARDK/AR/ARSessionEventArgs/ARSessionInterruptionEndedArgs.cs new file mode 100644 index 0000000..6a018f8 --- /dev/null +++ b/Assets/ARDK/AR/ARSessionEventArgs/ARSessionInterruptionEndedArgs.cs @@ -0,0 +1,11 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.AR.ARSessionEventArgs +{ + public struct ARSessionInterruptionEndedArgs: + IArdkEventArgs + { + } +} diff --git a/Assets/ARDK/AR/ARSessionEventArgs/ARSessionInterruptionEndedArgs.cs.meta b/Assets/ARDK/AR/ARSessionEventArgs/ARSessionInterruptionEndedArgs.cs.meta new file mode 100644 index 0000000..1d8376b --- /dev/null +++ b/Assets/ARDK/AR/ARSessionEventArgs/ARSessionInterruptionEndedArgs.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f267a561db24474383ce185a661763af +timeCreated: 1607548681 \ No newline at end of file diff --git a/Assets/ARDK/AR/ARSessionEventArgs/ARSessionPausedArgs.cs b/Assets/ARDK/AR/ARSessionEventArgs/ARSessionPausedArgs.cs new file mode 100644 index 0000000..46638ba --- /dev/null +++ b/Assets/ARDK/AR/ARSessionEventArgs/ARSessionPausedArgs.cs @@ -0,0 +1,11 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.AR.ARSessionEventArgs +{ + public struct ARSessionPausedArgs: + IArdkEventArgs + { + } +} diff --git a/Assets/ARDK/AR/ARSessionEventArgs/ARSessionPausedArgs.cs.meta b/Assets/ARDK/AR/ARSessionEventArgs/ARSessionPausedArgs.cs.meta new file mode 100644 index 0000000..4fe7b29 --- /dev/null +++ b/Assets/ARDK/AR/ARSessionEventArgs/ARSessionPausedArgs.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 0b78dac5b402472098f55c172895fcdd +timeCreated: 1607018524 \ No newline at end of file diff --git a/Assets/ARDK/AR/ARSessionEventArgs/ARSessionRanArgs.cs b/Assets/ARDK/AR/ARSessionEventArgs/ARSessionRanArgs.cs new file mode 100644 index 0000000..5d0b2a8 --- /dev/null +++ b/Assets/ARDK/AR/ARSessionEventArgs/ARSessionRanArgs.cs @@ -0,0 +1,11 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.AR.ARSessionEventArgs +{ + public struct ARSessionRanArgs: + IArdkEventArgs + { + } +} diff --git a/Assets/ARDK/AR/ARSessionEventArgs/ARSessionRanArgs.cs.meta b/Assets/ARDK/AR/ARSessionEventArgs/ARSessionRanArgs.cs.meta new file mode 100644 index 0000000..674e159 --- /dev/null +++ b/Assets/ARDK/AR/ARSessionEventArgs/ARSessionRanArgs.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d968aec455454cdf8586fd3298017d0d +timeCreated: 1607018481 \ No newline at end of file diff --git a/Assets/ARDK/AR/ARSessionEventArgs/AnchorsArgs.cs b/Assets/ARDK/AR/ARSessionEventArgs/AnchorsArgs.cs new file mode 100644 index 0000000..12da7de --- /dev/null +++ b/Assets/ARDK/AR/ARSessionEventArgs/AnchorsArgs.cs @@ -0,0 +1,21 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.Collections.ObjectModel; + +using Niantic.ARDK.AR.Anchors; +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.AR.ARSessionEventArgs +{ + public struct AnchorsArgs: + IArdkEventArgs + { + public AnchorsArgs(IARAnchor[] anchors): + this() + { + Anchors = new ReadOnlyCollection(anchors); + } + + public ReadOnlyCollection Anchors { get; } + } +} diff --git a/Assets/ARDK/AR/ARSessionEventArgs/AnchorsArgs.cs.meta b/Assets/ARDK/AR/ARSessionEventArgs/AnchorsArgs.cs.meta new file mode 100644 index 0000000..d560bbe --- /dev/null +++ b/Assets/ARDK/AR/ARSessionEventArgs/AnchorsArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e91873eb6ff6c438fa3b2eb557146799 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/ARSessionEventArgs/AnchorsMergedArgs.cs b/Assets/ARDK/AR/ARSessionEventArgs/AnchorsMergedArgs.cs new file mode 100644 index 0000000..c164de3 --- /dev/null +++ b/Assets/ARDK/AR/ARSessionEventArgs/AnchorsMergedArgs.cs @@ -0,0 +1,23 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.Collections.ObjectModel; + +using Niantic.ARDK.AR.Anchors; +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.AR.ARSessionEventArgs +{ + public struct AnchorsMergedArgs: + IArdkEventArgs + { + public AnchorsMergedArgs(IARAnchor parent, IARAnchor[] children): + this() + { + Parent = parent; + Children = new ReadOnlyCollection(children); + } + + public IARAnchor Parent { get; } + public ReadOnlyCollection Children { get; } + } +} diff --git a/Assets/ARDK/AR/ARSessionEventArgs/AnchorsMergedArgs.cs.meta b/Assets/ARDK/AR/ARSessionEventArgs/AnchorsMergedArgs.cs.meta new file mode 100644 index 0000000..66fa14d --- /dev/null +++ b/Assets/ARDK/AR/ARSessionEventArgs/AnchorsMergedArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e6db636ee9df2453a983e373e56b9bc5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/ARSessionEventArgs/AnyARSessionInitializedArgs.cs b/Assets/ARDK/AR/ARSessionEventArgs/AnyARSessionInitializedArgs.cs new file mode 100644 index 0000000..5b10d20 --- /dev/null +++ b/Assets/ARDK/AR/ARSessionEventArgs/AnyARSessionInitializedArgs.cs @@ -0,0 +1,21 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.AR.ARSessionEventArgs +{ + public struct AnyARSessionInitializedArgs: + IArdkEventArgs + { + public AnyARSessionInitializedArgs(IARSession session, bool isLocal): + this() + { + Session = session; + _IsLocal = isLocal; + } + + public IARSession Session { get; private set; } + + internal bool _IsLocal { get; } + } +} \ No newline at end of file diff --git a/Assets/ARDK/AR/ARSessionEventArgs/AnyARSessionInitializedArgs.cs.meta b/Assets/ARDK/AR/ARSessionEventArgs/AnyARSessionInitializedArgs.cs.meta new file mode 100644 index 0000000..c67d657 --- /dev/null +++ b/Assets/ARDK/AR/ARSessionEventArgs/AnyARSessionInitializedArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f6b3f19f2034a479fb92d138acaeaf2b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/ARSessionEventArgs/CameraTrackingStateChangedArgs.cs b/Assets/ARDK/AR/ARSessionEventArgs/CameraTrackingStateChangedArgs.cs new file mode 100644 index 0000000..480355d --- /dev/null +++ b/Assets/ARDK/AR/ARSessionEventArgs/CameraTrackingStateChangedArgs.cs @@ -0,0 +1,21 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.AR.Camera; +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.AR.ARSessionEventArgs +{ + public struct CameraTrackingStateChangedArgs: + IArdkEventArgs + { + public CameraTrackingStateChangedArgs(IARCamera camera, TrackingState trackingState): + this() + { + Camera = camera; + TrackingState = trackingState; + } + + public IARCamera Camera { get; private set; } + public TrackingState TrackingState { get; private set; } + } +} diff --git a/Assets/ARDK/AR/ARSessionEventArgs/CameraTrackingStateChangedArgs.cs.meta b/Assets/ARDK/AR/ARSessionEventArgs/CameraTrackingStateChangedArgs.cs.meta new file mode 100644 index 0000000..0f35aeb --- /dev/null +++ b/Assets/ARDK/AR/ARSessionEventArgs/CameraTrackingStateChangedArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c07dcb9b35f93466f8d68fb919b5e712 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/ARSessionEventArgs/FrameUpdatedArgs.cs b/Assets/ARDK/AR/ARSessionEventArgs/FrameUpdatedArgs.cs new file mode 100644 index 0000000..c012fc5 --- /dev/null +++ b/Assets/ARDK/AR/ARSessionEventArgs/FrameUpdatedArgs.cs @@ -0,0 +1,19 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.AR.Frame; +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.AR.ARSessionEventArgs +{ + public struct FrameUpdatedArgs: + IArdkEventArgs + { + public FrameUpdatedArgs(IARFrame frame) + : this() + { + Frame = frame; + } + + public IARFrame Frame { get; private set; } + } +} diff --git a/Assets/ARDK/AR/ARSessionEventArgs/FrameUpdatedArgs.cs.meta b/Assets/ARDK/AR/ARSessionEventArgs/FrameUpdatedArgs.cs.meta new file mode 100644 index 0000000..0142702 --- /dev/null +++ b/Assets/ARDK/AR/ARSessionEventArgs/FrameUpdatedArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d9af593312af943f39e7caeb4c360ec4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/ARSessionEventArgs/MapsArgs.cs b/Assets/ARDK/AR/ARSessionEventArgs/MapsArgs.cs new file mode 100644 index 0000000..8139473 --- /dev/null +++ b/Assets/ARDK/AR/ARSessionEventArgs/MapsArgs.cs @@ -0,0 +1,21 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.Collections.ObjectModel; + +using Niantic.ARDK.AR.SLAM; +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.AR.ARSessionEventArgs +{ + public struct MapsArgs: + IArdkEventArgs + { + public MapsArgs(IARMap[] maps): + this() + { + Maps = new ReadOnlyCollection(maps); + } + + public ReadOnlyCollection Maps { get; private set; } + } +} diff --git a/Assets/ARDK/AR/ARSessionEventArgs/MapsArgs.cs.meta b/Assets/ARDK/AR/ARSessionEventArgs/MapsArgs.cs.meta new file mode 100644 index 0000000..926e094 --- /dev/null +++ b/Assets/ARDK/AR/ARSessionEventArgs/MapsArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1e6ebce341eb8417dba14e1444e11771 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/ARSessionEventArgs/QueryingShouldSessionAttemptRelocalizationArgs.cs b/Assets/ARDK/AR/ARSessionEventArgs/QueryingShouldSessionAttemptRelocalizationArgs.cs new file mode 100644 index 0000000..02e5b29 --- /dev/null +++ b/Assets/ARDK/AR/ARSessionEventArgs/QueryingShouldSessionAttemptRelocalizationArgs.cs @@ -0,0 +1,15 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.AR.ARSessionEventArgs +{ + public sealed class QueryingShouldSessionAttemptRelocalizationArgs: + IArdkEventArgs + { + /// + /// Set this property to true if the session should attempt a relocalization. + /// + public bool ShouldSessionAttemptRelocalization { get; set; } + } +} diff --git a/Assets/ARDK/AR/ARSessionEventArgs/QueryingShouldSessionAttemptRelocalizationArgs.cs.meta b/Assets/ARDK/AR/ARSessionEventArgs/QueryingShouldSessionAttemptRelocalizationArgs.cs.meta new file mode 100644 index 0000000..4dc7e20 --- /dev/null +++ b/Assets/ARDK/AR/ARSessionEventArgs/QueryingShouldSessionAttemptRelocalizationArgs.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 8f7a14c7a17f48a7848696e630c793dc +timeCreated: 1607548905 \ No newline at end of file diff --git a/Assets/ARDK/AR/ARSessionFactory.cs b/Assets/ARDK/AR/ARSessionFactory.cs new file mode 100644 index 0000000..4be447f --- /dev/null +++ b/Assets/ARDK/AR/ARSessionFactory.cs @@ -0,0 +1,301 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.ComponentModel; + +using Niantic.ARDK.AR.ARSessionEventArgs; +using Niantic.ARDK.VirtualStudio; +using Niantic.ARDK.VirtualStudio.AR; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.VirtualStudio.Remote; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; + +namespace Niantic.ARDK.AR +{ + /// Class used to create ARSessions and also to be notified when new ARSessions are created. + public static class ARSessionFactory + { + /// Create an ARSession appropriate for the current device. + /// + /// On a mobile device, the attempted order will be LiveDevice, Remote, and finally Mock. + /// In the Unity Editor, the attempted order will be Remote, then Mock. + /// + /// @param stageIdentifier + /// The identifier used by the C++ library to connect all related components. + /// + /// @returns The created session, or throws if it was not possible to create a session. + public static IARSession Create(Guid stageIdentifier = default) + { + return _Create(null, stageIdentifier); + } + + /// Create an ARSession with the specified RuntimeEnvironment. + /// + /// @param env + /// The env used to create the session for. + /// @param stageIdentifier + /// The identifier used by the C++ library to connect all related components. + /// + /// @returns The created session, or null if it was not possible to create a session. + public static IARSession Create(RuntimeEnvironment env, Guid stageIdentifier = default(Guid)) + { + if (stageIdentifier == default(Guid)) + stageIdentifier = Guid.NewGuid(); + + IARSession result; + switch (env) + { + case RuntimeEnvironment.Default: + // Return early here or else _InvokeSessionInitialized will get called twice + return Create(stageIdentifier); + + case RuntimeEnvironment.LiveDevice: + #pragma warning disable CS0162 + if (NativeAccess.Mode != NativeAccess.ModeType.Native && NativeAccess.Mode != NativeAccess.ModeType.Testing) + return null; + #pragma warning restore CS0162 + + if (_activeSession != null) + throw new InvalidOperationException("There's another session still active."); + + result = new _NativeARSession(stageIdentifier); + break; + + case RuntimeEnvironment.Remote: + if (!_RemoteConnection.IsEnabled) + return null; + + result = new _RemoteEditorARSession(stageIdentifier); + break; + + case RuntimeEnvironment.Mock: + result = new _MockARSession(stageIdentifier, _VirtualStudioManager.Instance); + break; + + default: + throw new InvalidEnumArgumentException(nameof(env), (int)env, env.GetType()); + } + + _InvokeSessionInitialized(result, isLocal: true); + return result; + } + + ///Create an AR Playback Session. + /// + /// @param stageIdentifier + /// The identifier used by the C++ library to connect all related components. + /// + /// @returns The created session, or throws if it was not possible to create a session. + /// @note this is an experimental feature + internal static IARSession _CreatePlaybackSession(Guid stageIdentifier = default(Guid)) + { + if (stageIdentifier == default(Guid)) + stageIdentifier = Guid.NewGuid(); + +#pragma warning disable CS0162 + if (NativeAccess.Mode != NativeAccess.ModeType.Native && NativeAccess.Mode != NativeAccess.ModeType.Testing) + return null; +#pragma warning disable CS0162 + + if (_activeSession != null) + throw new InvalidOperationException("There's another session still active."); + + // Enable playback + IARSession result = new _NativeARSession(stageIdentifier, true); + + _InvokeSessionInitialized(result, isLocal: true); + return result; + } + + private static ArdkEventHandler _sessionInitialized; + + /// Event invoked when a new session is created and initialized. + public static event ArdkEventHandler SessionInitialized + { + add + { + _StaticMemberValidator._FieldIsNullWhenScopeEnds(() => _sessionInitialized); + + _sessionInitialized += value; + + IARSession activeSession; + lock (_activeSessionLock) + activeSession = _activeSession; + + if (activeSession != null) + { + var args = new AnyARSessionInitializedArgs(activeSession, isLocal: true); + value(args); + } + } + remove + { + _sessionInitialized -= value; + } + } + + internal static readonly RuntimeEnvironment[] _defaultBestMatches = +#if (UNITY_IOS || UNITY_ANDROID) && !UNITY_EDITOR + new RuntimeEnvironment[] { RuntimeEnvironment.LiveDevice, RuntimeEnvironment.Remote, RuntimeEnvironment.Mock }; +#else + new RuntimeEnvironment[] + { + RuntimeEnvironment.Remote, RuntimeEnvironment.Mock + }; +#endif + + /// Tries to create an ARSession of any of the given envs. + /// + /// @param envs + /// A collection of runtime environments used to create the session for. As not all platforms + /// support all environments, the code will try to create the session for the first + /// environment, then for the second and so on. If envs is null or empty, then the order used + /// is LiveDevice, Remote and finally Mock. + /// @param stageIdentifier + /// The identifier used by the C++ library to connect all related components. + /// + /// @returns The created session, or null if it was not possible to create a session. + internal static IARSession _Create + ( + IEnumerable envs = null, + Guid stageIdentifier = default(Guid) + ) + { + bool triedAtLeast1 = false; + + if (envs != null) + { + foreach (var env in envs) + { + var possibleResult = Create(env, stageIdentifier); + if (possibleResult != null) + return possibleResult; + + triedAtLeast1 = true; + } + } + + if (!triedAtLeast1) + return _Create(_defaultBestMatches, stageIdentifier); + + throw new NotSupportedException("None of the provided envs are supported by this build."); + } + + internal static IARSession _CreateVirtualStudioManagedARSession + ( + RuntimeEnvironment env, + Guid stageIdentifier, + bool isLocal, + _IVirtualStudioManager virtualStudioManager + ) + { + IARSession result; + + switch (env) + { + case RuntimeEnvironment.Mock: + { + if (virtualStudioManager == null) + virtualStudioManager = _VirtualStudioManager.Instance; + + result = new _MockARSession(stageIdentifier, virtualStudioManager); + break; + } + + case RuntimeEnvironment.Remote: + result = new _RemoteEditorARSession(stageIdentifier); + break; + + default: + throw new InvalidEnumArgumentException(nameof(env), (int)env, typeof(RuntimeEnvironment)); + } + + ARLog._DebugFormat + ( + "Created IARSession with env: {0} and stage identifier: {1}", + false, + env, + stageIdentifier + ); + + _InvokeSessionInitialized(result, isLocal); + return result; + } + + private static object _activeSessionLock = new object(); + private static IARSession _activeSession; + + // As there is no ConcurrentHashSet at the moment, we use a ConcurrentDictionary and only + // care about the key, ignoring the value. + private static ConcurrentDictionary _nonLocalSessions = + new ConcurrentDictionary(_ReferenceComparer.Instance); + + private static void _InvokeSessionInitialized(IARSession session, bool isLocal) + { + var handler = isLocal ? _sessionInitialized : _nonLocalSessionInitialized; + if (handler != null) + { + var args = new AnyARSessionInitializedArgs(session, isLocal); + handler(args); + } + + if (isLocal) + { + _StaticMemberValidator._FieldIsNullWhenScopeEnds(() => _activeSession); + + lock (_activeSessionLock) + { + if (_activeSession != null) + throw new InvalidOperationException("There's another session still active."); + + _activeSession = session; + } + + session.Deinitialized += + (_) => + { + lock (_activeSessionLock) + if (_activeSession == session) + _activeSession = null; + }; + } + else + { + _StaticMemberValidator._CollectionIsEmptyWhenScopeEnds(() => _nonLocalSessions); + + if (!_nonLocalSessions.TryAdd(session, true)) + throw new InvalidOperationException("Duplicated session."); + + session.Deinitialized += (ignored) => _nonLocalSessions.TryRemove(session, out _); + } + } + + private static ArdkEventHandler _nonLocalSessionInitialized; + + internal static event ArdkEventHandler _NonLocalSessionInitialized + { + add + { + _StaticMemberValidator._FieldIsNullWhenScopeEnds(() => _nonLocalSessionInitialized); + + _nonLocalSessionInitialized += value; + + // Doing a foreach on a ConcurrentDictionary is safe even if values keep being added or + // removed during the iteration. Also, it is lock free, so no chance of dead-locks. + foreach (var session in _nonLocalSessions.Keys) + { + var args = new AnyARSessionInitializedArgs(session, isLocal: false); + value(args); + } + } + remove + { + _nonLocalSessionInitialized -= value; + } + } + } +} diff --git a/Assets/ARDK/AR/ARSessionFactory.cs.meta b/Assets/ARDK/AR/ARSessionFactory.cs.meta new file mode 100644 index 0000000..9f008c5 --- /dev/null +++ b/Assets/ARDK/AR/ARSessionFactory.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 81d2d1b962fa440ebab8434dc81fda3d +timeCreated: 1595879947 \ No newline at end of file diff --git a/Assets/ARDK/AR/ARSessionRunOptions.cs b/Assets/ARDK/AR/ARSessionRunOptions.cs new file mode 100644 index 0000000..f28287f --- /dev/null +++ b/Assets/ARDK/AR/ARSessionRunOptions.cs @@ -0,0 +1,25 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +namespace Niantic.ARDK.AR +{ + /// Options for transitioning an AR session's current state when you change its configuration. + [Flags] + public enum ARSessionRunOptions + { + /// No additional behaviour will occur when the configuration is changed. + /// @note Used to set the flag programmatically, select "Nothing" in the Unity Editor + None = 0, + + /// The session does not continue tracking from the previous configuration. + /// @note This is an iOS-only value. + ResetTracking = 1, + + /// Any anchor objects created previously are removed. + RemoveExistingAnchors = 2, + + /// Meshing is reset + RemoveExistingMesh = 4, + } +} diff --git a/Assets/ARDK/AR/ARSessionRunOptions.cs.meta b/Assets/ARDK/AR/ARSessionRunOptions.cs.meta new file mode 100644 index 0000000..d92f1f8 --- /dev/null +++ b/Assets/ARDK/AR/ARSessionRunOptions.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 9a79e150c87314f87918914fea9c3c6b +timeCreated: 1525206586 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Anchors.meta b/Assets/ARDK/AR/Anchors.meta new file mode 100644 index 0000000..c98888a --- /dev/null +++ b/Assets/ARDK/AR/Anchors.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 4feef442c9fc40819d2b50203d0e0ae4 +timeCreated: 1565641037 \ No newline at end of file diff --git a/Assets/ARDK/AR/Anchors/AnchorExtensions.cs b/Assets/ARDK/AR/Anchors/AnchorExtensions.cs new file mode 100644 index 0000000..a5170c9 --- /dev/null +++ b/Assets/ARDK/AR/Anchors/AnchorExtensions.cs @@ -0,0 +1,49 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; + +namespace Niantic.ARDK.AR.Anchors +{ + public static class AnchorExtensions + { + public static bool IsDisposed(this IARAnchor anchor) + { + return anchor.Identifier.Equals(Guid.Empty); + } + + internal static _SerializableAnchorsByType ClassifyAsSerializableAnchors(IEnumerable anchors) + { + var basicAnchors = new List<_SerializableARAnchor>(); + var planeAnchors = new List<_SerializableARPlaneAnchor>(); + var imageAnchors = new List<_SerializableARImageAnchor>(); + foreach (var anchor in anchors) + { + switch (anchor.AnchorType) + { + case AnchorType.Basic: + basicAnchors.Add(anchor._AsSerializableBasic()); + break; + + case AnchorType.Plane: + planeAnchors.Add(((IARPlaneAnchor)anchor)._AsSerializablePlane()); + break; + + case AnchorType.Image: + imageAnchors.Add(((IARImageAnchor)anchor)._AsSerializableImage()); + break; + + default: + break; + } + } + + return new _SerializableAnchorsByType + ( + basicAnchors, + planeAnchors, + imageAnchors + ); + } + } +} diff --git a/Assets/ARDK/AR/Anchors/AnchorExtensions.cs.meta b/Assets/ARDK/AR/Anchors/AnchorExtensions.cs.meta new file mode 100644 index 0000000..ba2f1af --- /dev/null +++ b/Assets/ARDK/AR/Anchors/AnchorExtensions.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 20fb9c8de6af4908bffd3e5d574403bf +timeCreated: 1643308601 \ No newline at end of file diff --git a/Assets/ARDK/AR/Anchors/AnchorType.cs b/Assets/ARDK/AR/Anchors/AnchorType.cs new file mode 100644 index 0000000..dfc2479 --- /dev/null +++ b/Assets/ARDK/AR/Anchors/AnchorType.cs @@ -0,0 +1,23 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.AR.Anchors +{ + /// Possible types for an anchor. Useful when checking if an Anchor object is actually a + /// sub-object. + public enum AnchorType + { + /// An anchor. + Basic = 0, + + /// A plane anchor. + Plane = 1, + + /// An image anchor. + /// @note This is an iOS-only value. + Image = 2, + + /// A face anchor. + /// @note Face anchors are only available in the face tracking feature branch + //Face = 3, + } +} diff --git a/Assets/ARDK/AR/Anchors/AnchorType.cs.meta b/Assets/ARDK/AR/Anchors/AnchorType.cs.meta new file mode 100644 index 0000000..e729436 --- /dev/null +++ b/Assets/ARDK/AR/Anchors/AnchorType.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c37715fc001e433f88f376d6b211fea8 +timeCreated: 1594678577 \ No newline at end of file diff --git a/Assets/ARDK/AR/Anchors/IARAnchor.cs b/Assets/ARDK/AR/Anchors/IARAnchor.cs new file mode 100644 index 0000000..4dc6fe9 --- /dev/null +++ b/Assets/ARDK/AR/Anchors/IARAnchor.cs @@ -0,0 +1,29 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using UnityEngine; + +namespace Niantic.ARDK.AR.Anchors +{ + /// An anchor is anything in the physical environment that can be tracked by the AR session. + /// @note + /// To track the position and orientation of static physical or virtual objects relative to + /// the camera, use the [IARSession.AddAnchor(transform)](@ref ARDK.AR.IARSession) method + /// to add them to your AR session. + /// \n + /// AR sessions can also detect and track [IARPlaneAnchor](@ref ARDK.AR.Anchors.IARPlaneAnchor) + /// and [IARImageAnchor](@ref ARDK.AR.Anchors.IARImageAnchor) objects if configured to do so. + public interface IARAnchor: + IDisposable + { + /// Position, rotation and scale of the anchor in the coordinate space of the AR session + /// it is being tracked in. + Matrix4x4 Transform { get; } + + /// A unique identifier representing this anchor. + Guid Identifier { get; } + + /// The type of this anchor (See AnchorType). + AnchorType AnchorType { get; } + } +} diff --git a/Assets/ARDK/AR/Anchors/IARAnchor.cs.meta b/Assets/ARDK/AR/Anchors/IARAnchor.cs.meta new file mode 100644 index 0000000..d655af6 --- /dev/null +++ b/Assets/ARDK/AR/Anchors/IARAnchor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 7d7ed70374054db6bf2b20d4f4af64e4 +timeCreated: 1594679170 \ No newline at end of file diff --git a/Assets/ARDK/AR/Anchors/IARImageAnchor.cs b/Assets/ARDK/AR/Anchors/IARImageAnchor.cs new file mode 100644 index 0000000..7e09c92 --- /dev/null +++ b/Assets/ARDK/AR/Anchors/IARImageAnchor.cs @@ -0,0 +1,19 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.AR.ReferenceImage; + +namespace Niantic.ARDK.AR.Anchors +{ + /// + /// Information about the position and orientation of an image detected in a world-tracking AR + /// session. + /// + public interface IARImageAnchor: + IARAnchor + { + /// + /// The detected image referenced by the image anchor + /// + IARReferenceImage ReferenceImage { get; } + } +} diff --git a/Assets/ARDK/AR/Anchors/IARImageAnchor.cs.meta b/Assets/ARDK/AR/Anchors/IARImageAnchor.cs.meta new file mode 100644 index 0000000..8d83082 --- /dev/null +++ b/Assets/ARDK/AR/Anchors/IARImageAnchor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 49a9b12f3905471eb405eb7288cec423 +timeCreated: 1594679531 \ No newline at end of file diff --git a/Assets/ARDK/AR/Anchors/IARPlaneAnchor.cs b/Assets/ARDK/AR/Anchors/IARPlaneAnchor.cs new file mode 100644 index 0000000..62fceee --- /dev/null +++ b/Assets/ARDK/AR/Anchors/IARPlaneAnchor.cs @@ -0,0 +1,47 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using UnityEngine; + +namespace Niantic.ARDK.AR.Anchors +{ + /// Information about the position and orientation of a real-world flat surface + /// detected in a world-tracking AR session. + /// @note When a session is run with plane estimation enabled, the Session will search and + /// automatically add anchors representing detected surfaces. + public interface IARPlaneAnchor: + IARAnchor + { + /// + /// The general orientation of the detected plane with respect to gravity. + /// + PlaneAlignment Alignment { get; } + + /// + /// Possible characterizations of real-world surfaces represented by plane anchors. + /// @note This is only available on iPhone Xs, Xr, Xs Max, with iOS 12+. + /// + PlaneClassification Classification { get; } + + /// + /// Possible states of ARKit's process for classifying plane anchors. + /// + PlaneClassificationStatus ClassificationStatus { get; } + + /// + /// The center point of the plane relative to its anchor position. + /// + Vector3 Center { get; } + + /// + /// The estimated width and length of the detected plane. + /// @remark The y-component of this vector will always be zero. + /// + Vector3 Extent { get; } + + /// + /// A coarse triangle mesh representing the general shape of the detected plane. + /// @note **May be null**. + /// + IARPlaneGeometry Geometry { get; } + } +} diff --git a/Assets/ARDK/AR/Anchors/IARPlaneAnchor.cs.meta b/Assets/ARDK/AR/Anchors/IARPlaneAnchor.cs.meta new file mode 100644 index 0000000..f1d64a4 --- /dev/null +++ b/Assets/ARDK/AR/Anchors/IARPlaneAnchor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 1b2aa348bcee484d88e93c0f29beda5a +timeCreated: 1594679612 \ No newline at end of file diff --git a/Assets/ARDK/AR/Anchors/PlaneAlignment.cs b/Assets/ARDK/AR/Anchors/PlaneAlignment.cs new file mode 100644 index 0000000..6531987 --- /dev/null +++ b/Assets/ARDK/AR/Anchors/PlaneAlignment.cs @@ -0,0 +1,22 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.AR.Anchors +{ + /// + /// Values describing possible general orientations of a detected plane with respect to gravity. + /// + /// Limit changing this enum, because it is used in comparisons with the + /// AR.Configuration.PlaneDetection enum. This rigidness is due to how these enums + /// are backed in ARKit and ARCore. + public enum PlaneAlignment + { + /// The plane's alignment is unknown + Unknown = 0, + + /// The plane is perpendicular to gravity. + Horizontal = 1, + + /// The plane is parallel to gravity. + Vertical = 2, + } +} diff --git a/Assets/ARDK/AR/Anchors/PlaneAlignment.cs.meta b/Assets/ARDK/AR/Anchors/PlaneAlignment.cs.meta new file mode 100644 index 0000000..5f47b71 --- /dev/null +++ b/Assets/ARDK/AR/Anchors/PlaneAlignment.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6976579b53514ceea987f83981e5ce59 +timeCreated: 1594678704 \ No newline at end of file diff --git a/Assets/ARDK/AR/Anchors/PlaneClassification.cs b/Assets/ARDK/AR/Anchors/PlaneClassification.cs new file mode 100644 index 0000000..5b0911b --- /dev/null +++ b/Assets/ARDK/AR/Anchors/PlaneClassification.cs @@ -0,0 +1,35 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.AR.Anchors +{ + /// + /// Values describing possible characterizations of real-world surfaces represented by plane anchors. + /// + public enum PlaneClassification + { + /// No classification is available for the plane anchor. + None = 0, + + /// The plane anchor represents a real-world wall or similar large vertical surface. + Wall = 1, + + /// The plane anchor represents a real-world floor, ground plane, or similar large + /// horizontal surface. + Floor = 2, + + /// The plane anchor represents a real-world ceiling or similar overhead horizontal surface. + Ceiling = 3, + + /// The plane anchor represents a real-world table, desk, bar, or similar flat surface. + Table = 4, + + /// The plane anchor represents a real-world chair, stool, bench or similar flat surface. + Seat = 5, + + /// The plane anchor represents a real-world door or similar vertical surface. + Door = 6, + + /// The plane anchor represents a real-world window or similar vertical surface. + Window = 7 + } +} diff --git a/Assets/ARDK/AR/Anchors/PlaneClassification.cs.meta b/Assets/ARDK/AR/Anchors/PlaneClassification.cs.meta new file mode 100644 index 0000000..ec5b0ca --- /dev/null +++ b/Assets/ARDK/AR/Anchors/PlaneClassification.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 392cd666abe340e880735b711081bee3 +timeCreated: 1594678735 \ No newline at end of file diff --git a/Assets/ARDK/AR/Anchors/PlaneClassificationStatus.cs b/Assets/ARDK/AR/Anchors/PlaneClassificationStatus.cs new file mode 100644 index 0000000..347e15a --- /dev/null +++ b/Assets/ARDK/AR/Anchors/PlaneClassificationStatus.cs @@ -0,0 +1,26 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.AR.Anchors +{ + /// + /// The status values of "NotAvailable", "Undetermined", and "Unknown" are possible reasons why the + /// plane's classification is "None." If the plane's classification is NOT None, status will be "Known" + /// + public enum PlaneClassificationStatus + { + /// ARKit cannot currently provide plane classification information because this device is + /// not an iPhone XS/XR or higher + NotAvailable = 0, + + /// ARKit has not yet produced a classification for the plane anchor. ARKit is still in the + /// process of plane classification + Undetermined = 1, + + /// ARKit has completed its classification process for the plane anchor, but the result is inconclusive. + Unknown = 2, + + /// ARKit has completed its classfication process for the plane anchor. Use getClassification() + /// to retrieve the plane's classification + Known = 3 + } +} diff --git a/Assets/ARDK/AR/Anchors/PlaneClassificationStatus.cs.meta b/Assets/ARDK/AR/Anchors/PlaneClassificationStatus.cs.meta new file mode 100644 index 0000000..5525fdc --- /dev/null +++ b/Assets/ARDK/AR/Anchors/PlaneClassificationStatus.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3768365d3d6a4be4a1fe74a99272f145 +timeCreated: 1594678784 \ No newline at end of file diff --git a/Assets/ARDK/AR/Anchors/_ARAnchorFactory.cs b/Assets/ARDK/AR/Anchors/_ARAnchorFactory.cs new file mode 100644 index 0000000..9b9c2a6 --- /dev/null +++ b/Assets/ARDK/AR/Anchors/_ARAnchorFactory.cs @@ -0,0 +1,142 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +#if UNITY_STANDALONE_OSX || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_WIN +#define UNITY_STANDALONE_DESKTOP +#endif + +using System; +using System.ComponentModel; +using System.Runtime.InteropServices; + +using Niantic.ARDK.Internals; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Anchors +{ + internal static class _ARAnchorFactory + { + internal static IARAnchor _Create(Matrix4x4 transform) + { + return _CreateForPlatform(transform); + } + + private static IARAnchor _CreateForPlatform(Matrix4x4 transform) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + var nativeTransform = _Convert.Matrix4x4ToInternalArray(NARConversions.FromUnityToNAR(transform)); + + var nativeHandle = _NARAnchor_Init(nativeTransform); + if (nativeHandle == IntPtr.Zero) + throw new InvalidOperationException("Unable to create anchor."); + + ARLog._DebugFormat + ( + "Successfully created a new native ARAnchor with handle: {0}", + false, + nativeHandle + ); + + return _FromNativeHandle(nativeHandle); + } +#pragma warning disable 0162 + else + { + var identifier = Guid.NewGuid(); + + ARLog._DebugFormat + ( + "Creating new _SerializableARBasicAnchor with identifier: {0}", + false, + identifier + ); + + return new _SerializableARBasicAnchor(transform, identifier); + } +#pragma warning restore 0162 + } + + private static _WeakValueDictionary _allAnchors = new _WeakValueDictionary(); + + internal static _NativeARAnchor _FromNativeHandle(IntPtr nativeHandle) + { + _StaticMemberValidator._CollectionIsEmptyWhenScopeEnds(() => _allAnchors); + + if (nativeHandle == IntPtr.Zero) + throw new ArgumentException("nativeHandle"); + + var cppAddress = _GetCppAddress(nativeHandle); + + var result = _allAnchors.TryGetValue(cppAddress); + if (result != null) + { + // We already have an existing Anchor for the same C++ address. + // We need to release the nativeHandle, as this is a different handle for the same object. + _NativeARAnchor._ReleaseImmediate(nativeHandle); + + return result; + } + + result = _allAnchors.GetOrAdd(cppAddress, (_) => _CreateFromHandle(nativeHandle)); + + // If an existing anchor is found (that is, got added just after our TryGetValue but + // before GetOrAdd) we need to release the nativeHandle as it is a duplicate to the same + // C++ object. + if (result._NativeHandle != nativeHandle) + _NativeARAnchor._ReleaseImmediate(nativeHandle); + + return result; + } + + [ThreadStatic] + internal static AnchorType _testOnly_DefaultAnchorType; + + private static _NativeARAnchor _CreateFromHandle(IntPtr nativeHandle) + { + AnchorType anchorType; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + anchorType = (AnchorType)_NARAnchor_GetAnchorType(nativeHandle); + #pragma warning disable 0162 + else + anchorType = _testOnly_DefaultAnchorType; + #pragma warning restore 0162 + + switch (anchorType) + { + case AnchorType.Basic: return new _NativeARBasicAnchor(nativeHandle); + case AnchorType.Image: return new _NativeARImageAnchor(nativeHandle); + case AnchorType.Plane: return new _NativeARPlaneAnchor(nativeHandle); + } + + throw new InvalidEnumArgumentException("Unknown AnchorType value: " + anchorType); + } + + internal static void _RemoveFromCache(_NativeARAnchor anchor) + { + _allAnchors.Remove(_GetCppAddress(anchor._NativeHandle)); + } + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NARAnchor_Init(float[] transform); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern UInt64 _NARAnchor_GetAnchorType(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NARAnchor_GetCppAddress(IntPtr nativeHandle); + + private static IntPtr _GetCppAddress(IntPtr nativeHandle) + { +#pragma warning disable 0162 + if (NativeAccess.Mode != NativeAccess.ModeType.Native) + return nativeHandle; +#pragma warning restore 0162 + + return _NARAnchor_GetCppAddress(nativeHandle); + } + } +} diff --git a/Assets/ARDK/AR/Anchors/_ARAnchorFactory.cs.meta b/Assets/ARDK/AR/Anchors/_ARAnchorFactory.cs.meta new file mode 100644 index 0000000..918d95a --- /dev/null +++ b/Assets/ARDK/AR/Anchors/_ARAnchorFactory.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: fa3b1b8abc094ef08d24cca0e8b46cb1 +timeCreated: 1594701746 \ No newline at end of file diff --git a/Assets/ARDK/AR/Anchors/_NativeARAnchor.cs b/Assets/ARDK/AR/Anchors/_NativeARAnchor.cs new file mode 100644 index 0000000..beb54b1 --- /dev/null +++ b/Assets/ARDK/AR/Anchors/_NativeARAnchor.cs @@ -0,0 +1,156 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +using Niantic.ARDK.Internals; +using Niantic.ARDK.Utilities; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Anchors +{ + internal abstract class _NativeARAnchor: + IARAnchor + { + static _NativeARAnchor() + { + Platform.Init(); + } + + internal static void _ReleaseImmediate(IntPtr nativeHandle) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + if (nativeHandle != IntPtr.Zero) + _NARAnchor_Release(nativeHandle); + } + #pragma warning disable 0162 + else if (NativeAccess.Mode == NativeAccess.ModeType.Testing) + { + _TestingShim.ReleasedHandles.Add(nativeHandle); + } + #pragma warning restore 0162 + } + + internal static Guid _GetIdentifier(IntPtr nativeHandle) + { + Guid result; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + _NARAnchor_GetIdentifier(nativeHandle, out result); + } + #pragma warning disable 0162 + else + { + ulong handleNumber = (ulong)nativeHandle; + var bytes = new byte[16]; + bytes[0] = (byte)handleNumber; + bytes[1] = (byte)(handleNumber >> 8); + bytes[2] = (byte)(handleNumber >> 16); + bytes[3] = (byte)(handleNumber >> 24); + bytes[4] = (byte)(handleNumber >> 32); + bytes[5] = (byte)(handleNumber >> 40); + bytes[6] = (byte)(handleNumber >> 48); + bytes[7] = (byte)(handleNumber >> 56); + result = new Guid(bytes); + } + #pragma warning restore 0162 + + return result; + } + + internal _NativeARAnchor(IntPtr nativeHandle) + { + if (nativeHandle == IntPtr.Zero) + throw new ArgumentException("nativeHandle can't be Zero.", nameof(nativeHandle)); + + _nativeHandle = nativeHandle; + + GC.AddMemoryPressure(MemoryPressure); + } + + ~_NativeARAnchor() + { + _ReleaseImmediate(_nativeHandle); + GC.RemoveMemoryPressure(MemoryPressure); + } + + public void Dispose() + { + GC.SuppressFinalize(this); + + var nativeHandle = _nativeHandle; + if (nativeHandle != IntPtr.Zero) + { + _ARAnchorFactory._RemoveFromCache(this); + + _nativeHandle = IntPtr.Zero; + + _ReleaseImmediate(nativeHandle); + GC.RemoveMemoryPressure(MemoryPressure); + } + } + + private IntPtr _nativeHandle; + internal IntPtr _NativeHandle + { + get { return _nativeHandle; } + } + + public abstract AnchorType AnchorType { get; } + + // Used to inform the C# GC that there is managed memory held by this object + protected virtual long MemoryPressure + { + get { return (16L * 4L) + (16L * 1L); } + } + + public Matrix4x4 Transform + { + get + { + var nativeTransform = new float[16]; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARAnchor_GetTransform(_nativeHandle, nativeTransform); + #pragma warning disable 0162 + else if (NativeAccess.Mode == NativeAccess.ModeType.Testing) + nativeTransform = _TestingShim.RawTransform; + #pragma warning restore 0162 + + return NARConversions.FromNARToUnity(_Convert.InternalToMatrix4x4(nativeTransform)); + } + } + + public Guid Identifier + { + get + { + return _GetIdentifier(_nativeHandle); + } + } + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARAnchor_Release(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARAnchor_GetIdentifier(IntPtr nativeHandle, out Guid identifier); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARAnchor_GetTransform(IntPtr nativeHandle, float[] outTransform); + + internal static class _TestingShim + { + // This stores all native handles that would normally be freed by passing them to + // _NARAnchor_Release. + public static List ReleasedHandles = new List(); + + // All anchors will act as if _NARAnchor_GetTransform output this transform. The actual value + // of Transform will be different based on the coordinate transform and the scale. + public static float[] RawTransform = new float[16]; + } + } +} diff --git a/Assets/ARDK/AR/Anchors/_NativeARAnchor.cs.meta b/Assets/ARDK/AR/Anchors/_NativeARAnchor.cs.meta new file mode 100644 index 0000000..e4f3139 --- /dev/null +++ b/Assets/ARDK/AR/Anchors/_NativeARAnchor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 25a20c5f11894083a895f39eb6075266 +timeCreated: 1594682569 \ No newline at end of file diff --git a/Assets/ARDK/AR/Anchors/_NativeARBasicAnchor.cs b/Assets/ARDK/AR/Anchors/_NativeARBasicAnchor.cs new file mode 100644 index 0000000..ebb7b87 --- /dev/null +++ b/Assets/ARDK/AR/Anchors/_NativeARBasicAnchor.cs @@ -0,0 +1,21 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +namespace Niantic.ARDK.AR.Anchors +{ + internal sealed class _NativeARBasicAnchor: + _NativeARAnchor + { + public _NativeARBasicAnchor(IntPtr nativeHandle): + base(nativeHandle) + { + } + + public override AnchorType AnchorType + { + get => AnchorType.Basic; + } + } +} + diff --git a/Assets/ARDK/AR/Anchors/_NativeARBasicAnchor.cs.meta b/Assets/ARDK/AR/Anchors/_NativeARBasicAnchor.cs.meta new file mode 100644 index 0000000..88a020e --- /dev/null +++ b/Assets/ARDK/AR/Anchors/_NativeARBasicAnchor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5dde313a558446cd81ac198ff31a97f2 +timeCreated: 1594683855 \ No newline at end of file diff --git a/Assets/ARDK/AR/Anchors/_NativeARImageAnchor.cs b/Assets/ARDK/AR/Anchors/_NativeARImageAnchor.cs new file mode 100644 index 0000000..b67a3e7 --- /dev/null +++ b/Assets/ARDK/AR/Anchors/_NativeARImageAnchor.cs @@ -0,0 +1,47 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Runtime.InteropServices; + +using Niantic.ARDK.AR.ReferenceImage; +using Niantic.ARDK.Internals; + +namespace Niantic.ARDK.AR.Anchors +{ + internal sealed class _NativeARImageAnchor: + _NativeARAnchor, + IARImageAnchor + { + public _NativeARImageAnchor(IntPtr nativeHandle): + base(nativeHandle) + { + } + + public override AnchorType AnchorType + { + get { return AnchorType.Image; } + } + + internal _NativeARReferenceImage ReferenceImage + { + get + { + #pragma warning disable 0162 + if (NativeAccess.Mode != NativeAccess.ModeType.Native) + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + + var nativeHandle = _NARImageAnchor_GetReferenceImage(_NativeHandle); + return _NativeARReferenceImage._FromNativeHandle(nativeHandle); + } + } + + IARReferenceImage IARImageAnchor.ReferenceImage + { + get { return ReferenceImage; } + } + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NARImageAnchor_GetReferenceImage(IntPtr nativeHandle); + } +} diff --git a/Assets/ARDK/AR/Anchors/_NativeARImageAnchor.cs.meta b/Assets/ARDK/AR/Anchors/_NativeARImageAnchor.cs.meta new file mode 100644 index 0000000..2b0df30 --- /dev/null +++ b/Assets/ARDK/AR/Anchors/_NativeARImageAnchor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f91b8ada021544ea9d5e191d4df7874a +timeCreated: 1594684623 \ No newline at end of file diff --git a/Assets/ARDK/AR/Anchors/_NativeARPlaneAnchor.cs b/Assets/ARDK/AR/Anchors/_NativeARPlaneAnchor.cs new file mode 100644 index 0000000..0ea7b83 --- /dev/null +++ b/Assets/ARDK/AR/Anchors/_NativeARPlaneAnchor.cs @@ -0,0 +1,153 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Runtime.InteropServices; + +using Niantic.ARDK.AR.PlaneGeometry; +using Niantic.ARDK.Internals; +using Niantic.ARDK.Utilities; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Anchors +{ + internal sealed class _NativeARPlaneAnchor: + _NativeARAnchor, + IARPlaneAnchor + { + public _NativeARPlaneAnchor(IntPtr nativeHandle): + base(nativeHandle) + { + } + + protected override long MemoryPressure + { + get { return base.MemoryPressure + (1L * 8L) + (3L * 4L) + (3L * 4L); } + } + + public override AnchorType AnchorType + { + get { return AnchorType.Plane; } + } + + public PlaneAlignment Alignment + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return (PlaneAlignment)_NARPlaneAnchor_GetAlignment(_NativeHandle); + #pragma warning disable 0162 + else + return PlaneAlignment.Unknown; + #pragma warning restore 0162 + } + } + + public PlaneClassification Classification + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return (PlaneClassification)_NARPlaneAnchor_GetClassification(_NativeHandle); + #pragma warning disable 0162 + else + return PlaneClassification.None; + #pragma warning restore 0162 + } + } + + public PlaneClassificationStatus ClassificationStatus + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return (PlaneClassificationStatus)_NARPlaneAnchor_GetClassificationStatus(_NativeHandle); + #pragma warning disable 0162 + else + return PlaneClassificationStatus.NotAvailable; + #pragma warning restore 0162 + } + } + + public Vector3 Center + { + get + { + var nativeCenter = new float[3]; + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARPlaneAnchor_GetCenter(_NativeHandle, nativeCenter); + + var center = + new Vector3 + ( + nativeCenter[0], + nativeCenter[1], + nativeCenter[2] + ); + + return NARConversions.FromNARToUnity(center); + } + } + + public Vector3 Extent + { + get + { + var nativeExtent = new float[3]; + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARPlaneAnchor_GetExtent(_NativeHandle, nativeExtent); + + return + new Vector3 + ( + nativeExtent[0], + nativeExtent[1], + nativeExtent[2] + ); + } + } + + internal _NativeARPlaneGeometry Geometry + { + get + { + IntPtr geometryHandle = IntPtr.Zero; + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + geometryHandle = _NARPlaneAnchor_GetGeometry(_NativeHandle); + + if (geometryHandle == IntPtr.Zero) + return null; + + return new _NativeARPlaneGeometry(geometryHandle); + } + } + + IARPlaneGeometry IARPlaneAnchor.Geometry + { + get { return Geometry; } + } + + public override string ToString() + { + return _NativeHandle.ToString(); + } + + [DllImport(_ARDKLibrary.libraryName)] + private static extern UInt64 _NARPlaneAnchor_GetAlignment(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern UInt64 _NARPlaneAnchor_GetClassification(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern UInt64 _NARPlaneAnchor_GetClassificationStatus(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARPlaneAnchor_GetCenter(IntPtr nativeHandle, float[] outCenter); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARPlaneAnchor_GetExtent(IntPtr nativeHandle, float[] outExtent); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NARPlaneAnchor_GetGeometry(IntPtr nativeHandle); + } +} diff --git a/Assets/ARDK/AR/Anchors/_NativeARPlaneAnchor.cs.meta b/Assets/ARDK/AR/Anchors/_NativeARPlaneAnchor.cs.meta new file mode 100644 index 0000000..3a8ecd1 --- /dev/null +++ b/Assets/ARDK/AR/Anchors/_NativeARPlaneAnchor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: cb5f4ebd3ac34cf5be432e202c78fbe8 +timeCreated: 1594684923 \ No newline at end of file diff --git a/Assets/ARDK/AR/Anchors/_SerializableARAnchor.cs b/Assets/ARDK/AR/Anchors/_SerializableARAnchor.cs new file mode 100644 index 0000000..5615358 --- /dev/null +++ b/Assets/ARDK/AR/Anchors/_SerializableARAnchor.cs @@ -0,0 +1,31 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Anchors +{ + [Serializable] + internal abstract class _SerializableARAnchor: + IARAnchor + { + public _SerializableARAnchor(Matrix4x4 transform, Guid identifier) + { + Transform = transform; + Identifier = identifier; + } + + public Matrix4x4 Transform { get; internal set; } + public Guid Identifier { get; private set; } + + public abstract AnchorType AnchorType { get; } + + public abstract _SerializableARAnchor Copy(); + + void IDisposable.Dispose() + { + // Do nothing. This implementation of IARAnchor is fully managed. + } + } +} diff --git a/Assets/ARDK/AR/Anchors/_SerializableARAnchor.cs.meta b/Assets/ARDK/AR/Anchors/_SerializableARAnchor.cs.meta new file mode 100644 index 0000000..6788b22 --- /dev/null +++ b/Assets/ARDK/AR/Anchors/_SerializableARAnchor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 317b2aede58a439fb93ab37a44a4c47a +timeCreated: 1594680225 \ No newline at end of file diff --git a/Assets/ARDK/AR/Anchors/_SerializableARAnchorFactory.cs b/Assets/ARDK/AR/Anchors/_SerializableARAnchorFactory.cs new file mode 100644 index 0000000..38eaf6e --- /dev/null +++ b/Assets/ARDK/AR/Anchors/_SerializableARAnchorFactory.cs @@ -0,0 +1,83 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.AR.ReferenceImage; + +namespace Niantic.ARDK.AR.Anchors +{ + internal static class _SerializableARAnchorFactory + { + internal static _SerializableARAnchor _AsSerializable(this IARAnchor source) + { + if (source == null) + return null; + + var anchorType = source.AnchorType; + switch (anchorType) + { + case AnchorType.Basic: + return _AsSerializableBasic(source); + + case AnchorType.Image: + return _AsSerializableImage((IARImageAnchor)source); + + case AnchorType.Plane: + return _AsSerializablePlane((IARPlaneAnchor)source); + } + + throw new ArgumentException("Unknown anchorType: " + anchorType); + } + + internal static _SerializableARBasicAnchor _AsSerializableBasic(this IARAnchor source) + { + if (source is _SerializableARBasicAnchor possibleResult) + return possibleResult; + + var result = + new _SerializableARBasicAnchor + ( + source.Transform, + source.Identifier + ); + + return result; + } + + internal static _SerializableARImageAnchor _AsSerializableImage(this IARImageAnchor source) + { + if (source is _SerializableARImageAnchor possibleResult) + return possibleResult; + + var result = + new _SerializableARImageAnchor + ( + source.Transform, + source.Identifier, + source.ReferenceImage._AsSerializable() + ); + + return result; + } + + internal static _SerializableARPlaneAnchor _AsSerializablePlane(this IARPlaneAnchor source) + { + if (source is _SerializableARPlaneAnchor possibleResult) + return possibleResult; + + var result = + new _SerializableARPlaneAnchor + ( + source.Transform, + source.Identifier, + source.Alignment, + source.Classification, + source.ClassificationStatus, + source.Center, + source.Extent + ); + + return result; + } + } +} diff --git a/Assets/ARDK/AR/Anchors/_SerializableARAnchorFactory.cs.meta b/Assets/ARDK/AR/Anchors/_SerializableARAnchorFactory.cs.meta new file mode 100644 index 0000000..3b9fe3d --- /dev/null +++ b/Assets/ARDK/AR/Anchors/_SerializableARAnchorFactory.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a7523c6daf15468ea1ce5b526757bf4f +timeCreated: 1594707524 \ No newline at end of file diff --git a/Assets/ARDK/AR/Anchors/_SerializableARBasicAnchor.cs b/Assets/ARDK/AR/Anchors/_SerializableARBasicAnchor.cs new file mode 100644 index 0000000..e0590a6 --- /dev/null +++ b/Assets/ARDK/AR/Anchors/_SerializableARBasicAnchor.cs @@ -0,0 +1,32 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Anchors +{ + [Serializable] + internal sealed class _SerializableARBasicAnchor: + _SerializableARAnchor + { + public _SerializableARBasicAnchor + ( + Matrix4x4 transform, + Guid identifier + ): + base(transform, identifier) + { + } + + public override AnchorType AnchorType + { + get => AnchorType.Basic; + } + + public override _SerializableARAnchor Copy() + { + return new _SerializableARBasicAnchor(Transform, Identifier); + } + } +} diff --git a/Assets/ARDK/AR/Anchors/_SerializableARBasicAnchor.cs.meta b/Assets/ARDK/AR/Anchors/_SerializableARBasicAnchor.cs.meta new file mode 100644 index 0000000..2681cd5 --- /dev/null +++ b/Assets/ARDK/AR/Anchors/_SerializableARBasicAnchor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: fff7840045db4637932361276f5d186b +timeCreated: 1594681952 \ No newline at end of file diff --git a/Assets/ARDK/AR/Anchors/_SerializableARImageAnchor.cs b/Assets/ARDK/AR/Anchors/_SerializableARImageAnchor.cs new file mode 100644 index 0000000..8e7f217 --- /dev/null +++ b/Assets/ARDK/AR/Anchors/_SerializableARImageAnchor.cs @@ -0,0 +1,42 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using Niantic.ARDK.AR.ReferenceImage; +using UnityEngine; + +namespace Niantic.ARDK.AR.Anchors +{ + [Serializable] + internal sealed class _SerializableARImageAnchor: + _SerializableARAnchor, + IARImageAnchor + { + public _SerializableARImageAnchor + ( + Matrix4x4 transform, + Guid identifier, + _SerializableARReferenceImage referenceImage + ): + base(transform, identifier) + { + ReferenceImage = referenceImage; + } + + public override AnchorType AnchorType + { + get { return AnchorType.Image; } + } + + public override _SerializableARAnchor Copy() + { + return new _SerializableARImageAnchor(Transform, Identifier, ReferenceImage); + } + + internal _SerializableARReferenceImage ReferenceImage { get; private set; } + + IARReferenceImage IARImageAnchor.ReferenceImage + { + get { return ReferenceImage; } + } + } +} diff --git a/Assets/ARDK/AR/Anchors/_SerializableARImageAnchor.cs.meta b/Assets/ARDK/AR/Anchors/_SerializableARImageAnchor.cs.meta new file mode 100644 index 0000000..5922b18 --- /dev/null +++ b/Assets/ARDK/AR/Anchors/_SerializableARImageAnchor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a7322336aa7944e4ada9616112990074 +timeCreated: 1594680746 \ No newline at end of file diff --git a/Assets/ARDK/AR/Anchors/_SerializableARPlaneAnchor.cs b/Assets/ARDK/AR/Anchors/_SerializableARPlaneAnchor.cs new file mode 100644 index 0000000..30a924c --- /dev/null +++ b/Assets/ARDK/AR/Anchors/_SerializableARPlaneAnchor.cs @@ -0,0 +1,68 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using Niantic.ARDK.AR.PlaneGeometry; +using UnityEngine; + +namespace Niantic.ARDK.AR.Anchors +{ + [Serializable] + internal sealed class _SerializableARPlaneAnchor: + _SerializableARAnchor, + IARPlaneAnchor + { + public _SerializableARPlaneAnchor + ( + Matrix4x4 transform, + Guid identifier, + PlaneAlignment alignment, + PlaneClassification classification, + PlaneClassificationStatus classificationStatus, + Vector3 center, + Vector3 extent + ): + base(transform, identifier) + { + Alignment = alignment; + Classification = classification; + ClassificationStatus = classificationStatus; + Center = center; + Extent = extent; + } + + public override AnchorType AnchorType + { + get { return AnchorType.Plane; } + } + + public override _SerializableARAnchor Copy() + { + return + new _SerializableARPlaneAnchor + ( + Transform, + Identifier, + Alignment, + Classification, + ClassificationStatus, + Center, + Extent + ); + } + + public PlaneAlignment Alignment { get; internal set; } + public PlaneClassification Classification { get; internal set; } + public PlaneClassificationStatus ClassificationStatus { get; internal set; } + public Vector3 Center { get; internal set; } + public Vector3 Extent { get; internal set; } + public _SerializableARPlaneGeometry Geometry { get; internal set; } + + IARPlaneGeometry IARPlaneAnchor.Geometry + { + get + { + return Geometry; + } + } + } +} diff --git a/Assets/ARDK/AR/Anchors/_SerializableARPlaneAnchor.cs.meta b/Assets/ARDK/AR/Anchors/_SerializableARPlaneAnchor.cs.meta new file mode 100644 index 0000000..4a6d7d0 --- /dev/null +++ b/Assets/ARDK/AR/Anchors/_SerializableARPlaneAnchor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 54032cca6321453980e3943b90b264eb +timeCreated: 1594680923 \ No newline at end of file diff --git a/Assets/ARDK/AR/Anchors/_SerializableAnchorsByType.cs b/Assets/ARDK/AR/Anchors/_SerializableAnchorsByType.cs new file mode 100644 index 0000000..4809614 --- /dev/null +++ b/Assets/ARDK/AR/Anchors/_SerializableAnchorsByType.cs @@ -0,0 +1,20 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.Collections.Generic; + +namespace Niantic.ARDK.AR.Anchors +{ + internal class _SerializableAnchorsByType + { + public _SerializableAnchorsByType(List<_SerializableARAnchor> basicAnchors, List<_SerializableARPlaneAnchor> planeAnchors, List<_SerializableARImageAnchor> imageAnchors) + { + BasicAnchors = basicAnchors; + PlaneAnchors = planeAnchors; + ImageAnchors = imageAnchors; + } + + public List<_SerializableARAnchor> BasicAnchors { get; } + public List<_SerializableARPlaneAnchor> PlaneAnchors { get; } + public List<_SerializableARImageAnchor> ImageAnchors { get; } + } +} diff --git a/Assets/ARDK/AR/Anchors/_SerializableAnchorsByType.cs.meta b/Assets/ARDK/AR/Anchors/_SerializableAnchorsByType.cs.meta new file mode 100644 index 0000000..b6932d4 --- /dev/null +++ b/Assets/ARDK/AR/Anchors/_SerializableAnchorsByType.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 73f76d96cf154657851c7ece752d9c21 +timeCreated: 1643310417 \ No newline at end of file diff --git a/Assets/ARDK/AR/Awareness.meta b/Assets/ARDK/AR/Awareness.meta new file mode 100644 index 0000000..be3eb39 --- /dev/null +++ b/Assets/ARDK/AR/Awareness.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e1252ab469a4407cabc6734cf9f2470b +timeCreated: 1609792783 \ No newline at end of file diff --git a/Assets/ARDK/AR/Awareness/AwarenessParameters.cs b/Assets/ARDK/AR/Awareness/AwarenessParameters.cs new file mode 100644 index 0000000..3f4dc9b --- /dev/null +++ b/Assets/ARDK/AR/Awareness/AwarenessParameters.cs @@ -0,0 +1,31 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using UnityEngine; + +namespace Niantic.ARDK.AR.Awareness +{ + /// Parameters that apply to awareness buffers and features + public static class AwarenessParameters + { + /// This value sets the normalized distance of the back-projection plane. Lower values result + /// in depths more accurate for closer pixels, but pixels further away will move faster + /// than they should. Use 0.5f if your subject in the scene is always closer than ~2 meters + /// from the device, and use 1.0f if your subject is further away most of the time. + public const float DefaultBackProjectionDistance = 0.9f; + + /// The near clipping plane used for interpolating awareness buffers. + public const float DefaultNear = 0.2f; + + /// The far clipping plane used for interpolating awareness buffers. + public const float DefaultFar = 100.0f; + + /// ZBufferParams for awareness buffers used in + /// the context of temporal warping (interpolation). + public static Vector4 ZBufferParams = new Vector4 + ( + x: 1.0f - DefaultFar / DefaultNear, + y: DefaultFar / DefaultNear, + z: (1.0f - DefaultFar / DefaultNear) / DefaultFar, + w: (DefaultFar / DefaultNear) / DefaultFar + ); + } +} diff --git a/Assets/ARDK/AR/Awareness/AwarenessParameters.cs.meta b/Assets/ARDK/AR/Awareness/AwarenessParameters.cs.meta new file mode 100644 index 0000000..8dfe4b7 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/AwarenessParameters.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 71d7502a4a1948eb9a9b0a5f8bcd61d0 +timeCreated: 1630433086 \ No newline at end of file diff --git a/Assets/ARDK/AR/Awareness/AwarenessUtils.cs b/Assets/ARDK/AR/Awareness/AwarenessUtils.cs new file mode 100644 index 0000000..bf028a0 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/AwarenessUtils.cs @@ -0,0 +1,60 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Awareness +{ + /// A collection of utility methods for working with contextual awareness buffers. + public static class AwarenessUtils + { + /// Converts pixel coordinates from the raw awareness buffer's + /// coordinate frame to viewport pixel coordinates. + /// @param processor Reference to the context awareness processor. + /// @param x Awareness buffer pixel position on the x axis. + /// @param y Awareness buffer pixel position on the y axis. + /// @returns Pixel coordinates on the viewport. + public static Vector2Int FromBufferToScreenPosition + ( + AwarenessBufferProcessor processor, + int x, + int y + ) where TBuffer : class, IDisposable, IAwarenessBuffer + { + // Acquire the buffer resolution + var buffer = processor.AwarenessBuffer; + var bufferWidth = buffer.Width; + var bufferHeight = buffer.Height; + + // Acquire the viewport resolution + var viewport = processor.CurrentViewportResolution; + var viewWidth = viewport.x; + var viewHeight = viewport.y; + + // The sampler transform takes from viewport to buffer, + // so we need to invert it to go the other way around + var transform = processor.SamplerTransform.inverse; + + // Get normalized buffer coordinates + var uv = new Vector4 + ( + Mathf.Clamp((float)x / bufferWidth, 0.0f, 1.0f), + Mathf.Clamp((float)y / bufferHeight, 0.0f, 1.0f), + 1.0f, + 1.0f + ); + + // Apply transform + var st = transform * uv; + var sx = st.x / st.z; + var sy = st.y / st.z; + + // Scale result to viewport + return new Vector2Int + ( + x: Mathf.Clamp(Mathf.RoundToInt(sx * viewWidth - 0.5f), 0, viewWidth - 1), + y: Mathf.Clamp(Mathf.RoundToInt(sy * viewHeight - 0.5f), 0, viewHeight - 1) + ); + } + } +} diff --git a/Assets/ARDK/AR/Awareness/AwarenessUtils.cs.meta b/Assets/ARDK/AR/Awareness/AwarenessUtils.cs.meta new file mode 100644 index 0000000..671eedd --- /dev/null +++ b/Assets/ARDK/AR/Awareness/AwarenessUtils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 35270f940564349c2a747dfd173af2a3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Awareness/Depth.meta b/Assets/ARDK/AR/Awareness/Depth.meta new file mode 100644 index 0000000..9cab6c6 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3886e277cfe724d64b0b6869fc2226e7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Awareness/Depth/DepthProvider.meta b/Assets/ARDK/AR/Awareness/Depth/DepthProvider.meta new file mode 100644 index 0000000..4e90058 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/DepthProvider.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9a0949c9b4754030ae080f344cb4a556 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Awareness/Depth/DepthProvider/DepthBufferProcessor.cs b/Assets/ARDK/AR/Awareness/Depth/DepthProvider/DepthBufferProcessor.cs new file mode 100644 index 0000000..d934647 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/DepthProvider/DepthBufferProcessor.cs @@ -0,0 +1,229 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using Niantic.ARDK.AR.ARSessionEventArgs; +using Niantic.ARDK.Rendering; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Awareness.Depth +{ + public class DepthBufferProcessor: + AwarenessBufferProcessor, + IDepthBufferProcessor + { + // The currently active AR session + private IARSession _session; + + // The render target descriptor used to determine the viewport resolution + private RenderTarget _viewport; + + #region Public API + + /// Allocates a new depth buffer processor. By default, the + /// awareness buffer will be fit to the main camera's viewport. + public DepthBufferProcessor() + { + _viewport = UnityEngine.Camera.main; + ARSessionFactory.SessionInitialized += OnARSessionInitialized; + } + + /// Allocates a new depth buffer processor. + /// @param viewport Determines the target viewport to fit the awareness buffer to. + public DepthBufferProcessor(RenderTarget viewport) + { + _viewport = viewport; + ARSessionFactory.SessionInitialized += OnARSessionInitialized; + } + + public float MinDepth + { + get => AwarenessBuffer?.NearDistance ?? float.PositiveInfinity; + } + + public float MaxDepth + { + get => AwarenessBuffer?.FarDistance ?? float.PositiveInfinity; + } + + /// Assigns a new render target descriptor for the depth processor. + /// The render target defines the viewport attributes to correctly + /// fit the depth buffer. + public void AssignViewport(RenderTarget target) + { + _viewport = target; + } + + /// + public float GetDepth(int viewportX, int viewportY) + { + var depthBuffer = AwarenessBuffer; + if (depthBuffer == null) + return float.PositiveInfinity; + + var x = viewportX + 0.5f; + var y = viewportY + 0.5f; + var resolution = _viewport.GetResolution(RenderTarget.ScreenOrientation); + var uv = new Vector4(x / resolution.width, y / resolution.height, 1.0f, 1.0f); + + // Sample the depth buffer + return depthBuffer.Sample(uv, SamplerTransform); + } + + /// + public float GetDistance(int viewportX, int viewportY) + { + var depthBuffer = AwarenessBuffer; + if (depthBuffer == null) + return float.PositiveInfinity; + + var x = viewportX + 0.5f; + var y = viewportY + 0.5f; + var resolution = _viewport.GetResolution(RenderTarget.ScreenOrientation); + var uv = new Vector4(x / resolution.width, y / resolution.height, 1.0f, 1.0f); + + // Sample the depth buffer + var depth = depthBuffer.Sample(uv, SamplerTransform); + + // Retrieve point in camera space + var pointRelativeToCamera = depth * BackProjectionTransform.MultiplyPoint(uv); + + // Calculate distance + return pointRelativeToCamera.magnitude; + } + + /// + public Vector3 GetWorldPosition(int viewportX, int viewportY) + { + var depthBuffer = AwarenessBuffer; + if (depthBuffer == null) + return Vector3.zero; + + var x = viewportX + 0.5f; + var y = viewportY + 0.5f; + var resolution = _viewport.GetResolution(RenderTarget.ScreenOrientation); + var uv = new Vector4(x / resolution.width, y / resolution.height, 1.0f, 1.0f); + + // Sample the depth buffer + // The sampler transform may contain re-projection. We do this because + // we need the depth value at the pixel predicted with interpolation. + var depth = depthBuffer.Sample(uv, SamplerTransform); + + // Retrieve point in camera space + var pointRelativeToCamera = depth * BackProjectionTransform.MultiplyPoint(uv); + + // Transform to world coordinates + return CameraToWorldTransform.MultiplyPoint(pointRelativeToCamera); + } + + /// + public Vector3 GetSurfaceNormal(int viewportX, int viewportY) + { + var depthBuffer = AwarenessBuffer; + if (depthBuffer == null) + return Vector3.up; + + var resolution = _viewport.GetResolution(RenderTarget.ScreenOrientation); + var viewportMax = Mathf.Max(resolution.width, resolution.height); + var bufferMax = Mathf.Max((int)depthBuffer.Width, (int)depthBuffer.Height); + var viewportDelta = Mathf.CeilToInt((float)viewportMax / bufferMax) + 1; + + // TODO: calculate normals without back-projection + var a = GetWorldPosition(viewportX, viewportY); + var b = GetWorldPosition(viewportX + viewportDelta, viewportY); + var c = GetWorldPosition(viewportX, viewportY + viewportDelta); + + return Vector3.Cross(a - b, c - a).normalized; + } + + public void CopyToAlignedTextureARGB32(ref Texture2D texture, ScreenOrientation orientation) + { + // Get a typed buffer + IDepthBuffer depthBuffer = AwarenessBuffer; + float max = depthBuffer.FarDistance; + float min = depthBuffer.NearDistance; + + // Acquire the affine transform for the buffer + var transform = SamplerTransform; + + // Call base method + CreateOrUpdateTextureARGB32 + ( + ref texture, + orientation, + + // The sampler function needs to be defined such that given a destination + // texture coordinate, what color needs to be written to that position? + sampler: uv => + { + // Sample raw depth from the buffer + var depth = depthBuffer.Sample(uv, transform); + + // Normalize depth + var val = (depth - min) / (max - min); + + // Copy to value to color channels + return new Color(val, val, val, 1.0f); + } + ); + } + + public void CopyToAlignedTextureRFloat(ref Texture2D texture, ScreenOrientation orientation) + { + // Get a typed buffer + IDepthBuffer depthBuffer = AwarenessBuffer; + + // Acquire the affine transform for the buffer + var transform = SamplerTransform; + + // Call base method + CreateOrUpdateTextureRFloat + ( + ref texture, + orientation, + + // The sampler function needs to be defined such that given a destination + // texture coordinate, what value needs to be written to that position? + sampler: uv => depthBuffer.Sample(uv, transform) + ); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + ARSessionFactory.SessionInitialized -= OnARSessionInitialized; + if (_session != null) + _session.FrameUpdated -= OnFrameUpdated; + } + + #endregion + + #region Implementation + + private void OnARSessionInitialized(AnyARSessionInitializedArgs args) + { + if (_session != null) + _session.FrameUpdated -= OnFrameUpdated; + + _session = args.Session; + _session.FrameUpdated += OnFrameUpdated; + } + + private void OnFrameUpdated(FrameUpdatedArgs args) + { + var frame = args.Frame; + if (frame == null) + return; + + var orientation = RenderTarget.ScreenOrientation; + + _ProcessFrame + ( + frame, + buffer: frame.Depth, + targetResolution: _viewport.GetResolution(forOrientation: orientation), + targetOrientation: orientation + ); + } + + #endregion + } +} \ No newline at end of file diff --git a/Assets/ARDK/AR/Awareness/Depth/DepthProvider/DepthBufferProcessor.cs.meta b/Assets/ARDK/AR/Awareness/Depth/DepthProvider/DepthBufferProcessor.cs.meta new file mode 100644 index 0000000..15a4039 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/DepthProvider/DepthBufferProcessor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ed7bb2bd1cef47ff88c20eeb03a885c1 +timeCreated: 1623450424 \ No newline at end of file diff --git a/Assets/ARDK/AR/Awareness/Depth/Effects.meta b/Assets/ARDK/AR/Awareness/Depth/Effects.meta new file mode 100644 index 0000000..59d8dcb --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/Effects.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 737bbe0424cbd4cf5b540ec7811ce0ae +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Awareness/Depth/Effects/DepthMeshBufferHelper.cs b/Assets/ARDK/AR/Awareness/Depth/Effects/DepthMeshBufferHelper.cs new file mode 100644 index 0000000..d4070b2 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/Effects/DepthMeshBufferHelper.cs @@ -0,0 +1,86 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using UnityEngine; +using UnityEngine.Rendering; + +#if ARDK_HAS_URP +using Niantic.ARDK.Rendering.SRP; +#endif + +using Niantic.ARDK.Utilities.Logging; + +namespace Niantic.ARDK.AR.Awareness.Depth.Effects +{ + public static class DepthMeshBufferHelper + { + public static void AddCommandBuffer(UnityEngine.Camera camera, CommandBuffer commandBuffer) + { + if (camera == null) + throw new ArgumentNullException(nameof(camera)); + + if (commandBuffer == null) + throw new ArgumentNullException(nameof(commandBuffer)); + +#if ARDK_HAS_URP + if (_RenderPipelineInternals.IsUniversalRenderPipelineEnabled) + { + var feature = GetFeature(); + if (feature != null) + feature.SetupMeshPass(camera, commandBuffer); + return; + } +#endif + + camera.AddCommandBuffer(CameraEvent.BeforeForwardOpaque, commandBuffer); + } + + public static void RemoveCommandBuffer(UnityEngine.Camera camera, CommandBuffer commandBuffer) + { +#if ARDK_HAS_URP + if (_RenderPipelineInternals.IsUniversalRenderPipelineEnabled) + { + var feature = GetFeature(); + if (feature != null) + feature.RemoveMeshPass(); + return; + } +#endif + + if (camera == null) + { + var msg = + "Camera is null. If the camera was destroyed, you don't need to explicitly remove " + + "this command buffer."; + throw new ArgumentNullException(nameof(camera), msg); + } + + if (commandBuffer == null) + throw new ArgumentNullException(nameof(commandBuffer)); + + var cbHandle = commandBuffer; + if (cbHandle != null) + camera.RemoveCommandBuffer(CameraEvent.BeforeForwardOpaque, cbHandle); + } + +#if ARDK_HAS_URP + private static DepthMeshRendererFeature GetFeature() + { + var feature = + _RenderPipelineInternals.GetFeatureOfType(); + + if (feature == null) + { + var message = + "No DepthMeshRendererFeature was found added to the " + + "active Universal Render Pipeline Renderer."; + + ARLog._Error(message); + return null; + } + + return feature; + } +#endif + } +} diff --git a/Assets/ARDK/AR/Awareness/Depth/Effects/DepthMeshBufferHelper.cs.meta b/Assets/ARDK/AR/Awareness/Depth/Effects/DepthMeshBufferHelper.cs.meta new file mode 100644 index 0000000..31c82e8 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/Effects/DepthMeshBufferHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 05310c279dd4c4dac97521b09ec44c09 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Awareness/Depth/Effects/DepthMeshOccluder.cs b/Assets/ARDK/AR/Awareness/Depth/Effects/DepthMeshOccluder.cs new file mode 100644 index 0000000..ce59adc --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/Effects/DepthMeshOccluder.cs @@ -0,0 +1,209 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; + +using Niantic.ARDK.AR.Awareness.Depth.Effects; +using Niantic.ARDK.Rendering; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; +using UnityEngine.Rendering; + +namespace Niantic.ARDK.AR.Depth.Effects +{ + public sealed class DepthMeshOccluder : IDisposable + { + private const string ShaderName = "ARDK/Effects/DepthMeshOccluder"; + private static readonly Shader OcclusionShader = Shader.Find(ShaderName); + + private readonly UnityEngine.Camera _targetCamera; + private readonly CommandBuffer _commandBuffer; + private readonly UnityEngine.Mesh _landscapeMesh, _portraitMesh; + private readonly Material _material; + + public enum ColorMask + { + None = 0, // RGBA: 0000 + Depth = 5, // RGBA: 0101 + UV = 11, // RGBA: 1011 + All = 15, // RGBA: 1111 + } + private ColorMask _colorMask = ColorMask.None; + + public ColorMask DebugColorMask + { + get => _colorMask; + set + { + _colorMask = value; + _material.SetFloat(PropertyBindings.DebugColorMask, (int)_colorMask); + } + } + + /// Enables or disables the occlusion effect. + public bool Enabled + { + get => _isEnabled; + set + { + if (_isEnabled == value) + return; + + _isEnabled = value; + + if (_isEnabled) + DepthMeshBufferHelper.AddCommandBuffer(_targetCamera, _commandBuffer); + else + DepthMeshBufferHelper.RemoveCommandBuffer(_targetCamera, _commandBuffer); + } + } + private bool _isEnabled; + + public Texture SuppressionTexture + { + set => _material.SetTexture(PropertyBindings.DepthSuppressionMask, value); + } + + public Matrix4x4 DepthTransform + { + set => _material.SetMatrix(PropertyBindings.DepthTransform, value); + } + + public Matrix4x4 SemanticsTransform + { + set => _material.SetMatrix(PropertyBindings.SemanticsTransform, value); + } + + private ScreenOrientation _orientation; + + public ScreenOrientation Orientation + { + set + { + if (_orientation == value) + return; + + _orientation = value; + _commandBuffer.Clear(); + _commandBuffer.DrawMesh(_orientation == ScreenOrientation.Portrait || + _orientation == ScreenOrientation.PortraitUpsideDown + ? _portraitMesh + : _landscapeMesh, + Matrix4x4.identity, _material); + } + } + + public DepthMeshOccluder + ( + UnityEngine.Camera targetCamera, + Texture depthTexture, + Resolution meshResolution + ) + { + if (depthTexture == null) + { + ARLog._Error("No Depth Texture provided. Occlusion Mesh Not Created"); + return; + } + + if (targetCamera == null) + { + ARLog._Error("No Target Camera provided. Occlusion Mesh Not Created"); + return; + } + + // Calculate the aspect ratio + var aspect = (float)meshResolution.width / meshResolution.height; + + // Create a landscape version of the mesh using the specified resolution + _landscapeMesh = aspect > 1.0f + ? CreateMesh(meshResolution.width, meshResolution.height) + : CreateMesh(meshResolution.height, meshResolution.width); + + // Create a portrait version of the mesh using the specified resolution + _portraitMesh = aspect < 1.0f + ? CreateMesh(meshResolution.width, meshResolution.height) + : CreateMesh(meshResolution.height, meshResolution.width); + + _material = new Material(OcclusionShader); + _material.SetTexture(PropertyBindings.DepthChannel, depthTexture); + _material.SetFloat(PropertyBindings.DebugColorMask, (int)_colorMask); + + // Allocate the command buffer for drawing the mesh + _commandBuffer = new CommandBuffer(); + _commandBuffer.name = "DepthMeshOccluder"; + + // Assign target camera + _targetCamera = targetCamera; + + // Activate + Orientation = Screen.orientation; + Enabled = true; + } + + /// Sets the range for depth values. This should be invoked in case the GPU depth buffer + /// contains normalized values that need to be scaled before use. + /// @param isScalingEnabled Whether the depth texture contains normalized depth values. + /// @param minDepth Minimum depth value (depth near). + /// @param maxDepth Maximum depth value (depth far). + // TODO: do we need to explicitly set these, or defaults to 0-1? + public void SetScaling(float minDepth, float maxDepth) + { + // Set depth range + _material.SetFloat(PropertyBindings.DepthScaleMin, minDepth); + _material.SetFloat(PropertyBindings.DepthScaleMax, maxDepth); + } + + public void Dispose() + { + Enabled = false; + + // Release the command buffer + _commandBuffer?.Dispose(); + + // Release other resources + UnityEngine.Object.Destroy(_material); + UnityEngine.Object.Destroy(_portraitMesh); + UnityEngine.Object.Destroy(_landscapeMesh); + } + + private static UnityEngine.Mesh CreateMesh(int width, int height) + { + var numPoints = width * height; + var vertices = new Vector3[numPoints]; + var uvs = new Vector2[numPoints]; + var numTriangles = 2 * (width - 1) * (height - 1); // just under 2 triangles per point, total + + // Map vertex indices to triangle in triplets + var triangleIdx = new int[numTriangles * 3]; // 3 vertices per triangle + var startIndex = 0; + + for (var i = 0; i < width * height; ++i) + { + var h = i / width; + var w = i % width; + uvs[i] = new Vector2((float)w / (width - 1), (float)h / (height - 1)); + + if (h == height - 1 || w == width - 1) + continue; + + // Triangle indices are counter-clockwise to face you + triangleIdx[startIndex] = i; + triangleIdx[startIndex + 1] = i + width; + triangleIdx[startIndex + 2] = i + width + 1; + triangleIdx[startIndex + 3] = i; + triangleIdx[startIndex + 4] = i + width + 1; + triangleIdx[startIndex + 5] = i + 1; + startIndex += 6; + } + + var mesh = new UnityEngine.Mesh(); + mesh.MarkDynamic(); + mesh.indexFormat = width * height >= 65534 ? IndexFormat.UInt32 : IndexFormat.UInt16; + mesh.vertices = vertices; + mesh.uv = uvs; + mesh.triangles = triangleIdx; + + return mesh; + } + } +} diff --git a/Assets/ARDK/AR/Awareness/Depth/Effects/DepthMeshOccluder.cs.meta b/Assets/ARDK/AR/Awareness/Depth/Effects/DepthMeshOccluder.cs.meta new file mode 100644 index 0000000..9c89328 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/Effects/DepthMeshOccluder.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 66fe01d8c0a6c4e0385fef75c287e8ac +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Awareness/Depth/Effects/DepthMeshRendererFeature.cs b/Assets/ARDK/AR/Awareness/Depth/Effects/DepthMeshRendererFeature.cs new file mode 100644 index 0000000..230263e --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/Effects/DepthMeshRendererFeature.cs @@ -0,0 +1,51 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +#if ARDK_HAS_URP +using System; + +using UnityEngine; +using UnityEngine.Rendering; +using UnityEngine.Rendering.Universal; + +using Niantic.ARDK.Rendering.SRP; +using Niantic.ARDK.Utilities.Logging; + +namespace Niantic.ARDK.AR.Awareness.Depth.Effects +{ + public sealed class DepthMeshRendererFeature: ScriptableRendererFeature + { + private _CommandBufferPass _pass; + + public override void Create() + { + } + + public void SetupMeshPass(UnityEngine.Camera camera, CommandBuffer commandBuffer) + { + if (camera == null) + throw new ArgumentNullException("camera"); + + if (commandBuffer == null) + throw new ArgumentNullException("commandBuffer"); + + _pass = new _CommandBufferPass(RenderPassEvent.BeforeRenderingOpaques); + _pass.Setup(camera, commandBuffer); + SetActive(true); + } + + public void RemoveMeshPass() + { + _pass = null; + SetActive(false); + } + + // Here you can inject one or multiple render passes in the renderer. + // This method is called when setting up the renderer once per-camera. + public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) + { + if (_pass != null && renderingData.cameraData.camera == _pass.TargetCamera) + renderer.EnqueuePass(_pass); + } + } +} +#endif diff --git a/Assets/ARDK/AR/Awareness/Depth/Effects/DepthMeshRendererFeature.cs.meta b/Assets/ARDK/AR/Awareness/Depth/Effects/DepthMeshRendererFeature.cs.meta new file mode 100644 index 0000000..965e630 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/Effects/DepthMeshRendererFeature.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 50b17de350ea549a4a4312087f83fb9d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Awareness/Depth/Effects/Resources.meta b/Assets/ARDK/AR/Awareness/Depth/Effects/Resources.meta new file mode 100644 index 0000000..7de8dd8 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/Effects/Resources.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fe3ccba729be64a13aff03c950cf753e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Awareness/Depth/Effects/Resources/ContextAwarenessUtils.cginc b/Assets/ARDK/AR/Awareness/Depth/Effects/Resources/ContextAwarenessUtils.cginc new file mode 100644 index 0000000..0ab5b26 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/Effects/Resources/ContextAwarenessUtils.cginc @@ -0,0 +1,27 @@ +inline float DepthToZBufferValue(float z) +{ + // this is equivilent to: + // float4 pos = mul(UNITY_MATRIX_P, float4(0,0,-z,1)); + // return pos.z/pos.w; + return (-z*UNITY_MATRIX_P._m22 + UNITY_MATRIX_P._m23)/z; +} + +/** + * Disparity from the depth buffer is scaled between _minDepth and _maxDepth. + * Disparities (inverse depths) were predicted in the range 0..1 and correspond to + * depth predictions between minimum and maximum depth values hard-coded during training + */ +inline float ScaleDisparity(float disparity, float minDepth, float maxDepth) +{ + const float _minDisp = 1 / maxDepth; + const float _maxDisp = 1 / minDepth; + + float nearOffset = 0;//(_ProjectionParams.y - _minDepth); + float scaledDisp = _minDisp + (_maxDisp - _minDisp) * saturate(disparity); + return scaledDisp + nearOffset; +} + +inline float DisparityToDepth(float disparity, float minDepth, float maxDepth) +{ + return 1.0/lerp(1.0/maxDepth, 1.0/minDepth, saturate(disparity)); +} \ No newline at end of file diff --git a/Assets/ARDK/AR/Awareness/Depth/Effects/Resources/ContextAwarenessUtils.cginc.meta b/Assets/ARDK/AR/Awareness/Depth/Effects/Resources/ContextAwarenessUtils.cginc.meta new file mode 100644 index 0000000..c9ac928 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/Effects/Resources/ContextAwarenessUtils.cginc.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ab1a8914e788e4cd3834c7b02adc4d39 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Awareness/Depth/Effects/Resources/DepthMeshOccluder.shader b/Assets/ARDK/AR/Awareness/Depth/Effects/Resources/DepthMeshOccluder.shader new file mode 100644 index 0000000..a2790e9 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/Effects/Resources/DepthMeshOccluder.shader @@ -0,0 +1,111 @@ +Shader "ARDK/Effects/DepthMeshOccluder" +{ + Properties + { + _textureDepth ("Depth Texture", 2D) = "white" {} + _textureDepthSuppressionMask ("Depth Suppresion Mask", 2D) = "black" {} + _colorMask ("Color Mask", Float) = 0 + } + SubShader + { + Tags + { + "RenderType" = "Opaque" + "Queue" = "Geometry-1" + } + + Pass + { + ColorMask [_colorMask] + Offset 1, 1 + + CGPROGRAM + + #pragma vertex vert + #pragma fragment frag + + #include "UnityCG.cginc" + #include "./ContextAwarenessUtils.cginc" + + // Depth range used for scaling + float _depthScaleMin; + float _depthScaleMax; + + // Plane samplers + sampler2D _textureDepth; + sampler2D _textureDepthSuppressionMask; + + // Transform used to sample the context awareness textures + float4x4 _depthTransform; + float4x4 _semanticsTransform; + + struct v2f + { + float4 pos : SV_POSITION; + float4 color : COLOR; + }; + + v2f vert(appdata_base v) + { + // Transform UVs + float4 uv = float4(v.texcoord.x, v.texcoord.y, 1.0f, 1.0f); + float4 depth_st = mul(_depthTransform, uv); + float4 semantics_st = mul(_semanticsTransform, uv); + + float4 depth_uv = float4(depth_st.x / depth_st.z, depth_st.y / depth_st.z, 0.0f, 0.0f); + float4 semantics_uv = float4(semantics_st.x / semantics_st.z, semantics_st.y / semantics_st.z, 0.0f, 0.0f); + + // Reset depth + float depth = 0; + + // If depth is not suppressed at this vertex + if(tex2Dlod(_textureDepthSuppressionMask, semantics_uv).r == 0.0f) + { + // Sample depth + depth = tex2Dlod(_textureDepth, depth_uv).r; + + // Scale depth in case it is normalized + depth = depth * (_depthScaleMax - _depthScaleMin) + _depthScaleMin; + } + + v2f o; + + // Write depth + o.pos.z = DepthToZBufferValue(depth); // see ContextAwarenessUtils.cginc + o.pos.w = 1.0; + + // Upscale from the mesh's texture space (0..1) to the screen's expected + // output domain of -1..1 + o.pos.x = v.texcoord.x * 2.0 - 1.0; + + // https://docs.unity3d.com/Manual/SL-PlatformDifferences.html + float doubleTextCoord = v.texcoord.y * 2.0; + o.pos.y = lerp + ( + 1.0 - doubleTextCoord, + doubleTextCoord - 1.0, + (_ProjectionParams.x + 1) / 2 + ); + + // We'll use colors to control debug visualization. + // The colors that actually get drawn will depend on the ColorMask that's set. + // R,B correspond to U,V of the disparity texture. + o.color.x = depth_uv.x; + o.color.z = depth_uv.y; + + // G channel corresponds to raw disparity value. + o.color.y = depth; + o.color.w = 1.0f; // For debug visualization, we need opaque. + + return o; + } + + half4 frag(v2f i) : COLOR + { + // Use the input color from the vertex, in the event we're using debug visualization. + return i.color; + } + ENDCG + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/AR/Awareness/Depth/Effects/Resources/DepthMeshOccluder.shader.meta b/Assets/ARDK/AR/Awareness/Depth/Effects/Resources/DepthMeshOccluder.shader.meta new file mode 100644 index 0000000..6d7235d --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/Effects/Resources/DepthMeshOccluder.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: c7de3bfe0691a44c7a95949479097361 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Awareness/Depth/Effects/Resources/DepthMeshOcclusionEffect.shader b/Assets/ARDK/AR/Awareness/Depth/Effects/Resources/DepthMeshOcclusionEffect.shader new file mode 100644 index 0000000..5a18a39 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/Effects/Resources/DepthMeshOcclusionEffect.shader @@ -0,0 +1,103 @@ +Shader "ARDK/Effects/DepthMeshOcclusionEffect" +{ + Properties + { + _minDepth("Min Depth", Float) = 0.0 + _maxDepth("Max Depth", Float) = 0.0 + _disparityTexture ("Depth Texture", 2D) = "white" {} + _suppressionTexture ("Suppression Texture", 2D) = "black" {} + _colorMask ("Color Mask", Float) = 0 + } + SubShader + { + Tags + { + "RenderType" = "Opaque" + "Queue" = "Geometry-1" + } + + Pass + { + ColorMask [_colorMask] + Offset 1, 1 + + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + + #include "UnityCG.cginc" + #include "./ContextAwarenessUtils.cginc" + + sampler2D_float _disparityTexture; + sampler2D_float _suppressionTexture; + float _minDepth; + float _maxDepth; + struct v2f + { + float4 pos : SV_POSITION; + float4 color : COLOR; + }; + + /** + * This function is called for every vertex in the mesh, i.e., + * for every pixel in the depthmap + * + * \param[in] v.texcoord Texture coordinates (0..1) of this vertex in the mesh + * \param[in] _depthTexture A 2D texture sampler that can read disparity values (0..1) from + * the 1 channel depth texture + * \return o o.pos contains the 3D camera space position of the mesh's vertex derived from the depthmap + */ + v2f vert(appdata_base v) + { + float2 depthUV = float2(v.texcoord.x, v.texcoord.y); + + float disparity = tex2Dlod(_disparityTexture, saturate(float4(depthUV, 0.0, 0.0))).r; + float scaledDisparity = ScaleDisparity(disparity, _minDepth, _maxDepth); // see ContextAwarenessUtils.cginc + float depth = DisparityToDepth(disparity, _minDepth, _maxDepth); // see ContextAwarenessUtils.cginc + + // If this suppression texture pixel is white, the pixel belongs to the channel + // NOTE : From what I understand the pixel should be either 0.0 or 1.0. + // Could possibly use multiplication instead of branching? Need to confirm. + if(tex2Dlod(_suppressionTexture, saturate(float4(depthUV, 0.0, 0.0))).r > 0.0) + { + // Suppress it + depth = _maxDepth; + } + + // Remap the 70-100 range to the 70-1000 range with exponential distance increase + // The logic behind this is that currently, depth models become especially noisy + // in this range. So we want to push the noise away to make a cleaner occlusion. + // When the model becomes more stable at further distances, this can be removed. + depth += pow(max(0.0, (depth - 70.0)), 2.0); + + v2f o; + o.pos.z = DepthToZBufferValue(depth); // see ContextAwarenessUtils.cginc + o.pos.w = 1.0; + + // Upscale from the mesh's texture space (0..1) to the screen's expected output domain of -1..1 + o.pos.x = v.texcoord.x * 2.0 - 1.0; + + // https://docs.unity3d.com/Manual/SL-PlatformDifferences.html + float doubleTextCoord = v.texcoord.y * 2.0; + o.pos.y = lerp(1.0 - doubleTextCoord, doubleTextCoord - 1.0, (_ProjectionParams.x + 1) / 2); + + // We'll use colors to control debug visualization. + // The colors that actually get drawn will depend on the ColorMask that's set. + // R,B correspond to U,V of the disparity texture. + o.color.x = depthUV.x; + o.color.z = depthUV.y; + // G channel corresponds to raw disparity value. + o.color.y = scaledDisparity; + o.color.w = 1.0f; // For debug visualiztion, we need opaque. + return o; + } + + half4 frag(v2f i) : COLOR + { + // Use the input color from the vertex, in the event we're using debug visualization. + return i.color; + } + ENDCG + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/AR/Awareness/Depth/Effects/Resources/DepthMeshOcclusionEffect.shader.meta b/Assets/ARDK/AR/Awareness/Depth/Effects/Resources/DepthMeshOcclusionEffect.shader.meta new file mode 100644 index 0000000..c6153bd --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/Effects/Resources/DepthMeshOcclusionEffect.shader.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 49ac0dd71f9444551a771b941f7f2430 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Awareness/Depth/Generators.meta b/Assets/ARDK/AR/Awareness/Depth/Generators.meta new file mode 100644 index 0000000..686b313 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/Generators.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 82e9b9264a55a44669e2420523b78027 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Awareness/Depth/Generators/DepthPointCloudGenerator.cs b/Assets/ARDK/AR/Awareness/Depth/Generators/DepthPointCloudGenerator.cs new file mode 100644 index 0000000..86301fb --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/Generators/DepthPointCloudGenerator.cs @@ -0,0 +1,197 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.ObjectModel; +using System.Runtime.InteropServices; + +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Rendering; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Awareness.Depth.Generators +{ + /// This class takes in a frame of DepthBuffer raw data and generates a point cloud based + /// on it and the camera intrinsics. + public sealed class DepthPointCloudGenerator: + IDisposable + { + private const string GENERATOR_SHADER_NAME = "DepthPointCloudGenerator"; + + private static readonly ComputeShader _pointCloudShader = + (ComputeShader)Resources.Load(GENERATOR_SHADER_NAME); + + private const string KERNEL_NAME = "Generate"; + +#region Shader Handles + private static readonly int DEPTH_BUFFER_WIDTH_HANDLE = + Shader.PropertyToID("DepthBufferWidth"); + + private static readonly int DEPTH_BUFFER_HEIGHT_HANDLE = + Shader.PropertyToID("DepthBufferHeight"); + + private static readonly int INTRINSICS_HANDLE = + Shader.PropertyToID("Intrinsics"); + + private static readonly int POSE_HANDLE = + Shader.PropertyToID("CameraToWorld"); + + private static readonly int POINT_CLOUD_HANDLE = + Shader.PropertyToID("PointCloud"); + + private static readonly int DEPTH_HANDLE = + Shader.PropertyToID("Depth"); + +#endregion + + private int _kernel; + + private uint _kernelThreadsX; + private uint _kernelThreadsY; + + private int _size = 0; + private ComputeBuffer _pointCloudBuffer; + private ComputeBuffer _depthComputeBuffer; + private Vector3[] _pointCloud; + + /// The output of this class. Contains a point for every point on the DepthBuffer, stored + /// as a flat two-dimensional array. + public Vector3[] PointCloud + { + get { return _pointCloud; } + private set { _pointCloud = value; } + } + + /// Constructs a new generator. + /// @param settings User-controlled settings specific to this generator. Cached. + /// @param depthBuffer Depth buffer used to initialize the generator. Not cached. + public DepthPointCloudGenerator() + { + if (!SystemInfo.supportsComputeShaders) + { + var msg = + "DepthPointCloudGenerator failed to initialize because compute shaders are not " + + "supported on this platform."; + +#if UNITY_EDITOR + msg += + " Go to the Edit > Project Settings > Player tab and look in the Other Settings " + + "section to enable Metal Editor Support."; +#endif + + ARLog._Error(msg); + return; + } + + _kernel = _pointCloudShader.FindKernel(KERNEL_NAME); + + _pointCloudShader.GetKernelThreadGroupSizes( + _kernel, + out _kernelThreadsX, + out _kernelThreadsY, + out uint _ + ); + } + + ~DepthPointCloudGenerator() + { + ARLog._Error("DepthPointCloudGenerator must be released by calling Dispose()."); + } + + public void Dispose() + { + GC.SuppressFinalize(this); + + var depthBuffer = _depthComputeBuffer; + if (depthBuffer != null) + { + _depthComputeBuffer = null; + depthBuffer.Release(); + } + + var pointCloudBuffer = _pointCloudBuffer; + if (pointCloudBuffer != null) + { + _pointCloudBuffer = null; + pointCloudBuffer.Release(); + } + } + + /// + /// Uses the compute shaders to generate the a point cloud from the depth image. Each pixel + /// in the depth image will be turned into a 3d point in world space (defined by the + /// inverseViewMat and the focal length). Each 3d point can optionally be categorized. + /// + /// @param depthBuffer A depth buffer with which to generate a point cloud + /// @returns A point cloud based on the depth buffer + public IDepthPointCloud GeneratePointCloud(IDepthBuffer depthBuffer, IARCamera camera) + { + int size = (int)(depthBuffer.Width * depthBuffer.Height); + if(_size != size ){ + + // Setting up input data buffer + _depthComputeBuffer = new ComputeBuffer + ( + (int)(depthBuffer.Width * depthBuffer.Height), + Marshal.SizeOf(typeof(float)) + ); + + _pointCloudShader.SetBuffer(_kernel, DEPTH_HANDLE, _depthComputeBuffer); + + // Setting up output data buffer + _pointCloudBuffer = new ComputeBuffer + ( + (int)(depthBuffer.Width * depthBuffer.Height), + Marshal.SizeOf(typeof(Vector3)) + ); + + _pointCloud = new Vector3[depthBuffer.Width * depthBuffer.Height]; + _pointCloudBuffer.SetData(_pointCloud); + _pointCloudShader.SetBuffer(_kernel, POINT_CLOUD_HANDLE, _pointCloudBuffer); + _size = size; + } + + var cameraToWorld = + ( + MathUtils.CalculateScreenRotation + ( + from: ScreenOrientation.LandscapeLeft, + to: RenderTarget.ScreenOrientation + ) * depthBuffer.ViewMatrix + ).inverse; + + _pointCloudShader.SetInt(DEPTH_BUFFER_WIDTH_HANDLE, (int)depthBuffer.Width); + _pointCloudShader.SetInt(DEPTH_BUFFER_HEIGHT_HANDLE, (int)depthBuffer.Height); + _pointCloudShader.SetVector(INTRINSICS_HANDLE, depthBuffer.Intrinsics); + _pointCloudShader.SetMatrix(POSE_HANDLE, cameraToWorld); + + // update the depth image + _depthComputeBuffer.SetData(depthBuffer.Data); + + // We can't assume the width/height are evenly divisible by thread count. + // So, to get around this, we'll oversize if needed and then no-op in the shader for + // any excess workers + var threadGroupPaddingX = depthBuffer.Width % _kernelThreadsX > 0 ? 1 : 0; + var threadGroupPaddingY = depthBuffer.Height % _kernelThreadsY > 0 ? 1 : 0; + var threadGroupX = (int)(depthBuffer.Width / _kernelThreadsX) + threadGroupPaddingX; + var threadGroupY = (int)(depthBuffer.Height / _kernelThreadsY) + threadGroupPaddingY; + + // TODO : Profile this Dispatch & Get. Maybe we can avoid having the main thread wait? + // calculate the point cloud + _pointCloudShader.Dispatch(_kernel, threadGroupX, threadGroupY, 1); + + // copy the point cloud into the local buffer + _pointCloudBuffer.GetData(_pointCloud); + + var retVal = new _DepthPointCloud + ( + new ReadOnlyCollection(_pointCloud), + depthBuffer.Width, + depthBuffer.Height + ); + + return retVal; + } + } +} diff --git a/Assets/ARDK/AR/Awareness/Depth/Generators/DepthPointCloudGenerator.cs.meta b/Assets/ARDK/AR/Awareness/Depth/Generators/DepthPointCloudGenerator.cs.meta new file mode 100644 index 0000000..8a2ec89 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/Generators/DepthPointCloudGenerator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9bc78c174c2a644c385cb6b3cb3c59d6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Awareness/Depth/Generators/IDepthPointCloud.cs b/Assets/ARDK/AR/Awareness/Depth/Generators/IDepthPointCloud.cs new file mode 100644 index 0000000..4508fba --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/Generators/IDepthPointCloud.cs @@ -0,0 +1,27 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.ObjectModel; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Awareness.Depth +{ + /// + /// Represents a depth point cloud. + /// + public interface IDepthPointCloud: + IDisposable + { + /// + /// The collection of world-space depth points. + /// + ReadOnlyCollection Points { get; } + + /// The width of the depth point cloud, from the camera's perspective + UInt32 Width { get; } + + /// The height of the depth point cloud, from the camera's perspective + UInt32 Height { get; } + } +} diff --git a/Assets/ARDK/AR/Awareness/Depth/Generators/IDepthPointCloud.cs.meta b/Assets/ARDK/AR/Awareness/Depth/Generators/IDepthPointCloud.cs.meta new file mode 100644 index 0000000..e31366f --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/Generators/IDepthPointCloud.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5ecd8845842324a13b49c574b2021342 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Awareness/Depth/Generators/Resources.meta b/Assets/ARDK/AR/Awareness/Depth/Generators/Resources.meta new file mode 100644 index 0000000..d04ccc0 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/Generators/Resources.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7e94b3da7fb944b3e971591079f352e0 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Awareness/Depth/Generators/Resources/DepthPointCloudGenerator.compute b/Assets/ARDK/AR/Awareness/Depth/Generators/Resources/DepthPointCloudGenerator.compute new file mode 100644 index 0000000..7ad8b3b --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/Generators/Resources/DepthPointCloudGenerator.compute @@ -0,0 +1,62 @@ +// TODO (awetherington) : Is there a way to register this shader as "ARDK/Generators/DepthPointCloudGenerator"? + +#pragma kernel Generate + +static const uint3 NumThreads = {8, 8, 1}; + +uint DepthBufferWidth; +uint DepthBufferHeight; +float4 Intrinsics; +float4x4 CameraToWorld; + +// vars that change per invocation +RWStructuredBuffer PointCloud; +StructuredBuffer Depth; + +// helper method to get the index into the Depth buffer from the thread index +int DepthBufferIndexFromId(in uint3 id) +{ + // return -1 if this worker thread is padding, else return the depth buffer index + return (DepthBufferWidth <= id.x || DepthBufferHeight <= id.y) ? + -1 : id.x + id.y * DepthBufferWidth; +} + +float3 UnProject(in float2 id, in float depth) +{ + float2 focalLength = float2(Intrinsics.x, Intrinsics.y); + float2 principalPoint = float2(Intrinsics.z, Intrinsics.w); + + // First, convert the threadID [0, N] into a pixel coordinate with the centered + // principalPoint treated as the origin, so the new range is [-N/2, N/2] + float2 idPixelCoord = float2(id.x - principalPoint.x, id.y - principalPoint.y); + + // Then use similar triangles to determine a metric offset in camera space + // Using the fact that: camSpacePos.x / idPixelCoord.x = depth / focalLength.x + float2 camSpacePos = depth * float2(idPixelCoord.x/focalLength.x, idPixelCoord.y/focalLength.y); + + // NAR to Unity conversion + float4 pointToCamera = float4(camSpacePos.x, -camSpacePos.y, depth, 1); + + // camera to world coordinate + float4 pointToWorld = mul(CameraToWorld, pointToCamera); + return pointToWorld.xyz; +} + +// For a given Depth sample at a given pixel position, determine the world position +// the sample represents. +[numthreads(NumThreads.x, NumThreads.y, NumThreads.z)] +void Generate(uint3 id : SV_DispatchThreadID) +{ + // get the Depth sample + int index = DepthBufferIndexFromId(id); + if(index == -1){ + return; + } + float depth = Depth[index]; + + // Unproject + float3 position = UnProject(float2(id.x, id.y), depth); + + // apply the vertial fixup and save the value into the point cloud buffer + PointCloud[index] = position; +} \ No newline at end of file diff --git a/Assets/ARDK/AR/Awareness/Depth/Generators/Resources/DepthPointCloudGenerator.compute.meta b/Assets/ARDK/AR/Awareness/Depth/Generators/Resources/DepthPointCloudGenerator.compute.meta new file mode 100644 index 0000000..1f5769b --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/Generators/Resources/DepthPointCloudGenerator.compute.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0672af943144b4f1482431ffea10dc5b +ComputeShaderImporter: + externalObjects: {} + currentAPIMask: 196608 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Awareness/Depth/Generators/_DepthPointCloud.cs b/Assets/ARDK/AR/Awareness/Depth/Generators/_DepthPointCloud.cs new file mode 100644 index 0000000..f936518 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/Generators/_DepthPointCloud.cs @@ -0,0 +1,38 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; + +using Niantic.ARDK.AR; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Awareness.Depth +{ + [Serializable] + internal sealed class _DepthPointCloud : IDepthPointCloud + { + internal _DepthPointCloud + ( + ReadOnlyCollection points, + UInt32 width, + UInt32 height + ) + { + Points = points; + Width = width; + Height = height; + } + + public ReadOnlyCollection Points { get; } + public UInt32 Width { get; } + public UInt32 Height { get; } + + void IDisposable.Dispose() + { + // Do nothing as this object is fully managed. + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/AR/Awareness/Depth/Generators/_DepthPointCloud.cs.meta b/Assets/ARDK/AR/Awareness/Depth/Generators/_DepthPointCloud.cs.meta new file mode 100644 index 0000000..26aee5f --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/Generators/_DepthPointCloud.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 48cb9f46a215a4c2b913d6d6a666f005 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Awareness/Depth/IDepthBuffer.cs b/Assets/ARDK/AR/Awareness/Depth/IDepthBuffer.cs new file mode 100644 index 0000000..a436a81 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/IDepthBuffer.cs @@ -0,0 +1,125 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Awareness.Depth +{ + // The value of position [x, y] in the Data buffer equals how many meters away + // from the camera the surface in that pixel is, clamped to the range of NearDistance + // to FarDistance. + public interface IDepthBuffer: IDataBuffer, IDisposable + { + /// The minimum distance from the camera (in meters) captured by this depth buffer. + /// Depths closer in will be assigned this distance. + float NearDistance { get; } + + /// The maximum distance from the camera (in meters) captured by this depth buffer. + /// Depths farther out will be assigned this distance. + float FarDistance { get; } + + /// Update (or create, if needed) a texture with this depth buffer's data. + /// @param texture + /// Reference to the texture to copy to. This method will create a texture if the reference + /// is null. + /// @param valueConverter + /// Defines a function to perform additional processing on the values before pushing + /// to the GPU. This is usually used to normalize values for ARGB32 textures. + /// @returns True if the buffer was successfully copied to the given texture. + bool CreateOrUpdateTextureARGB32 + ( + ref Texture2D texture, + FilterMode filterMode = FilterMode.Point, + Func valueConverter = null + ); + + /// Update (or create, if needed) a texture with this depth buffer's data. + /// @param texture + /// Reference to the texture to copy to. This method will create a texture if the reference + /// is null. + /// @returns True if the buffer was successfully copied to the given texture. + bool CreateOrUpdateTextureRFloat + ( + ref Texture2D texture, + FilterMode filterMode = FilterMode.Point + ); + + /// Rotates the depth buffer so it is oriented to the screen. + /// @note + /// The raw buffer, not yet rotated to screen orientation, will be oriented the same as the + /// device's raw camera image. In most cases, gravity points to the right. + /// @returns + /// A new depth buffer rotated. + /// @note + /// This method is deprecated and will be removed in a future update. + /// Use DepthBufferProcessor's CopyToAlignedTexture to get a texture fitted to the screen. + IDepthBuffer RotateToScreenOrientation(); + + /// Interpolate the depth buffer using the given camera and viewport information. Since the + /// depth buffer served by an ARFrame was likely generated using a camera image from a previous + /// frame, always interpolate the buffer in order to get the best depth estimation. + /// @param arCamera + /// ARCamera with the pose to interpolate this buffer to. + /// @param viewportWidth + /// Width of the viewport. In most cases this equals to the rendering camera's pixel width. + /// This is used to calculate the new projection matrix. + /// @param viewportHeight + /// Height of the viewport. In most cases this equals to the rendering camera's pixel height. + /// This is used to calculate the new projection matrix. + /// @param backProjectionDistance + /// This value sets the normalized distance of the back-projection plane. Lower values result + /// in depths more accurate for closer pixels, but pixels further away will move faster + /// than they should. Use 0.5f if your subject in the scene is always closer than ~2 meters + /// from the device, and use 1.0f if your subject is further away most of the time. + /// @returns A new IDepthBuffer with data interpolated using the camera and viewport inputs. + /// @note + /// This method is deprecated and will be removed in a future update. + /// Use DepthBufferProcessor's CopyToAlignedTexture to get a texture fitted to the screen. + IDepthBuffer Interpolate + ( + IARCamera arCamera, + int viewportWidth, + int viewportHeight, + float backProjectionDistance = AwarenessParameters.DefaultBackProjectionDistance + ); + + /// Fits the depth buffer to the given dimensions. + /// @note + /// The returned depth buffer will be rotated to match the screen orientation, + /// if it has not been already. + /// @param viewportWidth + /// Width of the viewport. In most cases this equals the screen resolution's width. + /// @param viewportHeight + /// Height of the viewport. In most cases this equals the screen resolution's height. + /// @returns + /// A new buffer sized to the given viewport dimensions, + /// and rotated to the screen rotation. + /// @note + /// This method is deprecated and will be removed in a future update. + /// Use DepthBufferProcessor's CopyToAlignedTexture to get a texture fitted to the screen. + IDepthBuffer FitToViewport + ( + int viewportWidth, + int viewportHeight + ); + + /// Returns the nearest value to the specified normalized coordinates in the buffer. + /// @param uv + /// Normalized coordinates. + /// @returns + /// The value in the depth buffer at the nearest location to the coordinates. + float Sample(Vector2 uv); + + /// Returns the nearest value to the specified normalized coordinates in the buffer. + /// @param uv + /// Normalized coordinates. + /// @param transform + /// 2D transformation applied to normalized coordinates before sampling. + /// This transformation should convert to the depth buffer's coordinate frame. + /// @returns + /// The value in the depth buffer at the nearest location to the + /// transformed coordinates. + float Sample(Vector2 uv, Matrix4x4 transform); + } +} diff --git a/Assets/ARDK/AR/Awareness/Depth/IDepthBuffer.cs.meta b/Assets/ARDK/AR/Awareness/Depth/IDepthBuffer.cs.meta new file mode 100644 index 0000000..c07abcc --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/IDepthBuffer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ef9c2a8ee8ee644468ac68c07c604dd0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Awareness/Depth/IDepthBufferProcessor.cs b/Assets/ARDK/AR/Awareness/Depth/IDepthBufferProcessor.cs new file mode 100644 index 0000000..6f27d3b --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/IDepthBufferProcessor.cs @@ -0,0 +1,77 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using UnityEngine; + +namespace Niantic.ARDK.AR.Awareness.Depth +{ + /// An interface that extracts information from a raw depth buffer for game code. + /// @note Requires that the ARSession is run with IARWorldTrackingConfiguration.DepthFeatures + /// set to DepthFeatures.Depth. + public interface IDepthBufferProcessor: + IAwarenessBufferProcessor + { + /// The CPU copy of the latest awareness buffer. + IDepthBuffer AwarenessBuffer { get; } + + /// The closest perpendicular depth value to be considered meaningful. + float MinDepth { get; } + + /// The farthest perpendicular depth value to be considered meaningful. + float MaxDepth { get; } + + /// Returns the eye depth of the specified pixel. + /// @param viewportX Horizontal coordinate in viewport space. + /// @param viewportY Vertical coordinate in viewport space. + /// @returns The perpendicular depth from the camera plane if exists or float.PositiveInfinity + /// if the depth information is unavailable. + float GetDepth(int viewportX, int viewportY); + + /// Returns the distance of the specified pixel from the camera origin. + /// @param viewportX Horizontal coordinate in viewport space. + /// @param viewportY Vertical coordinate in viewport space. + /// @returns The distance from the camera if exists or float.PositiveInfinity if the depth + /// information is unavailable. + float GetDistance(int viewportX, int viewportY); + + /// Returns the world position of the specified pixel. + /// @param viewportX Horizontal coordinate in viewport space. + /// @param viewportY Vertical coordinate in viewport space. + /// @returns World position if exists or Vector3.zero if the depth information is unavailable. + Vector3 GetWorldPosition(int viewportX, int viewportY); + + /// Returns the surface normal of the specified pixel. + /// @param viewportX Horizontal coordinate in viewport space. + /// @param viewportY Vertical coordinate in viewport space. + /// @returns Normal if exists or Vector3.up if the depth information is unavailable. + Vector3 GetSurfaceNormal(int viewportX, int viewportY); + + /// Pushes the current state of the depth buffer to the + /// specified target texture. The resulting texture will + /// contain a display aligned representation of normalized + /// depth values. + /// @note Only use this call if you absolutely need the + /// texture to be display aligned. It is faster to + /// create a texture from the awareness buffer itself. + /// @param texture The target texture (ARGB32). If this + /// texture does not exist, it will be created. It is + /// the responsibility of the caller to release this texture. + /// @param orientation The target orientation of the texture. + /// This determines the resolution of the container. This has + /// to be either landscape or portrait. + void CopyToAlignedTextureARGB32(ref Texture2D texture, ScreenOrientation orientation); + + /// Pushes the current state of the depth buffer to the + /// specified target texture. The resulting texture will + /// contain a display aligned representation of the raw + /// depth values. + /// @note Only use this call if you absolutely need the + /// texture to be display aligned. It is faster to + /// create a texture from the awareness buffer itself. + /// @param texture The target texture (RFloat). If this + /// texture does not exist, it will be created. It is + /// the responsibility of the caller to release this texture. + /// @param orientation The target orientation of the texture. + /// This determines the resolution of the container. This has + /// to be either landscape or portrait. + void CopyToAlignedTextureRFloat(ref Texture2D texture, ScreenOrientation orientation); + } +} diff --git a/Assets/ARDK/AR/Awareness/Depth/IDepthBufferProcessor.cs.meta b/Assets/ARDK/AR/Awareness/Depth/IDepthBufferProcessor.cs.meta new file mode 100644 index 0000000..bd959e9 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/IDepthBufferProcessor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6f788f4e515a4a99a14aaeb8ff2da0d7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Awareness/Depth/_NativeDepthBuffer.cs b/Assets/ARDK/AR/Awareness/Depth/_NativeDepthBuffer.cs new file mode 100644 index 0000000..a82a878 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/_NativeDepthBuffer.cs @@ -0,0 +1,340 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Internals; + +using System; +using System.Runtime.InteropServices; + +using Niantic.ARDK.AR.Camera; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Awareness.Depth +{ + internal sealed class _NativeDepthBuffer: + _NativeAwarenessBufferBase, + IDepthBuffer + { + static _NativeDepthBuffer() + { + Platform.Init(); + } + + internal _NativeDepthBuffer(IntPtr nativeHandle, float worldScale, CameraIntrinsics intrinsics) + : base + ( + nativeHandle, + worldScale, + GetNativeWidth(nativeHandle), + GetNativeHeight(nativeHandle), + IsNativeKeyframe(nativeHandle), + intrinsics + ) + { + } + + public float NearDistance + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _DepthBuffer_GetNearDistance(_nativeHandle); + #pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + } + } + + public float FarDistance + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _DepthBuffer_GetFarDistance(_nativeHandle); + #pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + } + } + + public override IAwarenessBuffer GetCopy() + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + var newHandle = _DepthBuffer_GetCopy(_nativeHandle); + + return new _NativeDepthBuffer(newHandle, _worldScale, Intrinsics); + } + else + { +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + } + + public IDepthBuffer RotateToScreenOrientation() + { + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + + var newHandle = _DepthBuffer_RotateToScreenOrientation(_nativeHandle); + + return new _NativeDepthBuffer(newHandle, _worldScale, Intrinsics); + } + else + { + #pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + } + } + + public IDepthBuffer Interpolate + ( + IARCamera arCamera, + int viewportWidth, + int viewportHeight, + float backProjectionDistance = AwarenessParameters.DefaultBackProjectionDistance + ) + { + var projectionMatrix = + arCamera.CalculateProjectionMatrix + ( + Screen.orientation, + viewportWidth, + viewportHeight, + NearDistance, + FarDistance + ); + + var frameViewMatrix = arCamera.GetViewMatrix(Screen.orientation); + var nativeProjectionMatrix = _UnityMatrixToNarArray(projectionMatrix); + var nativeFrameViewMatrix = _UnityMatrixToNarArray(frameViewMatrix); + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + var newHandle = _DepthBuffer_Interpolate + ( + _nativeHandle, + nativeProjectionMatrix, + nativeFrameViewMatrix, + backProjectionDistance + ); + + return new _NativeDepthBuffer(newHandle, _worldScale, Intrinsics); + } + else + { + #pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + } + } + + public IDepthBuffer FitToViewport + ( + int viewportWidth, + int viewportHeight + ) + { + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + + var newHandle = _DepthBuffer_FitToViewport + ( + _nativeHandle, + viewportWidth, + viewportHeight + ); + + return new _NativeDepthBuffer(newHandle, _worldScale, Intrinsics); + } + else + { + #pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + } + } + + public float Sample(Vector2 uv) + { + var w = (int)Width; + var h = (int)Height; + + var x = Mathf.Clamp(Mathf.RoundToInt(uv.x * w - 0.5f), 0, w - 1); + var y = Mathf.Clamp(Mathf.RoundToInt(uv.y * h - 0.5f), 0, h - 1); + + return Data[x + w * y]; + } + + public float Sample(Vector2 uv, Matrix4x4 transform) + { + var w = (int)Width; + var h = (int)Height; + + var st = transform * new Vector4(uv.x, uv.y, 1.0f, 1.0f); + var sx = st.x / st.z; + var sy = st.y / st.z; + + var x = Mathf.Clamp(Mathf.RoundToInt(sx * w - 0.5f), 0, w - 1); + var y = Mathf.Clamp(Mathf.RoundToInt(sy * h - 0.5f), 0, h - 1); + + return Data[x + w * y]; + } + + public bool CreateOrUpdateTextureARGB32 + ( + ref Texture2D texture, + FilterMode filterMode = FilterMode.Point, + Func valueConverter = null + ) + { + return _AwarenessBufferHelper._CreateOrUpdateTextureARGB32 + ( + Data, + (int)Width, + (int)Height, + ref texture, + filterMode, + valueConverter + ); + } + + public bool CreateOrUpdateTextureRFloat + ( + ref Texture2D texture, + FilterMode filterMode = FilterMode.Point + ) + { + return _AwarenessBufferHelper._CreateOrUpdateTextureRFloat + ( + Data, + (int)Width, + (int)Height, + ref texture, + filterMode + ); + } + + protected override void _GetViewMatrix(float[] outViewMatrix) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _DepthBuffer_GetView(_nativeHandle, outViewMatrix); + #pragma warning disable 0162 + else + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + } + + protected override void _GetIntrinsics(float[] outVector) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _DepthBuffer_GetIntrinsics(_nativeHandle, outVector); + #pragma warning disable 0162 + else + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + } + + protected override void _OnRelease() + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _DepthBuffer_Release(_nativeHandle); + #pragma warning disable 0162 + else + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + } + + protected override IntPtr _GetDataAddress() + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _DepthBuffer_GetDataAddress(_nativeHandle); + #pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + } + + private static uint GetNativeWidth(IntPtr nativeHandle) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _DepthBuffer_GetWidth(nativeHandle); + #pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + } + + private static uint GetNativeHeight(IntPtr nativeHandle) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _DepthBuffer_GetHeight(nativeHandle); + #pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + } + + + private static bool IsNativeKeyframe(IntPtr nativeHandle) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _DepthBuffer_IsKeyframe(nativeHandle); + #pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + } + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _DepthBuffer_Release(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern UInt32 _DepthBuffer_GetWidth(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern UInt32 _DepthBuffer_GetHeight(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern bool _DepthBuffer_IsKeyframe(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _DepthBuffer_GetView(IntPtr nativeHandle, float[] outViewMatrix); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _DepthBuffer_GetIntrinsics(IntPtr nativeHandle, float[] outVector); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _DepthBuffer_GetDataAddress(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern float _DepthBuffer_GetNearDistance(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern float _DepthBuffer_GetFarDistance(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _DepthBuffer_GetCopy(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _DepthBuffer_RotateToScreenOrientation(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _DepthBuffer_Interpolate + ( + IntPtr nativeHandle, + float[] nativeProjectionMatrix, + float[] nativeFrameViewMatrix, + float backProjectionDistance + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _DepthBuffer_FitToViewport + ( + IntPtr nativeHandle, + int viewportWidth, + int viewportHeight + ); + } +} diff --git a/Assets/ARDK/AR/Awareness/Depth/_NativeDepthBuffer.cs.meta b/Assets/ARDK/AR/Awareness/Depth/_NativeDepthBuffer.cs.meta new file mode 100644 index 0000000..c178700 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/_NativeDepthBuffer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d4c52a74e8a8c41e88619a6598774a68 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Awareness/Depth/_SerializableDepthBuffer.cs b/Assets/ARDK/AR/Awareness/Depth/_SerializableDepthBuffer.cs new file mode 100644 index 0000000..1c2c63a --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/_SerializableDepthBuffer.cs @@ -0,0 +1,284 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.AR.Camera; +using Niantic.ARDK.Utilities.Logging; + +using Unity.Collections; +using UnityEngine; + +namespace Niantic.ARDK.AR.Awareness.Depth +{ + // Can't use [Serializable]. Need to provide a serializer. + internal sealed class _SerializableDepthBuffer + : _SerializableAwarenessBufferBase, + IDepthBuffer + { + private static bool _hasWarnedAboutInterpolation; + + internal _SerializableDepthBuffer + ( + uint width, + uint height, + bool isKeyframe, + Matrix4x4 viewMatrix, + NativeArray data, + float nearDistance, + float farDistance, + CameraIntrinsics intrinsics + ) + : base(width, height, isKeyframe, viewMatrix, data, intrinsics) + { + NearDistance = nearDistance; + FarDistance = farDistance; + } + + public float NearDistance { get; private set; } + + public float FarDistance { get; private set; } + + public float Sample(Vector2 uv) + { + var w = (int)Width; + var h = (int)Height; + + var x = Mathf.Clamp(Mathf.RoundToInt(uv.x * w - 0.5f), 0, w - 1); + var y = Mathf.Clamp(Mathf.RoundToInt(uv.y * h - 0.5f), 0, h - 1); + + return Data[x + w * y]; + } + + public float Sample(Vector2 uv, Matrix4x4 transform) + { + var w = (int)Width; + var h = (int)Height; + + var st = transform * new Vector4(uv.x, uv.y, 1.0f, 1.0f); + var sx = st.x / st.z; + var sy = st.y / st.z; + + var x = Mathf.Clamp(Mathf.RoundToInt(sx * w - 0.5f), 0, w - 1); + var y = Mathf.Clamp(Mathf.RoundToInt(sy * h - 0.5f), 0, h - 1); + + return Data[x + w * y]; + } + + public override IAwarenessBuffer GetCopy() + { + return new _SerializableDepthBuffer + ( + Width, + Height, + false, + ViewMatrix, + new NativeArray(Data, Allocator.Persistent), + NearDistance, + FarDistance, + Intrinsics + ) + { + IsRotatedToScreenOrientation = IsRotatedToScreenOrientation + }; + } + + public IDepthBuffer RotateToScreenOrientation() + { + if (IsRotatedToScreenOrientation) + return GetCopy() as IDepthBuffer; + + var newData = + _AwarenessBufferHelper.RotateToScreenOrientation + ( + Data, + (int) Width, + (int) Height, + out int newWidth, + out int newHeight + ); + + var newBuffer = + new _SerializableDepthBuffer + ( + (uint) newWidth, + (uint) newHeight, + false, + ViewMatrix, + newData, + NearDistance, + FarDistance, + Intrinsics + ) + { + IsRotatedToScreenOrientation = true + }; + + return newBuffer; + } + + public IDepthBuffer Interpolate + ( + IARCamera arCamera, + int viewportWidth, + int viewportHeight, + float backProjectionDistance = AwarenessParameters.DefaultBackProjectionDistance + ) + { + if (!_hasWarnedAboutInterpolation) + { + ARLog._Warn + ( + "IDepthBuffer.Interpolate is not supported in the Unity Editor. " + + "No interpolation will be performed." + ); + + _hasWarnedAboutInterpolation = true; + } + + if (!IsRotatedToScreenOrientation) + { + var rotated = + _AwarenessBufferHelper.RotateToScreenOrientation + ( + Data, + (int) Width, + (int) Height, + out int rotatedWidth, + out int rotatedHeight + ); + + return new _SerializableDepthBuffer + ( + (uint)rotatedWidth, + (uint)rotatedHeight, + false, + ViewMatrix, + rotated, + NearDistance, + FarDistance, + Intrinsics + ) + { + IsRotatedToScreenOrientation = true + }; + } + + return new _SerializableDepthBuffer + ( + Width, + Height, + false, + ViewMatrix, + new NativeArray(Data, Allocator.Persistent), + NearDistance, + FarDistance, + Intrinsics + ) + { + IsRotatedToScreenOrientation = true + }; + } + + public IDepthBuffer FitToViewport + ( + int viewportWidth, + int viewportHeight + ) + { + NativeArray fit; + int fitWidth, fitHeight; + + if (!IsRotatedToScreenOrientation) + { + var rotated = + _AwarenessBufferHelper.RotateToScreenOrientation + ( + Data, + (int)Width, + (int)Height, + out int rotatedWidth, + out int rotatedHeight + ); + + fit = + _AwarenessBufferHelper._FitToViewport + ( + rotated, + rotatedWidth, + rotatedHeight, + viewportWidth, + viewportHeight, + out fitWidth, + out fitHeight + ); + + rotated.Dispose(); + } + else + { + fit = + _AwarenessBufferHelper._FitToViewport + ( + Data, + (int)Width, + (int)Height, + viewportWidth, + viewportHeight, + out fitWidth, + out fitHeight + ); + } + + + return new _SerializableDepthBuffer + ( + (uint)fitWidth, + (uint)fitHeight, + false, + ViewMatrix, + fit, + NearDistance, + FarDistance, + Intrinsics + ) + { + IsRotatedToScreenOrientation = true + }; + } + + public bool CreateOrUpdateTextureARGB32 + ( + ref Texture2D texture, + FilterMode filterMode = FilterMode.Point, + Func valueConverter = null + ) + { + return + _AwarenessBufferHelper._CreateOrUpdateTextureARGB32 + ( + Data, + (int)Width, + (int)Height, + ref texture, + filterMode, + valueConverter + ); + } + + public bool CreateOrUpdateTextureRFloat + ( + ref Texture2D texture, + FilterMode filterMode = FilterMode.Point + ) + { + return _AwarenessBufferHelper._CreateOrUpdateTextureRFloat + ( + Data, + (int)Width, + (int)Height, + ref texture, + filterMode + ); + } + } +} diff --git a/Assets/ARDK/AR/Awareness/Depth/_SerializableDepthBuffer.cs.meta b/Assets/ARDK/AR/Awareness/Depth/_SerializableDepthBuffer.cs.meta new file mode 100644 index 0000000..5624ace --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/_SerializableDepthBuffer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e8a990d99a4574e799ce6e126b96367d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Awareness/Depth/_SerializableDepthBufferSerializer.cs b/Assets/ARDK/AR/Awareness/Depth/_SerializableDepthBufferSerializer.cs new file mode 100644 index 0000000..c993378 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/_SerializableDepthBufferSerializer.cs @@ -0,0 +1,79 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.Utilities.BinarySerialization; +using Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers; +using Niantic.ARDK.AR.Camera; + +using Unity.Collections; +using UnityEngine; + +namespace Niantic.ARDK.AR.Awareness.Depth +{ + internal sealed class _SerializableDepthBufferSerializer: + _SerializableAwarenessBufferSerializer<_SerializableDepthBuffer, float> + { + private const bool USE_JPEG_COMPRESSION = true; + + // 0-100. Better use higher quality as depth buffer resolution is low and + // artifacts from compression affects more. + private const int JPEG_COMPRESSION_QUALITY = 95; + internal static readonly _SerializableDepthBufferSerializer _instance = + new _SerializableDepthBufferSerializer(); + + private _SerializableDepthBufferSerializer() + { + } + + protected override void DoSerialize(BinarySerializer serializer, _SerializableDepthBuffer item) + { + base.DoSerialize(serializer, item); + + var compressedData = _VideoStreamHelper._CompressForDepthBuffer + ( + (int)item.Width, + (int)item.Height, + item.Data, + USE_JPEG_COMPRESSION, + JPEG_COMPRESSION_QUALITY + ); + ByteArraySerializer.Instance.Serialize(serializer, compressedData); + + var floatSerializer = FloatSerializer.Instance; + floatSerializer.Serialize(serializer, item.NearDistance); + floatSerializer.Serialize(serializer, item.FarDistance); + } + + protected override _SerializableDepthBuffer _InternalDeserialize + ( + BinaryDeserializer deserializer, + uint width, + uint height, + bool isKeyFrame, + Matrix4x4 view, + CameraIntrinsics intrinsics + ) + { + var compressedData = ByteArraySerializer.Instance.Deserialize(deserializer); + var data = _VideoStreamHelper._DecompressForDepthBuffer(compressedData, USE_JPEG_COMPRESSION); + + var floatSerializer = FloatSerializer.Instance; + float nearDistance = floatSerializer.Deserialize(deserializer); + float farDistance = floatSerializer.Deserialize(deserializer); + + return + new _SerializableDepthBuffer + ( + width, + height, + isKeyFrame, + view, + data, + nearDistance, + farDistance, + intrinsics + ); + } + } +} diff --git a/Assets/ARDK/AR/Awareness/Depth/_SerializableDepthBufferSerializer.cs.meta b/Assets/ARDK/AR/Awareness/Depth/_SerializableDepthBufferSerializer.cs.meta new file mode 100644 index 0000000..85c812e --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Depth/_SerializableDepthBufferSerializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cec38b647c26940c5872059b2149406b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Awareness/IAwarenessBuffer.cs b/Assets/ARDK/AR/Awareness/IAwarenessBuffer.cs new file mode 100644 index 0000000..5809993 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/IAwarenessBuffer.cs @@ -0,0 +1,33 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.AR.Camera; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Awareness +{ + public interface IAwarenessBuffer + { + /// View matrix of the ARCamera when this buffer was generated. + Matrix4x4 ViewMatrix { get; } + + /// Intrinsics values of the image this depth buffer was generate from. + CameraIntrinsics Intrinsics { get; } + + /// True if this buffer is a keyframe (i.e. not interpolated). + bool IsKeyframe { get; } + + /// Width of the buffer. + UInt32 Width { get; } + + /// Height of the buffer. + UInt32 Height { get; } + + /// Copies the awareness buffer + /// @returns + /// A new typed awareness buffer copied. + IAwarenessBuffer GetCopy(); + } +} diff --git a/Assets/ARDK/AR/Awareness/IAwarenessBuffer.cs.meta b/Assets/ARDK/AR/Awareness/IAwarenessBuffer.cs.meta new file mode 100644 index 0000000..32879a2 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/IAwarenessBuffer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 7d0f7c9fe34a4dc1ae69f8f397384da8 +timeCreated: 1593467222 \ No newline at end of file diff --git a/Assets/ARDK/AR/Awareness/IDataBuffer.cs b/Assets/ARDK/AR/Awareness/IDataBuffer.cs new file mode 100644 index 0000000..73b1312 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/IDataBuffer.cs @@ -0,0 +1,13 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Unity.Collections; + +namespace Niantic.ARDK.AR.Awareness +{ + public interface IDataBuffer : IAwarenessBuffer + where T: struct + { + /// Raw data of this buffer. + NativeArray Data { get; } + } +} diff --git a/Assets/ARDK/AR/Awareness/IDataBuffer.cs.meta b/Assets/ARDK/AR/Awareness/IDataBuffer.cs.meta new file mode 100644 index 0000000..31b3950 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/IDataBuffer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 624dfbe126904b449782a1cb17136f14 +timeCreated: 1607723453 \ No newline at end of file diff --git a/Assets/ARDK/AR/Awareness/Semantics.meta b/Assets/ARDK/AR/Awareness/Semantics.meta new file mode 100644 index 0000000..cf4c93b --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Semantics.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 01e75a8cd1a64d78b64c2d4de0da6ed0 +timeCreated: 1627050953 \ No newline at end of file diff --git a/Assets/ARDK/AR/Awareness/Semantics/Generators.meta b/Assets/ARDK/AR/Awareness/Semantics/Generators.meta new file mode 100644 index 0000000..b5a784b --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Semantics/Generators.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d12607ed4606e458c8c7fd2a8e5b78e2 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Awareness/Semantics/Generators/IDepthPointCloud.cs b/Assets/ARDK/AR/Awareness/Semantics/Generators/IDepthPointCloud.cs new file mode 100644 index 0000000..9aa6bef --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Semantics/Generators/IDepthPointCloud.cs @@ -0,0 +1,27 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.ObjectModel; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Depth +{ + /// + /// Represents a depth point cloud. + /// + public interface IDepthPointCloud: + IDisposable + { + /// + /// The collection of world-space depth points. + /// + ReadOnlyCollection Points { get; } + + /// The width of the depth point cloud, from the camera's perspective + UInt32 Width { get; } + + /// The height of the depth point cloud, from the camera's perspective + UInt32 Height { get; } + } +} diff --git a/Assets/ARDK/AR/Awareness/Semantics/Generators/IDepthPointCloud.cs.meta b/Assets/ARDK/AR/Awareness/Semantics/Generators/IDepthPointCloud.cs.meta new file mode 100644 index 0000000..194e8c7 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Semantics/Generators/IDepthPointCloud.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d7113a65cf07a4347b283c77d8617489 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Awareness/Semantics/Generators/_DepthPointCloud.cs b/Assets/ARDK/AR/Awareness/Semantics/Generators/_DepthPointCloud.cs new file mode 100644 index 0000000..2eaba58 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Semantics/Generators/_DepthPointCloud.cs @@ -0,0 +1,38 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; + +using Niantic.ARDK.AR; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Depth +{ + [Serializable] + internal sealed class _DepthPointCloud : IDepthPointCloud + { + internal _DepthPointCloud + ( + ReadOnlyCollection points, + UInt32 width, + UInt32 height + ) + { + Points = points; + Width = width; + Height = height; + } + + public ReadOnlyCollection Points { get; } + public UInt32 Width { get; } + public UInt32 Height { get; } + + void IDisposable.Dispose() + { + // Do nothing as this object is fully managed. + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/AR/Awareness/Semantics/Generators/_DepthPointCloud.cs.meta b/Assets/ARDK/AR/Awareness/Semantics/Generators/_DepthPointCloud.cs.meta new file mode 100644 index 0000000..581cc86 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Semantics/Generators/_DepthPointCloud.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f2f253d9fb34a4474a97cf89436b1037 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Awareness/Semantics/IAwarenessBufferProcessor.cs b/Assets/ARDK/AR/Awareness/Semantics/IAwarenessBufferProcessor.cs new file mode 100644 index 0000000..64ef00e --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Semantics/IAwarenessBufferProcessor.cs @@ -0,0 +1,20 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using UnityEngine; + +namespace Niantic.ARDK.AR.Awareness +{ + public interface IAwarenessBufferProcessor + { + /// A composited matrix to fit the awareness buffer to the screen. + /// This affine transform converts normalized screen coordinates to + /// the buffer's coordinate frame while accounting for interpolation. + Matrix4x4 SamplerTransform { get; } + + /// The current interpolation setting. + InterpolationMode InterpolationMode { get; set; } + + /// The current setting whether to align with close (0.0f) or distant pixels (1.0f) + /// during interpolation. + float InterpolationPreference { get; set; } + } +} diff --git a/Assets/ARDK/AR/Awareness/Semantics/IAwarenessBufferProcessor.cs.meta b/Assets/ARDK/AR/Awareness/Semantics/IAwarenessBufferProcessor.cs.meta new file mode 100644 index 0000000..0bbc096 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Semantics/IAwarenessBufferProcessor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ead6ab08a4894332ab60f20d3e28823b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Awareness/Semantics/ISemanticBuffer.cs b/Assets/ARDK/AR/Awareness/Semantics/ISemanticBuffer.cs new file mode 100644 index 0000000..15e0840 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Semantics/ISemanticBuffer.cs @@ -0,0 +1,143 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Awareness.Semantics +{ + public interface ISemanticBuffer : IDataBuffer, IDisposable + { + /// The number of channels contained in this buffer. + uint ChannelCount { get; } + + /// An array of semantic class names, in the order their channels appear in the data. + string[] ChannelNames { get; } + + /// Get the channel index of a specified semantic class. + /// @param channelName Name of semantic class. + /// @returns The index of the specified semantic class, or -1 if the channel does not exist. + int GetChannelIndex(string channelName); + + /// Get a mask with only the specified channel's bit enabled. Can be used to quickly check if + /// a channel exists at a particular pixel in this semantic buffer. + /// @param channelIndex Channel index of the semantic class to mask for. + /// @returns A mask with only the specified channel's bit enabled. + UInt32 GetChannelTextureMask(int channelIndex); + + /// Get a mask with only the specified channels' bits enabled. Can be used to quickly check if + /// a set of channels exists at a particular pixel in this semantic buffer. + /// @param channelIndices Channel indices of the semantic classes to mask for. + /// @returns A mask with only the specified channels' bits enabled. + UInt32 GetChannelTextureMask(int[] channelIndices); + + /// Get a mask with only the specified channel's bit enabled. Can be used to quickly check if + /// a channel exists at a particular pixel in this semantic buffer. + /// @param channelName Name of the semantic class to mask for. + /// @returns A mask with only the specified channel's bit enabled. + UInt32 GetChannelTextureMask(string channelName); + + /// Get a mask with only the specified channels' bits enabled. Can be used to quickly check if + /// a set of channels exists at a particular pixel in this semantic buffer. + /// @param channelNames Names of the semantic classes to mask for. + /// @returns A mask with only the specified channels' bits enabled. + UInt32 GetChannelTextureMask(string[] channelNames); + + /// Check if a pixel in this semantic buffer contains a certain channel. + /// @param x Pixel position on the x-axis. + /// @param y Pixel position on the y-axis. + /// @param channelIndex Channel index of the semantic class to look for. + /// @returns True if the channel exists at the given coordinates. + bool DoesChannelExistAt(int x, int y, int channelIndex); + + /// Check if a pixel in this semantic buffer contains a certain channel. + /// @param x Pixel position on the x-axis. + /// @param y Pixel position on the y-axis. + /// @param channelName Name of the semantic class to look for. + /// @returns True if the channel exists at the given coordinates. + bool DoesChannelExistAt(int x, int y, string channelName); + + /// Check if a pixel in this semantic buffer contains a certain channel. + /// This method samples the semantics buffer using normalised texture coordinates. + /// @param uv Normalised texture coordinates. The bottom-left is (0,1); the top-right is (1,0). + /// @param channelIndex Channel index of the semantic class to look for. + /// @returns True if the channel exists at the given coordinates. + bool DoesChannelExistAt(Vector2 uv, int channelIndex); + + /// Check if a pixel in this semantic buffer contains a certain channel. + /// This method samples the semantics buffer using normalised texture coordinates. + /// @param uv Normalised texture coordinates. The bottom-left is (0,1); the top-right is (1,0). + /// @param channelName Name of the semantic class to look for. + /// @returns True if the channel exists at the given coordinates. + bool DoesChannelExistAt(Vector2 uv, string channelName); + + /// Check if a certain channel exists anywhere in this buffer. + /// @param channelIndex Channel index of the semantic class to look for. + /// @returns True if the channel exists. + bool DoesChannelExist(int channelIndex); + + /// Check if a certain channel exists anywhere in this buffer. + /// @param channelName Name of the semantic class to look for. + /// @returns True if the channel exists. + bool DoesChannelExist(string channelName); + + /// Update (or create, if needed) a texture with data of one of this buffer's channels. + /// @param texture + /// Reference to the texture to copy to. This method will create a texture if the reference + /// is null. + /// @param channelIndex + /// Channel index of the semantic class to copy. + /// @param filterMode + /// Texture filtering mode. + /// @returns True if the buffer was successfully copied to the given texture. + bool CreateOrUpdateTextureARGB32 + ( + ref Texture2D texture, + int channelIndex, + FilterMode filterMode = FilterMode.Point + ); + + /// Update (or create, if needed) a texture with data composited of multiple channels from this buffer. + /// @param texture + /// Reference to the texture to copy to. This method will create a texture if the reference + /// is null. + /// @param channels + /// Semantic channel indices to copy to this texture. + /// @param filterMode + /// Texture filtering mode. + /// @returns True if the buffer was successfully copied to the given texture. + bool CreateOrUpdateTextureARGB32 + ( + ref Texture2D texture, + int[] channels, + FilterMode filterMode = FilterMode.Point + ); + + /// Update (or create, if needed) a texture with this data of the entire buffer. + /// @param croppedRect + /// Rectangle defining how to crop the buffer's data before copying to the texture. + /// @param texture + /// Reference to the texture to copy to. This method will create a texture if the reference + /// is null. + /// @returns True if the buffer was successfully copied to the given texture. + bool CreateOrUpdateTextureRFloat(ref Texture2D texture, FilterMode filterMode = FilterMode.Point); + + /// Returns the nearest value to the specified normalized coordinates in the buffer. + /// @param uv + /// Normalized coordinates. + /// @returns + /// The value in the semantic buffer at the nearest location to the coordinates. + UInt32 Sample(Vector2 uv); + + /// Returns the nearest value to the specified normalized coordinates in the buffer. + /// @param uv + /// Normalized coordinates. + /// @param transform + /// 2D transformation applied to normalized coordinates before sampling. + /// This transformation should convert to the depth buffer's coordinate frame. + /// @returns + /// The value in the semantic buffer at the nearest location to the + /// transformed coordinates. + UInt32 Sample(Vector2 uv, Matrix4x4 transform); + } +} diff --git a/Assets/ARDK/AR/Awareness/Semantics/ISemanticBuffer.cs.meta b/Assets/ARDK/AR/Awareness/Semantics/ISemanticBuffer.cs.meta new file mode 100644 index 0000000..c7e6af0 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Semantics/ISemanticBuffer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 93cb53500879044a1a979f928e9adcb4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Awareness/Semantics/ISemanticBufferProcessor.cs b/Assets/ARDK/AR/Awareness/Semantics/ISemanticBufferProcessor.cs new file mode 100644 index 0000000..2c39f60 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Semantics/ISemanticBufferProcessor.cs @@ -0,0 +1,76 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using Niantic.ARDK.AR.Awareness; +using Niantic.ARDK.AR.Awareness.Semantics; + +using UnityEngine; + +namespace Niantic.ARDK.AR +{ + public interface ISemanticBufferProcessor: + IAwarenessBufferProcessor + { + /// The CPU copy of the latest awareness buffer. + ISemanticBuffer AwarenessBuffer { get; } + + /// The number of classes available. + uint ChannelCount { get; } + + /// Returns the possible semantic classes that a pixel can be interpreted. + string[] Channels { get; } + + /// Returns the semantics of the specified pixel. + /// @param viewportX Horizontal coordinate in viewport space. + /// @param viewportY Vertical coordinate in viewport space. + /// @returns The result is a 32-bit packed unsigned integer + /// where each bit is a binary indicator for a class. + uint GetSemantics(int viewportX, int viewportY); + + /// Returns an array of channel indices that are present for the specified pixel. + /// @note This query allocates garbage. + /// @param viewportX Horizontal coordinate in viewport space. + /// @param viewportY Vertical coordinate in viewport space. + /// @returns An array of channel indices present for the pixel. + int[] GetChannelIndicesAt(int viewportX, int viewportY); + + /// Returns an array of channel names that are present for the specified pixel. + /// @note This query allocates garbage. + /// @param viewportX Horizontal coordinate in viewport space. + /// @param viewportY Vertical coordinate in viewport space. + /// @returns An array of channel names present for the pixel. + string[] GetChannelNamesAt(int viewportX, int viewportY); + + /// Check if a pixel is of a certain semantics class. + /// @param viewportX Horizontal coordinate in viewport space. + /// @param viewportY Vertical coordinate in viewport space. + /// @param channelIndex Channel index of the semantic class to look for. + /// @returns True if the semantic channel exists at the given coordinates. + bool DoesChannelExistAt(int viewportX, int viewportY, int channelIndex); + + /// Check if a pixel is of a certain semantics class. + /// @param viewportX Horizontal coordinate in viewport space. + /// @param viewportY Vertical coordinate in viewport space. + /// @param channelName Name of the semantic class to look for. + /// @returns True if the semantic channel exists at the given coordinates. + bool DoesChannelExistAt(int viewportX, int viewportY, string channelName); + + /// Pushes the current state of the semantics buffer to the specified target texture. + /// The resulting texture will contain a display aligned representation of the specified channel. + /// @note Only use this call if you absolutely need the texture to be display aligned. + /// It is faster to create a texture from the awareness buffer itself. + /// @param channel The semantic channel index to create a texture of. + /// @param texture The target texture. If this texture does not exist, it will be created. + /// It is the responsibility of the caller to release this texture. + /// @param orientation The target orientation of the texture. This determines the resolution of + /// the container. This has to be either landscape or portrait. + void CopyToAlignedTextureARGB32(int channel, ref Texture2D texture, ScreenOrientation orientation); + + /// Pushes the current state of the semantics buffer to the specified target texture. + /// The resulting texture will contain a display aligned representation of the specified channels. + /// @param channels The semantic channel indices to create a texture of. + /// @param texture The target texture. If this texture does not exist, it will be created. + /// It is the responsibility of the caller to release this texture. + /// @param orientation The target orientation of the texture. This determines the resolution of + /// the container. This has to be either landscape or portrait. + void CopyToAlignedTextureARGB32(int[] channels, ref Texture2D texture, ScreenOrientation orientation); + } +} \ No newline at end of file diff --git a/Assets/ARDK/AR/Awareness/Semantics/ISemanticBufferProcessor.cs.meta b/Assets/ARDK/AR/Awareness/Semantics/ISemanticBufferProcessor.cs.meta new file mode 100644 index 0000000..e4c2c83 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Semantics/ISemanticBufferProcessor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 81dac102adcb475fbac0a45e5812919a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Awareness/Semantics/SemanticsProvider.meta b/Assets/ARDK/AR/Awareness/Semantics/SemanticsProvider.meta new file mode 100644 index 0000000..c5ecbbc --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Semantics/SemanticsProvider.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0dd4f4f0672d4280844b5d7a4e5bae66 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Awareness/Semantics/SemanticsProvider/SemanticBufferProcessor.cs b/Assets/ARDK/AR/Awareness/Semantics/SemanticsProvider/SemanticBufferProcessor.cs new file mode 100644 index 0000000..94586a8 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Semantics/SemanticsProvider/SemanticBufferProcessor.cs @@ -0,0 +1,232 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; +using System.Collections.Generic; +using System.Linq; + +using Niantic.ARDK.AR.ARSessionEventArgs; +using Niantic.ARDK.Rendering; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Awareness.Semantics +{ + public class SemanticBufferProcessor: + AwarenessBufferProcessor, + ISemanticBufferProcessor + { + // The currently active AR session + private IARSession _session; + + // The render target descriptor used to determine the viewport resolution + private RenderTarget _viewport; + + /// Allocates a new semantic buffer processor. By default, the + /// awareness buffer will be fit to the main camera's viewport. + public SemanticBufferProcessor() + { + _viewport = UnityEngine.Camera.main; + ARSessionFactory.SessionInitialized += OnARSessionInitialized; + } + + /// Allocates a new semantic buffer processor. + /// @param viewport Determines the target viewport to fit the awareness buffer to. + public SemanticBufferProcessor(RenderTarget viewport) + { + _viewport = viewport; + ARSessionFactory.SessionInitialized += OnARSessionInitialized; + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + ARSessionFactory.SessionInitialized -= OnARSessionInitialized; + if (_session != null) + _session.FrameUpdated -= OnFrameUpdated; + } + + private void OnARSessionInitialized(AnyARSessionInitializedArgs args) + { + if (_session != null) + _session.FrameUpdated -= OnFrameUpdated; + + _session = args.Session; + _session.FrameUpdated += OnFrameUpdated; + } + + private void OnFrameUpdated(FrameUpdatedArgs args) + { + var frame = args.Frame; + if (frame == null) + return; + + var orientation = RenderTarget.ScreenOrientation; + + _ProcessFrame + ( + frame, + buffer: frame.Semantics, + targetResolution: _viewport.GetResolution(forOrientation: orientation), + targetOrientation: orientation + ); + } + + /// Assigns a new render target descriptor for the semantics processor. + /// The render target defines the viewport attributes to correctly fit + /// the semantics buffer. + public void AssignViewport(RenderTarget target) + { + _viewport = target; + } + + /// The number of classes available. + public uint ChannelCount + { + get => AwarenessBuffer?.ChannelCount ?? 0; + } + + /// Returns the possible semantic classes that a pixel can be interpreted. + public string[] Channels + { + get => AwarenessBuffer?.ChannelNames; + } + + /// + public uint GetSemantics(int viewportX, int viewportY) + { + var semanticsBuffer = AwarenessBuffer; + if (semanticsBuffer == null) + return 0u; + + // Get normalized coordinates + var x = viewportX + 0.5f; + var y = viewportY + 0.5f; + var resolution = _viewport.GetResolution(RenderTarget.ScreenOrientation); + var uv = new Vector3(x / resolution.width, y / resolution.height, 1.0f); + + return AwarenessBuffer.Sample(uv, SamplerTransform); + } + + /// + public int[] GetChannelIndicesAt(int viewportX, int viewportY) + { + var semanticsBuffer = AwarenessBuffer; + if (semanticsBuffer == null) + return Array.Empty(); + + var buffer = AwarenessBuffer; + int count = (int)ChannelCount; + var semantics = GetSemantics(viewportX, viewportY); + + var result = new List(capacity: count); + for (int i = 0; i < count; i++) + { + var mask = buffer.GetChannelTextureMask(i); + if ((semantics & mask) != 0u) + result.Add(i); + } + + return result.ToArray(); + } + + /// + public string[] GetChannelNamesAt(int viewportX, int viewportY) + { + var semanticsBuffer = AwarenessBuffer; + if (semanticsBuffer == null) + return Array.Empty(); + + var buffer = AwarenessBuffer; + var channels = Channels; + var semantics = GetSemantics(viewportX, viewportY); + + return ( + from channel in channels + let mask = buffer.GetChannelTextureMask(channel) + where (semantics & mask) != 0u + select channel).ToArray(); + } + + /// + public bool DoesChannelExistAt(int viewportX, int viewportY, int channelIndex) + { + var semantics = GetSemantics(viewportX, viewportY); + var bitMask = AwarenessBuffer.GetChannelTextureMask(channelIndex); + + return (semantics & bitMask) != 0u; + } + + /// + public bool DoesChannelExistAt(int viewportX, int viewportY, string channelName) + { + var semantics = GetSemantics(viewportX, viewportY); + var bitMask = AwarenessBuffer.GetChannelTextureMask(channelName); + + return (semantics & bitMask) != 0u; + } + + public void CopyToAlignedTextureARGB32(int channel, ref Texture2D texture, ScreenOrientation orientation) + { + if (AwarenessBuffer == null) + return; + + // Get a typed buffer + ISemanticBuffer semanticsBuffer = AwarenessBuffer; + + // Acquire the affine transform for the buffer + var transform = SamplerTransform; + + // Determine the bit mask for the requested semantic classes + var bitMask = AwarenessBuffer.GetChannelTextureMask(channel); + + // Call base method + CreateOrUpdateTextureARGB32 + ( + ref texture, + orientation, + + // The sampler function needs to be defined such that given a destination + // texture coordinate, what color needs to be written to that position? + // We sample the typed awareness buffer and apply the channel bitmask. + // White means the pixel contains at least one of the requested semantic + // classes. The resulting texture is display aligned, that's why we sample + // using the buffer's affine matrix. + sampler: uv => (semanticsBuffer.Sample(uv, transform) & bitMask) != 0u + ? Color.white + : Color.clear + ); + } + + public void CopyToAlignedTextureARGB32(int[] channels, ref Texture2D texture, ScreenOrientation orientation) + { + if (AwarenessBuffer == null) + return; + + // Get a typed buffer + ISemanticBuffer semanticsBuffer = AwarenessBuffer; + + // Acquire the affine transform for the buffer + var transform = SamplerTransform; + + // Determine the bit mask for the requested semantic classes + var bitMask = AwarenessBuffer.GetChannelTextureMask(channels); + + // Call base method + CreateOrUpdateTextureARGB32 + ( + ref texture, + orientation, + + // The sampler function needs to be defined such that given a destination + // texture coordinate, what color needs to be written to that position? + // We sample the typed awareness buffer and apply the channel bitmask. + // White means the pixel contains at least one of the requested semantic + // classes. The resulting texture is display aligned, that's why we sample + // using the buffer's affine matrix. + sampler: uv => (semanticsBuffer.Sample(uv, transform) & bitMask) != 0u + ? Color.white + : Color.clear + ); + } + } +} diff --git a/Assets/ARDK/AR/Awareness/Semantics/SemanticsProvider/SemanticBufferProcessor.cs.meta b/Assets/ARDK/AR/Awareness/Semantics/SemanticsProvider/SemanticBufferProcessor.cs.meta new file mode 100644 index 0000000..523ad4d --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Semantics/SemanticsProvider/SemanticBufferProcessor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c7f071f38aa749f4bf8eb40b281752a2 +timeCreated: 1629463373 \ No newline at end of file diff --git a/Assets/ARDK/AR/Awareness/Semantics/_NativeSemanticBuffer.cs b/Assets/ARDK/AR/Awareness/Semantics/_NativeSemanticBuffer.cs new file mode 100644 index 0000000..7e678aa --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Semantics/_NativeSemanticBuffer.cs @@ -0,0 +1,488 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Internals; + +using System; +using System.Runtime.InteropServices; + +using Niantic.ARDK.AR.Camera; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Awareness.Semantics +{ + internal sealed class _NativeSemanticBuffer: + _NativeAwarenessBufferBase, + ISemanticBuffer + { + public const int BitsPerPixel = sizeof(UInt32) * 8; + + private string[] _channelNames; + + static _NativeSemanticBuffer() + { + Platform.Init(); + } + + internal _NativeSemanticBuffer(IntPtr nativeHandle, float worldScale, CameraIntrinsics intrinsics) + : base + ( + nativeHandle, + worldScale, + GetNativeWidth(nativeHandle), + GetNativeHeight(nativeHandle), + IsNativeKeyframe(nativeHandle), + intrinsics + ) + { + } + + public uint ChannelCount + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _SemanticBuffer_GetNumberChannels(_nativeHandle); + +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + } + + public string[] ChannelNames + { + get + { + if (_channelNames == null) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + var ptrNames = new IntPtr[ChannelCount]; + if (ChannelCount > 0 && _SemanticBuffer_GetNames(_nativeHandle, ptrNames)) + { + _channelNames = new string[ChannelCount]; + for (int i = 0; i < ChannelCount; i++) + if (ptrNames[i] != IntPtr.Zero) + _channelNames[i] = Marshal.PtrToStringAnsi(ptrNames[i]); + } + else + { + _channelNames = new string[0]; + } + } + else + { +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + } + + return _channelNames; + } + } + + public int GetChannelIndex(string channelName) + { + var index = Array.IndexOf(ChannelNames, channelName); + + if (index < 0) + { + string suggestion = string.Empty; + var lowercase = channelName.ToLower(); + + if (Array.IndexOf(ChannelNames, lowercase) >= 0) + suggestion = string.Format("Did you mean \"{0}\"?", lowercase); + + ARLog._ErrorFormat + ( + "Invalid channelName \"{0}\". {1}", + channelName, + suggestion + ); + } + + return index; + } + + public UInt32 GetChannelTextureMask(int channelIndex) + { + // test for invalid index + if (channelIndex < 0 || channelIndex >= ChannelNames.Length) + return 0; + + return 1u << (BitsPerPixel - 1 - channelIndex); + } + + public UInt32 GetChannelTextureMask(int[] channelIndices) + { + UInt32 mask = 0; + + for (int i = 0; i < channelIndices.Length; i++) + mask |= GetChannelTextureMask(channelIndices[i]); + + return mask; + } + + public UInt32 GetChannelTextureMask(string channelName) + { + var index = GetChannelIndex(channelName); + return GetChannelTextureMask(index); + } + + public UInt32 GetChannelTextureMask(string[] channelNames) + { + UInt32 mask = 0; + + for (int i = 0; i < channelNames.Length; i++) + mask |= GetChannelTextureMask(channelNames[i]); + + return mask; + } + + public bool DoesChannelExistAt(int x, int y, int channelIndex) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _SemanticBuffer_DoesChannelExistAt(_nativeHandle, x, y, channelIndex); + +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + + public bool DoesChannelExistAt(int x, int y, string channelName) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _SemanticBuffer_DoesChannelExistAtByName(_nativeHandle, x, y, channelName); + +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + + public bool DoesChannelExistAt(Vector2 uv, int channelIndex) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _SemanticBuffer_DoesChannelExistAtNormalised(_nativeHandle, uv.x, uv.y, channelIndex); + +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + + public bool DoesChannelExistAt(Vector2 uv, string channelName) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + return + _SemanticBuffer_DoesChannelExistAtNormalisedByName + ( + _nativeHandle, + uv.x, + uv.y, + channelName + ); + } + +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + + public bool DoesChannelExist(int channelIndex) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _SemanticBuffer_DoesChannelExist(_nativeHandle, channelIndex); + +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + + public bool DoesChannelExist(string channelName) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _SemanticBuffer_DoesChannelExistByName(_nativeHandle, channelName); + +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + + /// + public bool CreateOrUpdateTextureARGB32 + ( + ref Texture2D texture, + int channelIndex, + FilterMode filterMode = FilterMode.Point + ) + { + uint flag = 1u << (BitsPerPixel - 1 - channelIndex); + return _AwarenessBufferHelper._CreateOrUpdateTextureARGB32 + ( + Data, + (int)Width, + (int)Height, + ref texture, + filterMode, + val => (val & flag) != 0 ? 1.0f : 0.0f + ); + } + + public bool CreateOrUpdateTextureARGB32 + ( + ref Texture2D texture, + int[] channels, + FilterMode filterMode = FilterMode.Point + ) + { + uint flag = GetChannelTextureMask(channels); + return _AwarenessBufferHelper._CreateOrUpdateTextureARGB32 + ( + Data, + (int)Width, + (int)Height, + ref texture, + filterMode, + val => (val & flag) != 0 ? 1.0f : 0.0f + ); + } + + /// + public bool CreateOrUpdateTextureRFloat + ( + ref Texture2D texture, + FilterMode filterMode = FilterMode.Point + ) + { + return _AwarenessBufferHelper._CreateOrUpdateTextureRFloat + ( + Data, + (int)Width, + (int)Height, + ref texture, + filterMode + ); + } + + public override IAwarenessBuffer GetCopy() + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + var newHandle = _SemanticBuffer_GetCopy(_nativeHandle); + return new _NativeSemanticBuffer(newHandle, _worldScale, Intrinsics); + } + +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + + public UInt32 Sample(Vector2 uv) + { + var w = (int)Width; + var h = (int)Height; + + var x = Mathf.Clamp(Mathf.RoundToInt(uv.x * w - 0.5f), 0, w - 1); + var y = Mathf.Clamp(Mathf.RoundToInt(uv.y * h - 0.5f), 0, h - 1); + + return Data[x + w * y]; + } + + public UInt32 Sample(Vector2 uv, Matrix4x4 transform) + { + var w = (int)Width; + var h = (int)Height; + + var st = transform * new Vector4(uv.x, uv.y, 1.0f, 1.0f); + var sx = st.x / st.z; + var sy = st.y / st.z; + + var x = Mathf.Clamp(Mathf.RoundToInt(sx * w - 0.5f), 0, w - 1); + var y = Mathf.Clamp(Mathf.RoundToInt(sy * h - 0.5f), 0, h - 1); + + return Data[x + w * y]; + } + + protected override void _GetViewMatrix(float[] outViewMatrix) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _SemanticBuffer_GetView(_nativeHandle, outViewMatrix); +#pragma warning disable 0162 + else + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + + protected override void _GetIntrinsics(float[] outVector) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _SemanticBuffer_GetIntrinsics(_nativeHandle, outVector); +#pragma warning disable 0162 + else + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + + protected override void _OnRelease() + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _SemanticBuffer_Release(_nativeHandle); +#pragma warning disable 0162 + else + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + + protected override IntPtr _GetDataAddress() + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _SemanticBuffer_GetDataAddress(_nativeHandle); +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + + private static uint GetNativeWidth(IntPtr nativeHandle) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _SemanticBuffer_GetWidth(nativeHandle); +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + + private static uint GetNativeHeight(IntPtr nativeHandle) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _SemanticBuffer_GetHeight(nativeHandle); +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + + + private static bool IsNativeKeyframe(IntPtr nativeHandle) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _SemanticBuffer_IsKeyframe(nativeHandle); +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _SemanticBuffer_Release(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern UInt32 _SemanticBuffer_GetWidth(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern UInt32 _SemanticBuffer_GetHeight(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern bool _SemanticBuffer_IsKeyframe(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _SemanticBuffer_GetView(IntPtr nativeHandle, float[] outViewMatrix); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _SemanticBuffer_GetIntrinsics(IntPtr nativeHandle, float[] outVector); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _SemanticBuffer_GetDataAddress(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern UInt32 _SemanticBuffer_GetNumberChannels(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern float _SemanticBuffer_GetNearDistance(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern float _SemanticBuffer_GetFarDistance(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern bool _SemanticBuffer_GetNames + ( + IntPtr nativeHandle, + IntPtr[] outNames + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern bool _SemanticBuffer_DoesChannelExistAt + ( + IntPtr nativeHandle, + Int32 x, + Int32 y, + Int32 channelIndex + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern bool _SemanticBuffer_DoesChannelExistAtByName + ( + IntPtr nativeHandle, + Int32 x, + Int32 y, + string channelName + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern bool _SemanticBuffer_DoesChannelExistAtNormalised + ( + IntPtr nativeHandle, + float u, + float v, + Int32 channelIndex + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern bool _SemanticBuffer_DoesChannelExistAtNormalisedByName + ( + IntPtr nativeHandle, + float u, + float v, + string channelName + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern bool _SemanticBuffer_DoesChannelExistAtViewpoint + ( + IntPtr nativeHandle, + float pointX, + float pointY, + Int32 viewportWidth, + Int32 viewportHeight, + Int32 channelIndex + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern bool _SemanticBuffer_DoesChannelExistAtViewpointByName + ( + IntPtr nativeHandle, + float pointX, + float pointY, + Int32 viewportWidth, + Int32 viewportHeight, + string channelName + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern bool _SemanticBuffer_DoesChannelExist + ( + IntPtr nativeHandle, + Int32 channelIndex + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern bool _SemanticBuffer_DoesChannelExistByName + ( + IntPtr nativeHandle, + string channelName + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _SemanticBuffer_GetCopy(IntPtr nativeHandle); + } +} diff --git a/Assets/ARDK/AR/Awareness/Semantics/_NativeSemanticBuffer.cs.meta b/Assets/ARDK/AR/Awareness/Semantics/_NativeSemanticBuffer.cs.meta new file mode 100644 index 0000000..e76eb71 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Semantics/_NativeSemanticBuffer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 046ce6bd3bb6478ca737a7cc63d11453 +timeCreated: 1607725617 \ No newline at end of file diff --git a/Assets/ARDK/AR/Awareness/Semantics/_SerializableSemanticBuffer.cs b/Assets/ARDK/AR/Awareness/Semantics/_SerializableSemanticBuffer.cs new file mode 100644 index 0000000..25b4d0f --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Semantics/_SerializableSemanticBuffer.cs @@ -0,0 +1,289 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Linq; +using System.Runtime.InteropServices; + +using Niantic.ARDK.AR.Awareness; +using Niantic.ARDK.AR.Camera; +using Niantic.ARDK.Utilities.Logging; + +using Unity.Collections; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Awareness.Semantics +{ + // Can't use [Serializable]. Need to provide a serializer. + internal sealed class _SerializableSemanticBuffer: + _SerializableAwarenessBufferBase, + ISemanticBuffer + { + private static bool _hasWarnedAboutInterpolation; + private bool[] _hasChannelCache; + + internal _SerializableSemanticBuffer + ( + uint width, + uint height, + bool isKeyframe, + Matrix4x4 viewMatrix, + NativeArray data, + string[] channelNames, + CameraIntrinsics intrinsics + ) + : base(width, height, isKeyframe, viewMatrix, data, intrinsics) + { + ChannelCount = (uint)channelNames.Length; + ChannelNames = channelNames; + } + + /// + public uint ChannelCount { get; private set; } + + /// + public string[] ChannelNames { get; private set; } + + /// + public int GetChannelIndex(string channelName) + { + var index = Array.IndexOf(ChannelNames, channelName); + + if (index < 0) + { + string suggestion = string.Empty; + var lowercase = channelName.ToLower(); + + if (Array.IndexOf(ChannelNames, lowercase) >= 0) + suggestion = string.Format("Did you mean \"{0}\"?", lowercase); + + ARLog._ErrorFormat + ( + "Invalid channelName \"{0}\". {1}", + channelName, + suggestion + ); + } + + return index; + } + + /// + public UInt32 GetChannelTextureMask(int channelIndex) + { + // test for invalid index + if (channelIndex < 0 || channelIndex >= ChannelNames.Length) + return 0; + + return 1u << (_NativeSemanticBuffer.BitsPerPixel - 1 - channelIndex); + } + + /// + public UInt32 GetChannelTextureMask(int[] channelIndices) + { + UInt32 mask = 0; + + for (int i = 0; i < channelIndices.Length; i++) + { + mask |= GetChannelTextureMask(channelIndices[i]); + } + + return mask; + } + + /// + public UInt32 GetChannelTextureMask(string channelName) + { + var index = GetChannelIndex(channelName); + + return GetChannelTextureMask(index); + } + + /// + public UInt32 GetChannelTextureMask(string[] channelNames) + { + UInt32 mask = 0; + + for (int i = 0; i < channelNames.Length; i++) + { + mask |= GetChannelTextureMask(channelNames[i]); + } + + return mask; + } + + /// + public bool DoesChannelExistAt(int x, int y, int channelIndex) + { + var data = Data; + var value = data[x + y * (int) Width]; + var flag = 1u << (_NativeSemanticBuffer.BitsPerPixel - 1) - channelIndex; + return (value & flag) != 0; + } + + /// + public bool DoesChannelExistAt(int x, int y, string channelName) + { + var index = GetChannelIndex(channelName); + return index != -1 && DoesChannelExistAt(x, y, index); + } + + /// + public bool DoesChannelExistAt(Vector2 uv, int channelIndex) + { + var widthMinusOne = (int)Width - 1; + var heightMinusOne = (int)Height - 1; + + // Sample the buffer + var x = Mathf.Clamp((int)Mathf.Floor(uv.x * widthMinusOne), 0, widthMinusOne); + var y = Mathf.Clamp((int)Mathf.Floor(uv.y * heightMinusOne), 0, heightMinusOne); + + return DoesChannelExistAt(x, y, channelIndex); + } + + /// + public bool DoesChannelExistAt(Vector2 uv, string channelName) + { + var index = GetChannelIndex(channelName); + return index != -1 && DoesChannelExistAt(uv, index); + } + + /// + public bool DoesChannelExist(int channelIndex) + { + _ComputeHasChannelCache(); + return _hasChannelCache != null && (channelIndex < ChannelCount) && _hasChannelCache[channelIndex]; + } + + public bool DoesChannelExist(string channelName) + { + var index = Array.IndexOf(ChannelNames, channelName); + return index != -1 && DoesChannelExist(index); + } + + public UInt32 Sample(Vector2 uv) + { + var w = (int)Width; + var h = (int)Height; + + var x = Mathf.Clamp(Mathf.RoundToInt(uv.x * w - 0.5f), 0, w - 1); + var y = Mathf.Clamp(Mathf.RoundToInt(uv.y * h - 0.5f), 0, h - 1); + + return Data[x + w * y]; + } + + public UInt32 Sample(Vector2 uv, Matrix4x4 transform) + { + var w = (int)Width; + var h = (int)Height; + + var st = transform * new Vector4(uv.x, uv.y, 1.0f, 1.0f); + var sx = st.x / st.z; + var sy = st.y / st.z; + + var x = Mathf.Clamp(Mathf.RoundToInt(sx * w - 0.5f), 0, w - 1); + var y = Mathf.Clamp(Mathf.RoundToInt(sy * h - 0.5f), 0, h - 1); + + return Data[x + w * y]; + } + + /// + public bool CreateOrUpdateTextureARGB32 + ( + ref Texture2D texture, + int channelIndex, + FilterMode filterMode = FilterMode.Point + ) + { + uint flag = 1u << (_NativeSemanticBuffer.BitsPerPixel - 1 - channelIndex); + return _AwarenessBufferHelper._CreateOrUpdateTextureARGB32 + ( + Data, + (int)Width, + (int)Height, + ref texture, + filterMode, + val => (val & flag) != 0 ? 1.0f : 0.0f + ); + } + + public bool CreateOrUpdateTextureARGB32 + ( + ref Texture2D texture, + int[] channels, + FilterMode filterMode = FilterMode.Point + ) + { + uint flag = GetChannelTextureMask(channels); + return _AwarenessBufferHelper._CreateOrUpdateTextureARGB32 + ( + Data, + (int)Width, + (int)Height, + ref texture, + filterMode, + val => (val & flag) != 0 ? 1.0f : 0.0f + ); + } + + /// + public bool CreateOrUpdateTextureRFloat + ( + ref Texture2D texture, + FilterMode filterMode = FilterMode.Point + ) + { + return _AwarenessBufferHelper._CreateOrUpdateTextureRFloat + ( + Data, + (int)Width, + (int)Height, + ref texture, + filterMode + ); + } + + public override IAwarenessBuffer GetCopy() + { + return new _SerializableSemanticBuffer + ( + Width, + Height, + false, + ViewMatrix, + new NativeArray(Data, Allocator.Persistent), + ChannelNames, + Intrinsics + ); + } + + /// + /// Calculate if this image has a specific channel or not by caching all the values and see + /// which channels are present + /// + private void _ComputeHasChannelCache() + { + if (_hasChannelCache == null && Data != null && Data.Length > 0) + { + var bitsPerPixel = Marshal.SizeOf(Data[0]) * 8; + + _hasChannelCache = new bool[ChannelCount]; + + foreach (var pixel in Data) + { + for (var i = 0; i < ChannelCount; i++) + { + if (!_hasChannelCache[i]) + { + var flag = 1u << (bitsPerPixel - 1) - i; + if ((pixel & flag) != 0) + { + _hasChannelCache[i] = true; + } + } + } + } + } + } + } +} diff --git a/Assets/ARDK/AR/Awareness/Semantics/_SerializableSemanticBuffer.cs.meta b/Assets/ARDK/AR/Awareness/Semantics/_SerializableSemanticBuffer.cs.meta new file mode 100644 index 0000000..dd80a74 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Semantics/_SerializableSemanticBuffer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8b21a56f953d94ed68fc430c8bdc6ce2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Awareness/Semantics/_SerializableSemanticBufferSerializer.cs b/Assets/ARDK/AR/Awareness/Semantics/_SerializableSemanticBufferSerializer.cs new file mode 100644 index 0000000..31fc874 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Semantics/_SerializableSemanticBufferSerializer.cs @@ -0,0 +1,74 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.Utilities.BinarySerialization; +using Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers; + +using Niantic.ARDK.AR.Awareness; +using Niantic.ARDK.AR.Camera; + +using Unity.Collections; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Awareness.Semantics +{ + internal sealed class _SerializableSemanticBufferSerializer: + _SerializableAwarenessBufferSerializer<_SerializableSemanticBuffer, UInt32> + { + internal static readonly _SerializableSemanticBufferSerializer _instance = + new _SerializableSemanticBufferSerializer(); + + private _SerializableSemanticBufferSerializer() + { + } + + protected override void DoSerialize + (BinarySerializer serializer, _SerializableSemanticBuffer item) + { + base.DoSerialize(serializer, item); + + NativeArraySerializer.Instance.Serialize(serializer, item.Data); + var uint32Serializer = CompressedUInt32Serializer.Instance; + uint32Serializer.Serialize(serializer, item.ChannelCount); + + foreach (var name in item.ChannelNames) + { + StringSerializer.Instance.Serialize(serializer, name); + } + } + + protected override _SerializableSemanticBuffer _InternalDeserialize + ( + BinaryDeserializer deserializer, + uint width, + uint height, + bool isKeyFrame, + Matrix4x4 view, + CameraIntrinsics intrinsics + ) + { + var data = NativeArraySerializer.Instance.Deserialize(deserializer); + var uint32Deserializer = CompressedUInt32Serializer.Instance; + var channelCount = uint32Deserializer.Deserialize(deserializer); + string[] channelNames = new string[channelCount]; + for (int i = 0; i < channelCount; i++) + { + channelNames[i] = StringSerializer.Instance.Deserialize(deserializer); + } + + return + new _SerializableSemanticBuffer + ( + width, + height, + isKeyFrame, + view, + data, + channelNames, + intrinsics + ); + } + } +} diff --git a/Assets/ARDK/AR/Awareness/Semantics/_SerializableSemanticBufferSerializer.cs.meta b/Assets/ARDK/AR/Awareness/Semantics/_SerializableSemanticBufferSerializer.cs.meta new file mode 100644 index 0000000..9f29bb7 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/Semantics/_SerializableSemanticBufferSerializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4440e6b865f024a98a68d5f0d71590d4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Awareness/_AwarenessBufferBase.cs b/Assets/ARDK/AR/Awareness/_AwarenessBufferBase.cs new file mode 100644 index 0000000..1c985db --- /dev/null +++ b/Assets/ARDK/AR/Awareness/_AwarenessBufferBase.cs @@ -0,0 +1,36 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.Collections.Generic; + +using Niantic.ARDK.AR.Camera; +using Niantic.ARDK.Utilities; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Awareness +{ + internal abstract class _AwarenessBufferBase: IAwarenessBuffer + { + internal _AwarenessBufferBase + ( + uint width, + uint height, + bool isKeyframe, + CameraIntrinsics intrinsics + ) + { + IsKeyframe = isKeyframe; + Width = width; + Height = height; + } + + public abstract IAwarenessBuffer GetCopy(); + + public bool IsKeyframe { get; private set; } + public uint Width { get; private set; } + public uint Height { get; private set; } + + public abstract Matrix4x4 ViewMatrix { get; } + public abstract CameraIntrinsics Intrinsics { get; } + } +} diff --git a/Assets/ARDK/AR/Awareness/_AwarenessBufferBase.cs.meta b/Assets/ARDK/AR/Awareness/_AwarenessBufferBase.cs.meta new file mode 100644 index 0000000..cd37b18 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/_AwarenessBufferBase.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 01bfb523091c433d96fd5c6068aa95bd +timeCreated: 1607980036 \ No newline at end of file diff --git a/Assets/ARDK/AR/Awareness/_AwarenessBufferFactory.cs b/Assets/ARDK/AR/Awareness/_AwarenessBufferFactory.cs new file mode 100644 index 0000000..cfbd0ec --- /dev/null +++ b/Assets/ARDK/AR/Awareness/_AwarenessBufferFactory.cs @@ -0,0 +1,55 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.AR.Awareness.Depth; +using Niantic.ARDK.AR.Awareness.Semantics; + +namespace Niantic.ARDK.AR.Awareness +{ + internal static class _AwarenessBufferFactory + { + internal static _SerializableDepthBuffer _AsSerializable(this IDepthBuffer source) + { + if (source == null) + return null; + + var possibleResult = source as _SerializableDepthBuffer; + if (possibleResult != null) + return possibleResult; + + return + new _SerializableDepthBuffer + ( + source.Width, + source.Height, + source.IsKeyframe, + source.ViewMatrix, + source.Data, + source.NearDistance, + source.FarDistance, + source.Intrinsics + ); + } + + internal static _SerializableSemanticBuffer _AsSerializable(this ISemanticBuffer source) + { + if (source == null) + return null; + + var possibleResult = source as _SerializableSemanticBuffer; + if (possibleResult != null) + return possibleResult; + + return + new _SerializableSemanticBuffer + ( + source.Width, + source.Height, + source.IsKeyframe, + source.ViewMatrix, + source.Data, + source.ChannelNames, + source.Intrinsics + ); + } + } +} diff --git a/Assets/ARDK/AR/Awareness/_AwarenessBufferFactory.cs.meta b/Assets/ARDK/AR/Awareness/_AwarenessBufferFactory.cs.meta new file mode 100644 index 0000000..c5ac94c --- /dev/null +++ b/Assets/ARDK/AR/Awareness/_AwarenessBufferFactory.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: cb5d87c29ac34a2f88c6901983e538eb +timeCreated: 1595010961 \ No newline at end of file diff --git a/Assets/ARDK/AR/Awareness/_AwarenessBufferHelper.cs b/Assets/ARDK/AR/Awareness/_AwarenessBufferHelper.cs new file mode 100644 index 0000000..688ea06 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/_AwarenessBufferHelper.cs @@ -0,0 +1,592 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Logging; + +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Awareness +{ + /// + /// Common functions to be used for inference buffers used by the native and serialized code. + /// NOTE: + /// - if these functions are templated, iOS increases in 10% cpu usage + /// - if raw pointers (unsafe) is used instead of arrays, memory usage significantly increases + /// + internal static class _AwarenessBufferHelper + { + // Buffer used to prepare values for depth textures + [ThreadStatic] + private static Color[] _bufferCache; + + internal static NativeArray RotateToScreenOrientation + ( + NativeArray src, + int srcWidth, + int srcHeight, + out int newWidth, + out int newHeight + ) + where T: struct, IComparable + { + newWidth = srcWidth; + newHeight = srcHeight; + + // Rotate and/or crop + + Func dstIdxFn; + switch (Screen.orientation) + { + case ScreenOrientation.Portrait: + // CW + dstIdxFn = (w, _, x, y) => x * w + (w - 1 - y); + newWidth = srcHeight; + newHeight = srcWidth; + break; + + case ScreenOrientation.PortraitUpsideDown: + // CCW + dstIdxFn = (w, h, x, y) => (h - 1 - x) * w + y; + newWidth = srcHeight; + newHeight = srcWidth; + break; + + case ScreenOrientation.LandscapeLeft: + // 180a + dstIdxFn = (w, h, x, y) => (h - 1 - y) * w + (w - 1 - x); + break; + + default: + return new NativeArray(src, Allocator.Persistent); + } + + var rotatedData = + new NativeArray + ( + newWidth * newHeight, + Allocator.Persistent, + NativeArrayOptions.UninitializedMemory + ); + + for (var y = 0; y < srcHeight; y++) + { + for (var x = 0; x < srcWidth; x++) + { + var srcIdx = y * srcWidth + x; + var dstIdx = dstIdxFn(newWidth, newHeight, x, y); + rotatedData[dstIdx] = src[srcIdx]; + } + } + + return rotatedData; + } + + internal static NativeArray _FitToViewport + ( + NativeArray src, + int srcWidth, + int srcHeight, + int viewportWidth, + int viewportHeight, + out int newWidth, + out int newHeight + ) + where T: struct, IComparable + { + // Ideally this code is shared between native and serializeable + var srcRatio = srcWidth / (float)srcHeight; + var trgRatio = viewportWidth / (float)viewportHeight; + + int cropStartX = 0, cropStartY = 0; + + newWidth = (int)srcWidth; + newHeight = (int)srcHeight; + + if (srcRatio > trgRatio) + { + // Portrait: crop along the width + newWidth = Mathf.FloorToInt(srcHeight * trgRatio); + if (newWidth < srcWidth) + cropStartX = Mathf.FloorToInt((srcWidth - newWidth) / 2f); + } + else if (srcRatio != trgRatio) + { + // Landscape: crop along the height + newHeight = Mathf.FloorToInt(srcWidth / trgRatio); + if (newHeight < srcHeight) + cropStartY = Mathf.FloorToInt((srcHeight - newHeight) / 2f); + } + + var newData = + new NativeArray + ( + newWidth * newHeight, + Allocator.Persistent, + NativeArrayOptions.UninitializedMemory + ); + +#if ENABLE_UNITY_COLLECTIONS_CHECKS + NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref newData, AtomicSafetyHandle.Create()); +#endif + + // Crop by copying data with offset + for (var y = 0; y < newHeight; y++) + { + for (var x = 0; x < newWidth; x++) + { + var srcIdx = (y + cropStartY) * srcWidth + x + cropStartX; + var dstIdx = (newHeight - 1 - y) * newWidth + x; + + newData[dstIdx] = src[srcIdx]; + } + } + + return newData; + } + + /// + /// Returns a boolean if input texture has a copy of the observation image buffer. + /// The texture if successfully copied needs to be deallocated. + /// Only call on Unity thread. + /// + internal static bool _CreateOrUpdateTextureARGB32 + ( + NativeArray src, + int width, + int height, + ref Texture2D texture, + FilterMode filterMode, + Func valueConverter = null + ) + { + if (width * height != src.Length) + { + ARLog._Error("The specified pixel buffer must match the size of the texture."); + return false; + } + + if (texture != null && texture.format != TextureFormat.ARGB32) + { + ARLog._Error("The texture has already been allocated with a different pixel format."); + return false; + } + + if (texture == null) + { + texture = new Texture2D(width, height, TextureFormat.ARGB32, false, false) + { + filterMode = filterMode, wrapMode = TextureWrapMode.Clamp, anisoLevel = 0 + }; + } + + if (texture.width != width || texture.height != height) + texture.Reinitialize(width, height); + + if (texture.filterMode != filterMode) + texture.filterMode = filterMode; + + // Copy to texture + _SetColorBuffer(ref _bufferCache, src, valueConverter); + texture.SetPixels(_bufferCache, 0); + + // Push top GPU + texture.Apply(false); + + // Success + return true; + } + + /// + /// Returns a boolean if input texture has a copy of the observation image buffer. + /// The texture if successfully copied needs to be deallocated. + /// Only call on Unity thread. + /// + internal static bool _CreateOrUpdateTextureRFloat + ( + NativeArray src, + int width, + int height, + ref Texture2D texture, + FilterMode filterMode + ) + { + if (width * height != src.Length) + { + ARLog._Error("The specified pixel buffer must match the size of the texture."); + return false; + } + + if (texture != null && texture.format != TextureFormat.RFloat) + { + ARLog._Error("The texture has already been allocated with a different pixel format."); + return false; + } + + if (texture == null) + { + texture = new Texture2D(width, height, TextureFormat.RFloat, false, false) + { + filterMode = filterMode, wrapMode = TextureWrapMode.Clamp, anisoLevel = 0 + }; + } + + if (texture.width != width || texture.height != height) + texture.Reinitialize(width, height); + + if (texture.filterMode != filterMode) + texture.filterMode = filterMode; + + // Copy to texture + texture.SetPixelData(src, 0); + + // Push top GPU + texture.Apply(false); + + // Success + return true; + } + + /// + /// Returns a boolean if input texture has a copy of the observation image buffer. + /// The texture if successfully copied needs to be deallocated. + /// Only call on Unity thread. + /// + internal static bool _CreateOrUpdateTextureARGB32 + ( + NativeArray src, + int width, + int height, + ref Texture2D texture, + FilterMode filterMode, + Func valueConverter = null + ) + { + if (width * height != src.Length) + { + ARLog._Error("The specified pixel buffer must match the size of the texture."); + return false; + } + + if (texture != null && texture.format != TextureFormat.ARGB32) + { + ARLog._Error("The texture has already been allocated with a different pixel format."); + return false; + } + + if (texture == null) + { + texture = new Texture2D(width, height, TextureFormat.ARGB32, false, false) + { + filterMode = filterMode, wrapMode = TextureWrapMode.Clamp, anisoLevel = 0 + }; + } + + if (texture.width != width || texture.height != height) + texture.Reinitialize(width, height); + + if (texture.filterMode != filterMode) + texture.filterMode = filterMode; + + // 32-bit pixel size, in this case use the value converter + // or fall back to the default ushort to float conversion + _SetColorBuffer(ref _bufferCache, src, valueConverter); + texture.SetPixels(_bufferCache, 0); + + // Push top GPU + texture.Apply(false); + + // Success + return true; + } + + /// + /// Returns a boolean if input texture has a copy of the observation image buffer. + /// The texture if successfully copied needs to be deallocated. + /// Only call on Unity thread. + /// + internal static bool _CreateOrUpdateTextureRFloat + ( + NativeArray src, + int width, + int height, + ref Texture2D texture, + FilterMode filterMode + ) + { + if (width * height != src.Length) + { + ARLog._Error("The specified pixel buffer must match the size of the texture."); + return false; + } + + if (texture != null && texture.format != TextureFormat.RFloat) + { + ARLog._Error("The texture has already been allocated with a different pixel format."); + return false; + } + + if (texture == null) + { + texture = new Texture2D(width, height, TextureFormat.RFloat, false, false) + { + filterMode = filterMode, wrapMode = TextureWrapMode.Clamp, anisoLevel = 0 + }; + } + + if (texture.width != width || texture.height != height) + texture.Reinitialize(width, height); + + if (texture.filterMode != filterMode) + texture.filterMode = filterMode; + + // 32-bit pixel size, copy straight to texture + texture.SetPixelData(src, 0); + + // Push top GPU + texture.Apply(false); + + // Success + return true; + } + + /// + /// Sets the internal color color cache used for texture creation using a source buffer of type Float32. + /// + private static void _SetColorBuffer + ( + ref Color[] destination, + NativeArray source, + Func valueConverter = null + ) + { + var length = source.Length; + if (destination == null || destination.Length != length) + destination = new Color[length]; + + var isConversionDefined = valueConverter != null; + for (var idx = 0; idx < length; idx++) + { + var val = isConversionDefined ? valueConverter(source[idx]) : source[idx]; + destination[idx] = new Color(val, val, val, 1); + } + } + + /// + /// Sets the internal color color cache used for texture creation using a source buffer of type Int16. + /// If valueConverter is defined, it'll be used to convert the values to 32 bit, otherwise + /// the method falls back to Convert.ToSingle(). + /// + private static void _SetColorBuffer + ( + ref Color[] destination, + NativeArray source, + Func valueConverter = null + ) + { + var length = source.Length; + if (destination == null || destination.Length != length) + destination = new Color[length]; + + var isConversionDefined = valueConverter != null; + for (var idx = 0; idx < length; idx++) + { + var val = isConversionDefined + ? valueConverter(source[idx]) + : Convert.ToInt32(source[idx]); + destination[idx] = new Color(val, val, val, 1); + } + } + + #region Math Extensions + + /// Produces a matrix that transforms a 3D point from the awareness buffer's + /// local coordinate space to the world. + /// @note The matrix returned by this call is essentially the same matrix as + /// the camera.cameraToWorldMatrix, but the UI rotation is excluded. + public static Matrix4x4 CalculateCameraToWorldTransform + ( + this IAwarenessBuffer forBuffer, + IARCamera camera + ) + { + // Infer buffer orientation + var bufferOrientation = forBuffer.Width > forBuffer.Height + ? ScreenOrientation.LandscapeLeft + : ScreenOrientation.Portrait; + + // Acquire the view matrix in the orientation of the buffer + var view = MathUtils.CalculateNarViewMatrix(camera, bufferOrientation); + + // The buffer's native coordinate system is upside down compared to + // Unity's 2D coordinate space. + InvertVerticalAxis(ref view); + + // Invert to produce a matrix that transforms from camera to world + return view.inverse; + } + + /// Calculates a display resolution for the buffer to preserve square pixels. + /// The result is the smallest resolution to fit the buffer and keep the aspect + /// ratio defined by the viewport resolution. + /// @returns + /// The display resolution for the buffer, adjusted to viewport orientation. + /// The result might be a cropped or padded resolution. + public static Resolution CalculateDisplayFrame + ( + this IAwarenessBuffer forBuffer, + float viewportWidth, + float viewportHeight + ) + { + return MathUtils.CalculateDisplayFrame + ( + forBuffer.Width, + forBuffer.Height, + viewportWidth, + viewportHeight + ); + } + + /// Calculates an affine transformation matrix to fit the specified buffer to the specified resolution + /// @note The buffer's container can be landscape or portrait, but the content of the + /// buffer needs to be sensor oriented. + /// @param forBuffer The buffer to fit to screen. + /// @param width Target width. + /// @param height Target height. + /// @param invertVertically Whether vertical flipping is required (e.g. when the target is the screen). + /// @returns An affine matrix to be applied to normalized image coordinates. + public static Matrix4x4 CalculateDisplayTransform + ( + this IAwarenessBuffer forBuffer, + int width, + int height, + bool invertVertically = false + ) + { + // Infer target orientation + var orientation = width > height + ? ScreenOrientation.LandscapeLeft + : ScreenOrientation.Portrait; + + return MathUtils.CalculateDisplayTransform + ( + imageWidth: (int)forBuffer.Width, + imageHeight: (int)forBuffer.Height, + viewportWidth: width, + viewportHeight: height, + viewportOrientation: orientation, + invertVertically: invertVertically + ); + } + + /// Calculates an affine transformation matrix to fit the specified buffer to the specified resolution + /// @note The buffer's container can be landscape or portrait, but the content of the + /// buffer needs to be sensor oriented. + /// @param forBuffer The buffer to fit to screen. + /// @param width Target width. + /// @param height Target height. + /// @param orientation Target orientation. + /// @param invertVertically Whether vertical flipping is required (e.g. when the target is the screen). + /// @returns An affine matrix to be applied to normalized image coordinates. + public static Matrix4x4 CalculateDisplayTransform + ( + this IAwarenessBuffer forBuffer, + int width, + int height, + ScreenOrientation orientation, + bool invertVertically = false + ) + { + return MathUtils.CalculateDisplayTransform + ( + imageWidth: (int)forBuffer.Width, + imageHeight: (int)forBuffer.Height, + viewportWidth: width, + viewportHeight: height, + viewportOrientation: orientation, + invertVertically: invertVertically + ); + } + + /// Calculates a transformation matrix for the buffer to synchronize its contents + /// with the camera pose. The transformation produced by this function is agnostic + /// to the presentation parameters. To also fit the buffer to the rendering viewport, + /// combine this transform with the one returned by CalculateDisplayTransform(). + /// @param forBuffer The buffer to fit to screen. + /// @param camera The AR camera. + /// @param viewOrientation The orientation of the viewport. + /// @param backProjectionDistance The normalized distance between the near and far view. + /// @returns An projective matrix to be applied to normalized image coordinates. + public static Matrix4x4 CalculateInterpolationTransform + ( + this IAwarenessBuffer forBuffer, + IARCamera camera, + ScreenOrientation viewOrientation, + float backProjectionDistance = 0.9f + ) + { + // Inspect buffer + var aspectRatio = (float)forBuffer.Width / forBuffer.Height; + var bufferOrientation = aspectRatio > 1.0f + ? ScreenOrientation.LandscapeLeft + : ScreenOrientation.Portrait; + + // Calculate fov + var fov = 2.0f * + Mathf.Atan(forBuffer.Height / (2.0f * forBuffer.Intrinsics.FocalLength.y)) * + Mathf.Rad2Deg; + + // To keep the homography agnostic to the screen, we need to create a + // projection with a view aspect ratio being the same as the buffer container. + var projection = Matrix4x4.Perspective + ( + fov, + aspectRatio, + AwarenessParameters.DefaultNear, + AwarenessParameters.DefaultFar + ); + + // Since the view matrices are rotated to match the interface orientation, + // we need to rotate them back to match the buffer's orientation. + var rotation = MathUtils.CalculateViewRotation(from: viewOrientation, to: bufferOrientation); + + // Acquire the reference pose to warp the image from + var referencePose = (rotation * forBuffer.ViewMatrix).ConvertViewMatrixBetweenNarAndUnity(); + + // Acquire the target pose to warp the image to + var targetPose = MathUtils.CalculateUnityViewMatrix(camera, bufferOrientation); + + // We need to flip the vertical axis, because we invert it in the display + // transform matrix, since Unity's 2D coordinate system starts from the + // bottom rather than from the top. + InvertVerticalAxis(ref referencePose); + InvertVerticalAxis(ref targetPose); + + return MathUtils.CalculateHomography + ( + referencePose, + targetPose, + projection, + backProjectionDistance + ); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void InvertVerticalAxis(ref Matrix4x4 matrix) + { + matrix.m10 *= -1.0f; + matrix.m11 *= -1.0f; + matrix.m12 *= -1.0f; + matrix.m13 *= -1.0f; + } + + #endregion + } +} diff --git a/Assets/ARDK/AR/Awareness/_AwarenessBufferHelper.cs.meta b/Assets/ARDK/AR/Awareness/_AwarenessBufferHelper.cs.meta new file mode 100644 index 0000000..f9dcdcf --- /dev/null +++ b/Assets/ARDK/AR/Awareness/_AwarenessBufferHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bb2b8f7776014beb900f7df21330cd95 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Awareness/_AwarenessInitializationCodeTranslator.cs b/Assets/ARDK/AR/Awareness/_AwarenessInitializationCodeTranslator.cs new file mode 100644 index 0000000..57745be --- /dev/null +++ b/Assets/ARDK/AR/Awareness/_AwarenessInitializationCodeTranslator.cs @@ -0,0 +1,135 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.AR.Awareness +{ + public enum AwarenessInitializationStatus + { + Unknown, + Uninitialized, + Initializing, + Ready, + Failed + } + + public enum AwarenessInitializationError + { + // No error occured + None, + + // Error is unknown + Unknown, + + // Awareness features cannot initialize because of invalid inputs + BadInput, + + // Awareness features cannot fetch data needed to initialize + FetchFailed, + + // Awareness features cannot unpack downloaded data needed to initialize + UnpackFailed, + + // Awareness features cannot decrypt downloaded data needed to initialize + DecryptFailed, + + // Awareness features could not perform initialization + InitializeFailed, + + // Awareness feature is currently initializing + AlreadyRunning, + + // Awareness feature has bad metadata + BadMetaData, + } + + /// Possible error values output by an native AR session + internal enum _NativeAwarenessInitializationCode + { + // No errors + None = 0, + + // Error is unknown + Unknown = 1, + + // Awareness features are not initialized yet + Uninitialized = 2, + + // Awareness features are not ready yet + NotReady = 3, + + // Awareness features cannot initialize because of invalid inputs + BadInput = 4, + + // Awareness features cannot fetch data needed to initialize + FetchFailed = 5, + + // Awareness features cannot unpack downloaded data needed to initialize + UnpackFailed = 6, + + // Awareness features cannot decrypt downloaded data needed to initialize + DecryptFailed = 7, + + // Awareness features could not perform initialization + InitializeFailed = 8, + + // Awareness feature is currently initializing + AlreadyRunning = 9, + + // Awareness feature has bad metadata + BadMetaData = 10, + } + + internal static class _AwarenessInitializationCodeTranslator + { + public static AwarenessInitializationStatus ToStatus(this _NativeAwarenessInitializationCode code) + { + switch (code) + { + case _NativeAwarenessInitializationCode.Uninitialized: + return AwarenessInitializationStatus.Uninitialized; + + case _NativeAwarenessInitializationCode.NotReady: + return AwarenessInitializationStatus.Initializing; + + case _NativeAwarenessInitializationCode.None: + return AwarenessInitializationStatus.Ready; + + default: + return AwarenessInitializationStatus.Failed; + } + } + + public static AwarenessInitializationError ToError(this _NativeAwarenessInitializationCode code) + { + switch (code) + { + case _NativeAwarenessInitializationCode.Unknown: + return AwarenessInitializationError.Unknown; + + case _NativeAwarenessInitializationCode.BadInput: + return AwarenessInitializationError.BadInput; + + case _NativeAwarenessInitializationCode.FetchFailed: + return AwarenessInitializationError.FetchFailed; + + case _NativeAwarenessInitializationCode.UnpackFailed: + return AwarenessInitializationError.UnpackFailed; + + case _NativeAwarenessInitializationCode.DecryptFailed: + return AwarenessInitializationError.DecryptFailed; + + case _NativeAwarenessInitializationCode.InitializeFailed: + return AwarenessInitializationError.InitializeFailed; + + case _NativeAwarenessInitializationCode.AlreadyRunning: + return AwarenessInitializationError.AlreadyRunning; + + case _NativeAwarenessInitializationCode.BadMetaData: + return AwarenessInitializationError.BadMetaData; + + default: + // Case for codes Ready, Uninitialized, and NotReady + return AwarenessInitializationError.None; + } + } + } +} diff --git a/Assets/ARDK/AR/Awareness/_AwarenessInitializationCodeTranslator.cs.meta b/Assets/ARDK/AR/Awareness/_AwarenessInitializationCodeTranslator.cs.meta new file mode 100644 index 0000000..a6656c1 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/_AwarenessInitializationCodeTranslator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 80ceba4f4ec340aab39883655a577ace +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Awareness/_NativeAwarenessBufferBase.cs b/Assets/ARDK/AR/Awareness/_NativeAwarenessBufferBase.cs new file mode 100644 index 0000000..1eed24f --- /dev/null +++ b/Assets/ARDK/AR/Awareness/_NativeAwarenessBufferBase.cs @@ -0,0 +1,145 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.InteropServices; + +using Niantic.ARDK.AR.Camera; +using Niantic.ARDK.Utilities; + +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Awareness +{ + internal abstract class _NativeAwarenessBufferBase: + _AwarenessBufferBase, + IDataBuffer, + IDisposable + where T: struct + { + protected readonly float _worldScale = 0; + protected IntPtr _nativeHandle; + + private long _consumedUnmanagedMemory; + private Matrix4x4? _cacheViewMatrix = null; + private CameraIntrinsics? _cachedIntrinsics = null; + private NativeArray _data; + + protected _NativeAwarenessBufferBase + ( + IntPtr handle, + float worldScale, + UInt32 width, + UInt32 height, + bool isKeyframe, + CameraIntrinsics intrinsics + ) + : base(width, height, isKeyframe, intrinsics) + { + _worldScale = worldScale; + _nativeHandle = handle; + + _consumedUnmanagedMemory = _CalculateConsumedMemory(); + GC.AddMemoryPressure(_consumedUnmanagedMemory); + } + + ~_NativeAwarenessBufferBase() + { + Dispose(); + } + + public NativeArray Data + { + get + { + unsafe + { + if (!_data.IsCreated) + { + UInt32 size = Width * Height; + _data = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray + (_GetDataAddress().ToPointer(), (int)size, Allocator.None); + } + + return _data; + } + } + } + + public override Matrix4x4 ViewMatrix + { + get + { + if (_cacheViewMatrix == null) + { + var nativeMatrix = new float[16]; + _GetViewMatrix(nativeMatrix); + + var viewMatrix = NARConversions.FromNARToUnity + (_Convert.InternalToMatrix4x4(nativeMatrix)); + + _Convert.ApplyScale(ref viewMatrix, _worldScale); + _cacheViewMatrix = viewMatrix; + } + + return _cacheViewMatrix ?? Matrix4x4.identity; + } + } + + public override CameraIntrinsics Intrinsics + { + get + { + if (!_cachedIntrinsics.HasValue) + { + var nativeVector = new float[4]; + _GetIntrinsics(nativeVector); + + _cachedIntrinsics = + new CameraIntrinsics + ( + nativeVector[0], + nativeVector[1], + nativeVector[2], + nativeVector[3] + ); + } + + return _cachedIntrinsics.Value; + } + } + + protected abstract void _GetViewMatrix(float[] outViewMatrix); + + protected abstract void _GetIntrinsics(float[] outVector); + + protected abstract IntPtr _GetDataAddress(); + + protected abstract void _OnRelease(); + + protected float[] _UnityMatrixToNarArray(Matrix4x4 matrix) + { + return _Convert.Matrix4x4ToInternalArray(NARConversions.FromUnityToNAR(matrix)); + } + + public void Dispose() + { + if (_nativeHandle != IntPtr.Zero) + { + _OnRelease(); + GC.SuppressFinalize(this); + GC.RemoveMemoryPressure(_consumedUnmanagedMemory); + _nativeHandle = IntPtr.Zero; + } + } + + private long _CalculateConsumedMemory() + { + return Width * Height * Marshal.SizeOf(typeof(T)); + } + } +} diff --git a/Assets/ARDK/AR/Awareness/_NativeAwarenessBufferBase.cs.meta b/Assets/ARDK/AR/Awareness/_NativeAwarenessBufferBase.cs.meta new file mode 100644 index 0000000..8b0df2b --- /dev/null +++ b/Assets/ARDK/AR/Awareness/_NativeAwarenessBufferBase.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: b3dd153df52c43cba2ceb31ee01f5dc4 +timeCreated: 1607722568 \ No newline at end of file diff --git a/Assets/ARDK/AR/Awareness/_SerializableAwarenessBufferBase.cs b/Assets/ARDK/AR/Awareness/_SerializableAwarenessBufferBase.cs new file mode 100644 index 0000000..761fd06 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/_SerializableAwarenessBufferBase.cs @@ -0,0 +1,91 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.IO; +using System.Runtime.InteropServices; + +using Niantic.ARDK.AR.Camera; +using Niantic.ARDK.Utilities; + +using Unity.Collections; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Awareness +{ + // Can't use [Serializable]. Need to provide a serializer. + internal abstract class _SerializableAwarenessBufferBase + : _AwarenessBufferBase, + IDataBuffer + where T: struct + { + private readonly Matrix4x4 _viewMatrix; + + private bool _disposed; + private readonly long _consumedUnmanagedMemory; + + private readonly CameraIntrinsics _intrinsics; + + internal _SerializableAwarenessBufferBase + ( + uint width, + uint height, + bool isKeyframe, + Matrix4x4 viewMatrix, + NativeArray data, + CameraIntrinsics intrinsics + ) + : base(width, height, isKeyframe, intrinsics) + { + _viewMatrix = viewMatrix; + _intrinsics = intrinsics; + Data = data; + + _consumedUnmanagedMemory = _CalculateConsumedMemory(); + GC.AddMemoryPressure(_consumedUnmanagedMemory); + } + + ~_SerializableAwarenessBufferBase() + { + Dispose(); + } + + public override Matrix4x4 ViewMatrix + { + get + { + return _viewMatrix; + } + } + + public override CameraIntrinsics Intrinsics + { + get + { + return _intrinsics; + } + } + + public NativeArray Data { get; } + + public bool IsRotatedToScreenOrientation { get; set; } + + public void Dispose() + { + if (_disposed) + return; + + if (Data.IsCreated) + Data.Dispose(); + + GC.SuppressFinalize(this); + GC.RemoveMemoryPressure(_consumedUnmanagedMemory); + _disposed = true; + } + + private long _CalculateConsumedMemory() + { + return Width * Height * Marshal.SizeOf(typeof(T)); + } + } +} diff --git a/Assets/ARDK/AR/Awareness/_SerializableAwarenessBufferBase.cs.meta b/Assets/ARDK/AR/Awareness/_SerializableAwarenessBufferBase.cs.meta new file mode 100644 index 0000000..c5e8c2d --- /dev/null +++ b/Assets/ARDK/AR/Awareness/_SerializableAwarenessBufferBase.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 0efb84e64b4c462ea828f9b573fb44fe +timeCreated: 1607734418 \ No newline at end of file diff --git a/Assets/ARDK/AR/Awareness/_SerializableAwarenessBufferSerializer.cs b/Assets/ARDK/AR/Awareness/_SerializableAwarenessBufferSerializer.cs new file mode 100644 index 0000000..5d2cf81 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/_SerializableAwarenessBufferSerializer.cs @@ -0,0 +1,63 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.AR.Camera; +using Niantic.ARDK.Utilities.BinarySerialization; +using Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers; + +using Unity.Collections; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Awareness +{ + internal abstract class _SerializableAwarenessBufferSerializer: + BaseItemSerializer + where TBuffer: _SerializableAwarenessBufferBase + where T: struct + { + protected override void DoSerialize + (BinarySerializer serializer, TBuffer item) + { + var uint32Serializer = CompressedUInt32Serializer.Instance; + + uint32Serializer.Serialize(serializer, item.Width); + uint32Serializer.Serialize(serializer, item.Height); + BooleanSerializer.Instance.Serialize(serializer, item.IsKeyframe); + Matrix4x4Serializer.Instance.Serialize(serializer, item.ViewMatrix); + CameraIntrinsicsSerializer.Instance.Serialize(serializer, item.Intrinsics); + } + + protected override TBuffer DoDeserialize + (BinaryDeserializer deserializer) + { + var uint32Serializer = CompressedUInt32Serializer.Instance; + + uint width = uint32Serializer.Deserialize(deserializer); + uint height = uint32Serializer.Deserialize(deserializer); + var isKeyFrame = BooleanSerializer.Instance.Deserialize(deserializer); + var viewMatrix = Matrix4x4Serializer.Instance.Deserialize(deserializer); + var intrinsics = CameraIntrinsicsSerializer.Instance.Deserialize(deserializer); + + return + _InternalDeserialize + ( + deserializer, + width, + height, + isKeyFrame, + viewMatrix, + intrinsics + ); + } + + protected abstract TBuffer _InternalDeserialize + ( + BinaryDeserializer deserializer, + uint width, + uint height, + bool isKeyFrame, + Matrix4x4 view, + CameraIntrinsics intrinsics + ); + } +} diff --git a/Assets/ARDK/AR/Awareness/_SerializableAwarenessBufferSerializer.cs.meta b/Assets/ARDK/AR/Awareness/_SerializableAwarenessBufferSerializer.cs.meta new file mode 100644 index 0000000..5d48284 --- /dev/null +++ b/Assets/ARDK/AR/Awareness/_SerializableAwarenessBufferSerializer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9d956985056e4f29a12672c1a3931e09 +timeCreated: 1607973462 \ No newline at end of file diff --git a/Assets/ARDK/AR/AwarenessBufferProcessor.cs b/Assets/ARDK/AR/AwarenessBufferProcessor.cs new file mode 100644 index 0000000..4508a9c --- /dev/null +++ b/Assets/ARDK/AR/AwarenessBufferProcessor.cs @@ -0,0 +1,417 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; + +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Awareness +{ + /// Base class for components that extract information from IAwarenessBuffer objects + /// to be used in game logic and rendering. + public abstract class AwarenessBufferProcessor + where TBuffer: class, IAwarenessBuffer, IDisposable + { + /// Event for when the context awareness feature stream has initialized and the + /// application received its initial frame. + public event ArdkEventHandler> AwarenessStreamBegan + { + add + { + _awarenessStreamBegan += value; + if (_didReceiveFirstUpdate) + { + var args = new ContextAwarenessArgs(this); + value.Invoke(args); + } + } + remove => _awarenessStreamBegan -= value; + } + private event ArdkEventHandler> _awarenessStreamBegan; + + /// Alerts subscribers when either the contents of the awareness buffer + /// or its sampler transform has changed. + public event ArdkEventHandler> AwarenessStreamUpdated; + + /// The CPU copy of the latest awareness buffer + public TBuffer AwarenessBuffer { get; private set; } + + /// The current interpolation setting. + public InterpolationMode InterpolationMode { get; set; } + + /// The current setting whether to align with close (0.0f) or distant pixels (1.0f) + /// during interpolation. + public float InterpolationPreference + { + get => _interpolationPreference; + set => _interpolationPreference = Mathf.Clamp(value, 0.0f, 1.0f); + } + + /// The resolution of the viewport, awareness buffers are being mapped to. + public Vector2Int CurrentViewportResolution + { + get => new Vector2Int(_lastTargetWidth, _lastTargetHeight); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// A composited matrix to fit the awareness buffer to the screen. + /// This affine transform converts normalized screen coordinates to + /// the buffer's coordinate frame while accounting for interpolation. + public Matrix4x4 SamplerTransform { get; private set; } + + // Helper matrices + private Matrix4x4 _displayTransform = Matrix4x4.identity; + private Matrix4x4 _interpolationTransform = Matrix4x4.identity; + private Matrix4x4 _arImageToBufferTransform = Matrix4x4.identity; + + /// This transform converts 2D normalized coordinates in buffer space to 3D points + /// in camera space using the awareness buffer's orientation and intrinsics. + /// This is primarily used to get camera space positions from depth, + /// for example posInCamera = depth * BackProjectionTransform * screenUV. + protected Matrix4x4 BackProjectionTransform { get; private set; } + + // The camera to world matrix is the inverted view matrix, + // matching the orientation of the buffer. It is used + // to transform points from camera space to world space. + protected Matrix4x4 CameraToWorldTransform { get; private set; } + + // The back-projection plane distance (for interpolation) + // between the preset near and far clipping planes. + private float _interpolationPreference = 0.9f; + + // Cached state variables + private ScreenOrientation _lastOrientation; + private int _lastTargetWidth, _lastTargetHeight; + private bool _didReceiveFirstUpdate; + + /// Updates the internal state of the context awareness stream. + /// Calculates the transformation matrix used to map the buffer's + /// contents to the target viewport. This is called the sampler transform. + /// It's possible to call this API with a null buffer. In that case, + /// only the sampler transform will be updated. + /// @param frame The AR frame to process. + /// @param buffer If provided, the contents of the buffer will be copied to an internal cache. + /// @param targetResolution The resolution of the target viewport. + /// @param targetOrientation The orientation of the target viewport. + protected void _ProcessFrame + ( + IARFrame frame, + TBuffer buffer, + Resolution targetResolution, + ScreenOrientation targetOrientation + ) + { + if (frame == null || frame.Camera == null) return; + + // Processing this frame can continue without having a new + // awareness buffer available. In that case, we just update + // the display and interpolation transformations. + var didUpdateAwarenessBuffer = buffer != null; + var isFirstUpdate = AwarenessBuffer == null && didUpdateAwarenessBuffer; + + // In case we have a new buffer available, we retain a CPU-side copy + // This is necessary because the original buffer is owned by the + // ARFrame and thus will get deallocated with it. + if (didUpdateAwarenessBuffer) + { + // Release the previous buffer, if any + AwarenessBuffer?.Dispose(); + + // Cache a copy of the new buffer + AwarenessBuffer = buffer.GetCopy() as TBuffer; + } + + // We either have not received the first buffer or failed to make a copy + if (AwarenessBuffer == null) + { + ARLog._Warn("No awareness buffer available to process."); + return; + } + + if (isFirstUpdate) + { + _didReceiveFirstUpdate = true; + + // Calculate an affine matrix that transforms from the AR image's + // aspect ratio and orientation to the buffer's coordinate space. + var arImageResolution = frame.Camera.ImageResolution; + _arImageToBufferTransform = AwarenessBuffer.CalculateDisplayTransform + ( + arImageResolution.width, + arImageResolution.height + ); + + // Propagate the event for when the context awareness feature initialized + _awarenessStreamBegan?.Invoke(new ContextAwarenessArgs(this)); + } + + // Check whether the viewport has been rotated and update the display transform + var isDisplayTransformDirty = isFirstUpdate || + _lastOrientation != targetOrientation || + _lastTargetWidth != targetResolution.width || + _lastTargetHeight != targetResolution.height; + + if (isDisplayTransformDirty) + { + _lastOrientation = targetOrientation; + _lastTargetWidth = targetResolution.width; + _lastTargetHeight = targetResolution.height; + + // Calculate an affine matrix that transforms normalized coordinates from the + // viewport's aspect ratio and orientation to the buffer's coordinate space. + _displayTransform = _arImageToBufferTransform * frame.CalculateDisplayTransform + ( + _lastOrientation, + _lastTargetWidth, + _lastTargetHeight + ); + } + + // Note: Neural network results are asynchronous, therefore when + // interpolation is on, we calculate a matrix to correct for the + // displacement that occured between the beginning of inference + // and the current pose of the AR driven camera. + // We only need to update the interpolation transform either if + // there is a new buffer or if it's set to be updated every frame + var isInterpolationTransformDirty = + (InterpolationMode == InterpolationMode.Balanced && didUpdateAwarenessBuffer) || + InterpolationMode == InterpolationMode.Smooth; + + if (isInterpolationTransformDirty) + { + _interpolationTransform = AwarenessBuffer.CalculateInterpolationTransform + ( + frame.Camera, + targetOrientation, + _interpolationPreference + ); + } + + // We need to update the transform used for sampling + // if either the display transform or the interpolation + // transform has been changed + var isSamplerTransformDirty = isDisplayTransformDirty || isInterpolationTransformDirty; + if (isSamplerTransformDirty) + { + // Compose final matrix used for sampling depth + SamplerTransform = InterpolationMode != InterpolationMode.None + ? _interpolationTransform * _displayTransform + : _displayTransform; + } + + if (didUpdateAwarenessBuffer) + { + // The back projection transform converts normalized + // viewport coordinates to 3D points in camera space. + // To calculate it, first we normalize the intrinsics. + // Note: we don't need to flip cy here, because the + // display transform already contains a vertical inversion. + var intrinsics = GetNormalizedIntrinsics(AwarenessBuffer); + + // The inverse of this matrix can be used to back project 2D points in 3D. + // Additionally, we multiply with the depth buffer's display transform to + // allow the matrix to be used with normalized viewport coordinates. + BackProjectionTransform = Matrix4x4.Inverse(intrinsics) * _displayTransform; + } + + // This state variable represents whether the current representation of the + // context awareness buffer is altered, i.e. the contents of the buffer + // changes or it needs to be mapped to the screen differently. + var isRepresentationDirty = didUpdateAwarenessBuffer || isSamplerTransformDirty; + + #if CONTEXT_AWARENESS_USE_INFERENCE_TIME_CAMERA + // When CONTEXT_AWARENESS_USE_INFERENCE_TIME_CAMERA is defined, + // the CameraToWorldTransform is only updated when there was a + // change in the buffer's representation. As a result, when + // back-projecting values (e.g. depth) from a screen point, + // the result will be calculated from where the screen point + // was the last time when the buffer was updated instead of + // where the screen point is currently. + if (isRepresentationDirty) + #endif + + // The camera to world matrix is the inverted view matrix, + // matching the orientation of the buffer. It is used + // to transform points from camera space to world space. + CameraToWorldTransform = AwarenessBuffer.CalculateCameraToWorldTransform(frame.Camera); + + if (isRepresentationDirty) + { + AwarenessStreamUpdated?.Invoke + ( + new ContextAwarenessStreamUpdatedArgs + ( + sender: this, + isKeyFrame: didUpdateAwarenessBuffer + ) + ); + } + } + + private Color[] _pixelBufferColor; + private float[] _pixelBufferFloat; + + protected void CreateOrUpdateTextureARGB32 + ( + ref Texture2D texture, + ScreenOrientation orientation, + Func sampler + ) + { + var resolution = CalculateContainerResolution + ( + forBuffer: AwarenessBuffer, + usingOrientation: orientation + ); + + var width = resolution.x; + var height = resolution.y; + var length = width * height; + + if (!PrepareTexture(ref texture, width, height, TextureFormat.ARGB32)) + return; + + // Allocate CPU buffer to cache the transformed image + if (_pixelBufferColor == null || _pixelBufferColor.Length != length) + _pixelBufferColor = new Color[length]; + + for (int x = 0; x < width; x++) + { + var adjustedX = x + 0.5f; + for (int y = 0; y < height; y++) + { + // Calculate normalized texture coordinates + var uv = new Vector2(adjustedX / width, (y + 0.5f) / height); + + // Sample the buffer + _pixelBufferColor[x + width * y] = sampler(uv); + } + } + + // Push to GPU + texture.SetPixels(_pixelBufferColor); + texture.Apply(updateMipmaps: false); + } + + protected void CreateOrUpdateTextureRFloat + ( + ref Texture2D texture, + ScreenOrientation orientation, + Func sampler + ) + { + var resolution = CalculateContainerResolution + ( + forBuffer: AwarenessBuffer, + usingOrientation: orientation + ); + + var width = resolution.x; + var height = resolution.y; + var length = width * height; + + if (!PrepareTexture(ref texture, width, height, TextureFormat.RFloat)) + return; + + // Allocate CPU buffer to cache the transformed image + if (_pixelBufferFloat == null || _pixelBufferFloat.Length != length) + _pixelBufferFloat = new float[length]; + + for (int x = 0; x < width; x++) + { + for (int y = 0; y < height; y++) + { + // Calculate normalized texture coordinates + var uv = new Vector2((x + 0.5f) / width, (y + 0.5f) / height); + + // Sample the buffer + _pixelBufferFloat[x + width * y] = sampler(uv); + } + } + + // Push to GPU + texture.SetPixelData(_pixelBufferFloat, 0); + texture.Apply(updateMipmaps: false); + } + + protected virtual void Dispose(bool disposing) + { + if(disposing) + AwarenessBuffer?.Dispose(); + } + + ~AwarenessBufferProcessor() + { + Dispose(false); + } + + /// Returns the normalized the intrinsics matrix of the awareness buffer. + /// @param buffer The context awareness buffer. + private static Matrix4x4 GetNormalizedIntrinsics(IAwarenessBuffer buffer) + { + var widthMinusOne = buffer.Width - 1; + var heightMinusOne = buffer.Height - 1; + var intrinsics = buffer.Intrinsics; + var result = Matrix4x4.identity; + + // Calculate normalized intrinsics + result[0, 0] = intrinsics.FocalLength.x / widthMinusOne; // fx + result[0, 3] = intrinsics.PrincipalPoint.x / widthMinusOne; // cx + result[1, 1] = intrinsics.FocalLength.y / heightMinusOne; // fy + result[1, 3] = intrinsics.PrincipalPoint.y / heightMinusOne; // cy + + return result; + } + + private static Vector2Int CalculateContainerResolution(IAwarenessBuffer forBuffer, ScreenOrientation usingOrientation) + { + // Inspect the buffer + var bufferWidth = (int)forBuffer.Width; + var bufferHeight = (int)forBuffer.Height; + + var bufferOrientation = bufferWidth > bufferHeight + ? ScreenOrientation.LandscapeLeft + : ScreenOrientation.Portrait; + + var targetOrientation = + usingOrientation == ScreenOrientation.LandscapeLeft || + usingOrientation == ScreenOrientation.LandscapeRight + ? ScreenOrientation.LandscapeLeft + : ScreenOrientation.Portrait; + + var rotateContainer = bufferOrientation != targetOrientation; + var width = rotateContainer ? bufferHeight : bufferWidth; + var height = rotateContainer ? bufferWidth : bufferHeight; + + return new Vector2Int(width, height); + } + + private static bool PrepareTexture(ref Texture2D texture, int width, int height, TextureFormat format) + { + if (texture == null) + { + // Alloc new texture + texture = new Texture2D(width, height, format, false, false) + { + filterMode = FilterMode.Point, wrapMode = TextureWrapMode.Clamp, anisoLevel = 0 + }; + } + else if (texture.format != format) + { + ARLog._Error("This texture has already been allocated with a different format."); + return false; + } + + if (texture.width != width || texture.height != height) + texture.Reinitialize(width, height); + + return true; + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/AR/AwarenessBufferProcessor.cs.meta b/Assets/ARDK/AR/AwarenessBufferProcessor.cs.meta new file mode 100644 index 0000000..76452d7 --- /dev/null +++ b/Assets/ARDK/AR/AwarenessBufferProcessor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ed06cdf1b33344b259785d2cc242b17d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Camera.meta b/Assets/ARDK/AR/Camera.meta new file mode 100644 index 0000000..a2d107f --- /dev/null +++ b/Assets/ARDK/AR/Camera.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e510300c441e942219929486334f8c51 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Camera/CameraIntrinsics.cs b/Assets/ARDK/AR/Camera/CameraIntrinsics.cs new file mode 100644 index 0000000..0f4de9d --- /dev/null +++ b/Assets/ARDK/AR/Camera/CameraIntrinsics.cs @@ -0,0 +1,55 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using UnityEngine; + +namespace Niantic.ARDK.AR.Camera +{ + /// Where (fx, fy) is the focal length and (px, py) is the principal point location, + /// can be cast into a vector: [fx, fy, px, py] + public struct CameraIntrinsics + { + public Vector2 FocalLength { get; } + public Vector2 PrincipalPoint { get; } + + private readonly Vector4 _vector; + + internal CameraIntrinsics(float fx, float fy, float px, float py) + { + FocalLength = new Vector2(fx, fy); + PrincipalPoint = new Vector2(px, py); + + _vector = new Vector4(FocalLength.x, FocalLength.y, PrincipalPoint.x, PrincipalPoint.y); + } + + public static implicit operator Vector4(CameraIntrinsics o) + { + return o._vector; + } + + public static implicit operator CameraIntrinsics(Vector4 v) + { + return new CameraIntrinsics(v.x, v.y, v.z, v.w); + } + + /// Converts this CameraIntrinsics instance to a Matrix4x4. + /// The resulting matrix will have the following layout: + /// + /// | Fx 0 0 Cx | + /// | 0 Fy 0 Cy | + /// | 0 0 1 0 | + /// | 0 0 0 1 | + /// + /// As an example, this matrix can be used to project points + /// from screen to camera space: + /// var pointInCamera = + /// depth * (Matrix4x4.Inverse(intrinsics) * new Vector4(x, y, 1.0f, 1.0f)); + public static implicit operator Matrix4x4(CameraIntrinsics intrinsics) + { + Matrix4x4 result = Matrix4x4.identity; + result[0, 0] = intrinsics.FocalLength.x; + result[1, 1] = intrinsics.FocalLength.y; + result[0, 3] = intrinsics.PrincipalPoint.x; + result[1, 3] = intrinsics.PrincipalPoint.y; + return result; + } + } +} diff --git a/Assets/ARDK/AR/Camera/CameraIntrinsics.cs.meta b/Assets/ARDK/AR/Camera/CameraIntrinsics.cs.meta new file mode 100644 index 0000000..de13b9b --- /dev/null +++ b/Assets/ARDK/AR/Camera/CameraIntrinsics.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a32fc5c03ef04dc990fb2e98d74a9ef0 +timeCreated: 1627392642 \ No newline at end of file diff --git a/Assets/ARDK/AR/Camera/_ARCameraFactory.cs b/Assets/ARDK/AR/Camera/_ARCameraFactory.cs new file mode 100644 index 0000000..e6fa47f --- /dev/null +++ b/Assets/ARDK/AR/Camera/_ARCameraFactory.cs @@ -0,0 +1,36 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using UnityEngine; + +namespace Niantic.ARDK.AR.Camera +{ + internal static class _ARCameraFactory + { + internal static _SerializableARCamera _AsSerializable(this IARCamera source) + { + if (source == null) + return null; + + var possibleResult = source as _SerializableARCamera; + if (possibleResult != null) + return possibleResult; + + return + new _SerializableARCamera + ( + trackingState: source.TrackingState, + trackingStateReason: source.TrackingStateReason, + // Passing scaled image resolution here, instead of native resolution + // TODO(kmori): will revisit if setting encoding res won't bring side effects + imageResolution: _VideoStreamHelper._EncodingImageResolution, + cpuImageResolution: _VideoStreamHelper._EncodingImageResolution, + transform: source.Transform, + projectionMatrix: source.ProjectionMatrix, + intrinsics: source.Intrinsics, + cpuIntrinsics: source.CPUIntrinsics, + worldScale: source.WorldScale, + estimatedViewMatrix: source.GetViewMatrix(Screen.orientation) + ); + } + } +} diff --git a/Assets/ARDK/AR/Camera/_ARCameraFactory.cs.meta b/Assets/ARDK/AR/Camera/_ARCameraFactory.cs.meta new file mode 100644 index 0000000..d792c66 --- /dev/null +++ b/Assets/ARDK/AR/Camera/_ARCameraFactory.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 7da7b86eff09420fb1646663be956dcf +timeCreated: 1595011894 \ No newline at end of file diff --git a/Assets/ARDK/AR/Camera/_NativeARCamera.cs b/Assets/ARDK/AR/Camera/_NativeARCamera.cs new file mode 100644 index 0000000..3282d73 --- /dev/null +++ b/Assets/ARDK/AR/Camera/_NativeARCamera.cs @@ -0,0 +1,454 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Runtime.InteropServices; + +using Niantic.ARDK.Internals; +using Niantic.ARDK.Utilities; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Camera +{ + internal sealed class _NativeARCamera: + IARCamera + { + // tracking peerState + tracking peerState reason + image resolution + transform + + // projection matrix + view matrix + private const long _MemoryPressure = + (1L * 8L) + (1L * 8L) + (2L * 8L) + (16L * 4L) + (16L * 4L) + (16L * 4L); + + static _NativeARCamera() + { + Platform.Init(); + } + + // Directly release a native camera without generating an object or waiting for GC. + internal static void _ReleaseImmediate(IntPtr nativeHandle) + { + _NARCamera_Release(nativeHandle); + } + + private static _WeakValueDictionary<_CppAddressAndScale, _NativeARCamera> _allCameras = + new _WeakValueDictionary<_CppAddressAndScale, _NativeARCamera>(); + + internal static _NativeARCamera _FromNativeHandle(IntPtr nativeHandle, float worldScale) + { + _StaticMemberValidator._CollectionIsEmptyWhenScopeEnds(() => _allCameras); + + var cppAddress = _NARCamera_GetCppAddress(nativeHandle); + var handleAndScale = new _CppAddressAndScale(cppAddress, worldScale); + + var result = _allCameras.TryGetValue(handleAndScale); + if (result != null) + { + // We found an existing C# wrapper for the actual C++ object. Let's release the new + // nativeHandle and return the existing wrapper. + + _ReleaseImmediate(nativeHandle); + return result; + } + + Func<_CppAddressAndScale, _NativeARCamera> creator = + (_) => new _NativeARCamera(nativeHandle, worldScale); + + result = _allCameras.GetOrAdd(handleAndScale, creator); + + if (result._nativeHandle != nativeHandle) + { + // We got on the very odd situation where just after a TryGetValue another value was added. + // We should release our handle immediately. Then, we can return the result as it is valid. + _ReleaseImmediate(nativeHandle); + } + + return result; + } + + internal _NativeARCamera(IntPtr nativeHandle, float worldScale) + { + if (nativeHandle == IntPtr.Zero) + throw new ArgumentException("nativeHandle can't be Zero.", nameof(nativeHandle)); + + _nativeHandle = nativeHandle; + WorldScale = worldScale; + GC.AddMemoryPressure(_MemoryPressure); + } + + ~_NativeARCamera() + { + _ReleaseImmediate(_nativeHandle); + GC.RemoveMemoryPressure(_MemoryPressure); + } + + public void Dispose() + { + GC.SuppressFinalize(this); + + var nativeHandle = _nativeHandle; + if (nativeHandle != IntPtr.Zero) + { + _nativeHandle = IntPtr.Zero; + + _ReleaseImmediate(nativeHandle); + GC.RemoveMemoryPressure(_MemoryPressure); + } + } + + public float WorldScale { get; private set; } + + private IntPtr _nativeHandle; + internal IntPtr _NativeHandle + { + get { return _nativeHandle; } + } + + private TrackingState _trackingState; + public TrackingState TrackingState + { + get + { + _PopulateTrackingStateIfNeeded(); + + return _trackingState; + } + } + + private TrackingStateReason _trackingStateReason; + public TrackingStateReason TrackingStateReason + { + get + { + _PopulateTrackingStateIfNeeded(); + + return _trackingStateReason; + } + } + + public Resolution ImageResolution + { + get + { + var nativeImageResolution = new Int32[2]; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARCamera_GetGPUImageResolution(_nativeHandle, nativeImageResolution); + + return + new Resolution + { + width = nativeImageResolution[0], + height = nativeImageResolution[1] + }; + } + } + + public Resolution CPUImageResolution + { + get + { + var nativeImageResolution = new Int32[2]; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARCamera_GetCPUImageResolution(_nativeHandle, nativeImageResolution); + + return + new Resolution + { + width = nativeImageResolution[0], + height = nativeImageResolution[1] + }; + } + } + + public CameraIntrinsics Intrinsics + { + get + { + var nativeIntrinsics = new float[16]; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARCamera_GetGPUIntrinsics(_nativeHandle, nativeIntrinsics); + #pragma warning disable 0162 + else + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + + return + new CameraIntrinsics + ( + nativeIntrinsics[0], + nativeIntrinsics[4], + nativeIntrinsics[6], + nativeIntrinsics[7] + ); + } + } + + public CameraIntrinsics CPUIntrinsics + { + get + { + var nativeIntrinsics = new float[16]; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARCamera_GetCPUIntrinsics(_nativeHandle, nativeIntrinsics); + #pragma warning disable 0162 + else + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + + return + new CameraIntrinsics + ( + nativeIntrinsics[0], + nativeIntrinsics[4], + nativeIntrinsics[6], + nativeIntrinsics[7] + ); + } + } + + public Matrix4x4 Transform + { + get + { + var nativeTransform = new float[16]; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARCamera_GetTransform(_nativeHandle, nativeTransform); + #pragma warning disable 0162 + else + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + + var transform = NARConversions.FromNARToUnity + (_Convert.InternalToMatrix4x4(nativeTransform)); + + _Convert.ApplyScale(ref transform, WorldScale); + return transform; + } + } + + /* The major difference between Unity and OpenGL is that Unity uses a left-handed + coordinate system while OpenGL uses a right-handed system. + + X-axis Y-axis z-axis + Unity left-to-right bottom-to-top near-to-far + OpenGL left-to-right bottom-to-top far-to-near + + So "forward" in OpenGL is "-z". In Unity forward is "+z". Most hand-rules you might know + from math are inverted in Unity. + For example the cross product usually uses the right hand rule c = a x b where a is thumb, + b is index finger and c is the middle finger. + In Unity you would use the same logic, but with the left hand. + + However this does not affect the projection matrix as Unity uses the OpenGL convention + for the projection matrix. + The required z-flipping is done by the cameras worldToCameraMatrix. So the projection + matrix should look the same as in OpenGL. + */ + public Matrix4x4 ProjectionMatrix + { + get + { + var nativeMatrix = new float[16]; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARCamera_GetProjectionMatrix(_nativeHandle, nativeMatrix); + #pragma warning disable 0162 + else + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + + return _Convert.InternalToMatrix4x4(nativeMatrix); + } + } + + public Matrix4x4 CalculateProjectionMatrix + ( + ScreenOrientation orientation, + int viewportWidth, + int viewportHeight, + float nearClipPlane, + float farClipPlane + ) + { + var nativeProjectionMatrix = new float[16]; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + _NARCamera_CalculateProjectionMatrix + ( + _nativeHandle, + (UInt64)orientation, + viewportWidth, + viewportHeight, + nearClipPlane, + farClipPlane, + nativeProjectionMatrix + ); + } + #pragma warning disable 0162 + else + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + + return _Convert.InternalToMatrix4x4(nativeProjectionMatrix); + } + + public Matrix4x4 GetViewMatrix(ScreenOrientation orientation) + { + var nativeViewMatrix = new float[16]; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + _NARCamera_GetViewMatrix + ( + _nativeHandle, + (UInt64)orientation, + nativeViewMatrix + ); + } + #pragma warning disable 0162 + else + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + + var viewMatrix = NARConversions.FromNARToUnity(_Convert.InternalToMatrix4x4(nativeViewMatrix)); + _Convert.ApplyScale(ref viewMatrix, WorldScale); + return viewMatrix; + } + + public Vector2 ProjectPoint + ( + Vector3 point, + ScreenOrientation orientation, + int viewportWidth, + int viewportHeight + ) + { + var outPoint = new float[2]; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + point = NARConversions.FromUnityToNAR(point); + var worldScale = WorldScale; + + _NARCamera_ProjectPoint + ( + _nativeHandle, + point.x * (1 / worldScale), + point.y * (1 / worldScale), + point.z * (1 / worldScale), + (UInt64)orientation, + viewportWidth, + viewportHeight, + outPoint + ); + } + + return new Vector2(outPoint[0], outPoint[1]); + } + + private bool _isTrackingStateLoaded; + // Populates the tracking state and reason. + private void _PopulateTrackingStateIfNeeded() + { + if (_isTrackingStateLoaded) + return; + + var nativeTrackingStates = new UInt64[2]; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARCamera_GetTrackingStates(_nativeHandle, nativeTrackingStates); + + _trackingState = (TrackingState)nativeTrackingStates[0]; + _trackingStateReason = (TrackingStateReason)nativeTrackingStates[1]; + _isTrackingStateLoaded = true; + } + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARCamera_Release(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NARCamera_GetCppAddress(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern byte _NARCamera_GetTrackingStates + ( + IntPtr nativeHandle, + UInt64[] outTrackingStates + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARCamera_GetTransform(IntPtr nativeHandle, float[] outMatrix); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARCamera_GetGPUImageResolution + ( + IntPtr nativeHandle, + Int32[] outResolution + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARCamera_GetCPUImageResolution + ( + IntPtr nativeHandle, + Int32[] outResolution + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARCamera_GetGPUIntrinsics + ( + IntPtr nativeHandle, + float[] outIntrinsics + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARCamera_GetCPUIntrinsics + ( + IntPtr nativeHandle, + float[] outIntrinsics + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARCamera_GetProjectionMatrix + ( + IntPtr nativeHandle, + float[] outMatrix + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARCamera_CalculateProjectionMatrix + ( + IntPtr nativeHandle, + UInt64 viewportOrientation, + Int32 viewportWidth, + Int32 viewportHeight, + float zNear, + float zFar, + float[] outMatrix + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARCamera_GetViewMatrix + ( + IntPtr nativeHandle, + UInt64 viewportOrientation, + float[] outMatrix + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARCamera_ProjectPoint + ( + IntPtr nativeHandle, + float pointX, + float pointY, + float pointZ, + UInt64 viewportOrientation, + Int32 viewportWidth, + Int32 viewportHeight, + float[] outPoint + ); + } +} diff --git a/Assets/ARDK/AR/Camera/_NativeARCamera.cs.meta b/Assets/ARDK/AR/Camera/_NativeARCamera.cs.meta new file mode 100644 index 0000000..726447f --- /dev/null +++ b/Assets/ARDK/AR/Camera/_NativeARCamera.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6a9c249b8a9440849af96ab06d4acf41 +timeCreated: 1592893955 \ No newline at end of file diff --git a/Assets/ARDK/AR/Camera/_SerializableARCamera.cs b/Assets/ARDK/AR/Camera/_SerializableARCamera.cs new file mode 100644 index 0000000..b54ea26 --- /dev/null +++ b/Assets/ARDK/AR/Camera/_SerializableARCamera.cs @@ -0,0 +1,98 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.Utilities; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Camera +{ + [Serializable] + internal sealed class _SerializableARCamera: + IARCamera + { + internal _SerializableARCamera() + { + } + + internal _SerializableARCamera + ( + TrackingState trackingState, + TrackingStateReason trackingStateReason, + Resolution imageResolution, + Resolution cpuImageResolution, + CameraIntrinsics intrinsics, + CameraIntrinsics cpuIntrinsics, + Matrix4x4 transform, + Matrix4x4 projectionMatrix, + float worldScale, + Matrix4x4 estimatedViewMatrix + ) + { + TrackingState = trackingState; + TrackingStateReason = trackingStateReason; + ImageResolution = imageResolution; + CPUImageResolution = cpuImageResolution; + Intrinsics = intrinsics; + CPUIntrinsics = cpuIntrinsics; + Transform = transform; + ProjectionMatrix = projectionMatrix; + WorldScale = worldScale; + _estimatedViewMatrix = estimatedViewMatrix; + } + + public TrackingState TrackingState { get; internal set; } + public TrackingStateReason TrackingStateReason { get; internal set; } + public Resolution ImageResolution { get; internal set; } + public Resolution CPUImageResolution { get; internal set; } + public CameraIntrinsics Intrinsics { get; internal set; } + public CameraIntrinsics CPUIntrinsics { get; internal set; } + public Matrix4x4 Transform { get; internal set; } + public Matrix4x4 ProjectionMatrix { get; internal set; } + public float WorldScale { get; internal set; } + + public Matrix4x4 CalculateProjectionMatrix + ( + ScreenOrientation orientation, + int viewportWidth, + int viewportHeight, + float nearClipPlane, + float farClipPlane + ) + { + return MathUtils.CalculateProjectionMatrix + ( + this, + orientation, + viewportWidth, + viewportHeight, + nearClipPlane, + farClipPlane + ); + } + + internal Matrix4x4 _estimatedViewMatrix; + public Matrix4x4 GetViewMatrix(ScreenOrientation orientation) + { + return _estimatedViewMatrix; + } + + public Vector2 ProjectPoint + ( + Vector3 point, + ScreenOrientation orientation, + int viewportWidth, + int viewportHeight + ) + { + // TODO(grayson): send message to project point and return result! + return new Vector2(); + } + + void IDisposable.Dispose() + { + // Do nothing. This object is fully managed. + } + } +} diff --git a/Assets/ARDK/AR/Camera/_SerializableARCamera.cs.meta b/Assets/ARDK/AR/Camera/_SerializableARCamera.cs.meta new file mode 100644 index 0000000..2d1ffa0 --- /dev/null +++ b/Assets/ARDK/AR/Camera/_SerializableARCamera.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2721e130fefcc4ec09992fa22fbc0e08 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/CompressedImage.cs b/Assets/ARDK/AR/CompressedImage.cs new file mode 100644 index 0000000..2dfef55 --- /dev/null +++ b/Assets/ARDK/AR/CompressedImage.cs @@ -0,0 +1,12 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +namespace Niantic.ARDK.AR +{ + [Serializable] + public sealed class CompressedImage + { + public byte[] CompressedData { get; set; } + } +} diff --git a/Assets/ARDK/AR/CompressedImage.cs.meta b/Assets/ARDK/AR/CompressedImage.cs.meta new file mode 100644 index 0000000..d7093f0 --- /dev/null +++ b/Assets/ARDK/AR/CompressedImage.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f26ac2e1c67645338ea61cc90897849a +timeCreated: 1593559982 \ No newline at end of file diff --git a/Assets/ARDK/AR/Configuration.meta b/Assets/ARDK/AR/Configuration.meta new file mode 100644 index 0000000..23f1e55 --- /dev/null +++ b/Assets/ARDK/AR/Configuration.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9c8aaa26aa9b4fbb988cd15f6e3f5983 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Configuration/ARCoreInstaller.cs b/Assets/ARDK/AR/Configuration/ARCoreInstaller.cs new file mode 100644 index 0000000..14ab495 --- /dev/null +++ b/Assets/ARDK/AR/Configuration/ARCoreInstaller.cs @@ -0,0 +1,89 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.Runtime.InteropServices; + +using Niantic.ARDK.Internals; + +namespace Niantic.ARDK.AR.Configuration +{ + /// @brief A tool that installs ARCore if it's not already installed. + /// @remark This class exposes the ArCoreApk_requestInstallCustom method from ARCore, documented here: + /// https://developers.google.com/ar/reference/c/group/ar-core-apk#arcoreapk_requestinstallcustom + public class ARCoreInstaller + { + public enum InstallBehavior + { + // This means the user prompt will have a cancel button and can be refused. + Optional = 0, + + // This means the user prompt cannot be refused (though the user can still avoid downloading + // arcore by closing and reopening the app). + Required = 1, + }; + + public enum InstallMessageType + { + // This tells the user that ARCore is required for a feature of your app. + Feature = 0, + + // This tells the user that ARCore is required for the entire app. + Application = 1, + + // This tells the user nothing about why ARCore is being requested, assuming you've already + // informed them. + UserAlreadyInformed = 2, + }; + + + public enum InstallResult + { + // This means that ARCore is installed and up to date. + Installed = 0, + + // The user is being sent to the play store to update/install ARCore. + PromptingUserToUpdate = 1, + + // The user has rejected the install/update request. + RejectedByUser = 2, + + // The request failed for some reason unrelated to the user. + Failed = 3, + } + + /// Calling this method with shouldPromptUserToUpdate will either return that ARCore is already + /// installed, or send the user to the play store to install it. Calling it with + /// shouldPromptUserToUpdate as false will either return that ARCore is successfully installed + /// or will say that the user declined to install it. + /// If the user is sent to the play store to install ARCore, this activity will pause. This will + /// need to be called again after the activity has resumed to check the results. + public static InstallResult RequestInstallARCore + ( + bool shouldPromptUserToUpdate, + InstallBehavior installBehavior, + InstallMessageType messageType + ) + { + var result = InstallResult.Installed; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + result = (InstallResult)_NARConfiguration_RequestInstallARCore + ( + shouldPromptUserToUpdate ? (byte)1 : (byte)0, + (uint)installBehavior, + (uint)messageType + ); + } + + return result; + } + + [DllImport(_ARDKLibrary.libraryName)] + static extern uint _NARConfiguration_RequestInstallARCore + ( + byte sendUserToInstall, + uint installBehavior, + uint messageType + ); + } +} diff --git a/Assets/ARDK/AR/Configuration/ARCoreInstaller.cs.meta b/Assets/ARDK/AR/Configuration/ARCoreInstaller.cs.meta new file mode 100644 index 0000000..0890f0e --- /dev/null +++ b/Assets/ARDK/AR/Configuration/ARCoreInstaller.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e6866b33169d4c1e93c70bb8afe0d2ba +timeCreated: 1601501530 \ No newline at end of file diff --git a/Assets/ARDK/AR/Configuration/ARHardwareCapability.cs b/Assets/ARDK/AR/Configuration/ARHardwareCapability.cs new file mode 100644 index 0000000..49e57ec --- /dev/null +++ b/Assets/ARDK/AR/Configuration/ARHardwareCapability.cs @@ -0,0 +1,23 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.AR.Configuration +{ + /// Possible states of capability for the current hardware device regarding a particular + /// configuration. + public enum ARHardwareCapability + { + /// Hardware device is not capable for the particular configuration. + NotCapable = 0, + + /// An internal error occurred while determining capability. + /// @note Android-only value. + CheckFailedWithError = 1, + + /// The query to check capability timed out. This may be due to the device being offline. + /// @note Android-only value. + CheckFailedWithTimeout = 2, + + /// Hardware device is capable of the particular configuration. + Capable = 4, + } +} diff --git a/Assets/ARDK/AR/Configuration/ARHardwareCapability.cs.meta b/Assets/ARDK/AR/Configuration/ARHardwareCapability.cs.meta new file mode 100644 index 0000000..acd8a0c --- /dev/null +++ b/Assets/ARDK/AR/Configuration/ARHardwareCapability.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d99ea0cca1a04798ba4e24ada0db26c2 +timeCreated: 1594225441 \ No newline at end of file diff --git a/Assets/ARDK/AR/Configuration/ARSessionChangesCollector.cs b/Assets/ARDK/AR/Configuration/ARSessionChangesCollector.cs new file mode 100644 index 0000000..9094dcd --- /dev/null +++ b/Assets/ARDK/AR/Configuration/ARSessionChangesCollector.cs @@ -0,0 +1,104 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.Extensions; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Logging; + +namespace Niantic.ARDK.AR.Configuration +{ + /// An instance of this class is owned by an ARSession. + /// ARConfigChanger instances Register to the ARConfigChangerCollector of the ARSession they need + /// to affect, and when ARSession.Run is called, all registered ARConfigChangers will have their + /// changes collected. + /// + /// ARConfigChangers can also request the ARSession be re-run (and so config changes re-collected) + /// by invoking their _ConfigurationChanged event. Re-runs will be triggered at max once per frame. + public sealed class ARSessionChangesCollector + { + public sealed class ARSessionRunProperties + { + public IARConfiguration ARConfiguration; + public ARSessionRunOptions RunOptions; + + public ARSessionRunProperties + ( + IARConfiguration arConfiguration, + ARSessionRunOptions runOptions + ) + { + ARConfiguration = arConfiguration; + RunOptions = runOptions; + } + } + private _IARSession _arSession; + + private Action _configChangesRequested; + + private bool _observerRequestedCollection; + + private IARConfiguration _preChangeConfiguration; + + internal ARSessionChangesCollector(_IARSession arSession) + { + _arSession = arSession; + _arSession.Deinitialized += _ => _arSession = null; + _UpdateLoop.Tick += RerunIfRequested; + } + + internal void _CollectChanges(IARConfiguration arConfiguration, ref ARSessionRunOptions runOptions) + { + _preChangeConfiguration = ARWorldTrackingConfigurationFactory.Create(); + arConfiguration.CopyTo(_preChangeConfiguration); + + var properties = new ARSessionRunProperties(arConfiguration, runOptions); + _configChangesRequested?.Invoke(properties); + + runOptions = properties.RunOptions; + + _observerRequestedCollection = false; + } + + public void Register(ARConfigChanger changer) + { + ARLog._DebugFormat("Registered {0} as ARConfigChanger.", objs: changer.GetType()); + _configChangesRequested += changer.ApplyARConfigurationChange; + + // Rerun will only occur if the ARSession.State is Running in the next Unity Update frame. + changer._ConfigurationChanged += RequestCollection; + } + + public void Unregister(ARConfigChanger changer) + { + ARLog._DebugFormat("Unregistered {0} as ARConfigChanger.", objs: changer.GetType()); + _configChangesRequested -= changer.ApplyARConfigurationChange; + changer._ConfigurationChanged -= RequestCollection; + } + + private void RequestCollection() + { + _observerRequestedCollection = true; + } + + private void RerunIfRequested() + { + if (_observerRequestedCollection && _arSession != null) + { + _observerRequestedCollection = false; + + if (_arSession.State != ARSessionState.Running) + return; + + var configCopy = ARWorldTrackingConfigurationFactory.Create(); + _preChangeConfiguration.CopyTo(configCopy); + + // The ARSession will call _CollectChanges. + // Keep the ARConfiguration from the last run, but have a fresh slate for run options. + // Just because a dev wanted to reset tracking on the previous run doesn't mean they want + // changing plane detection, for example, to reset tracking again. + _arSession.Run(configCopy, ARSessionRunOptions.None); + } + } + } +} diff --git a/Assets/ARDK/AR/Configuration/ARSessionChangesCollector.cs.meta b/Assets/ARDK/AR/Configuration/ARSessionChangesCollector.cs.meta new file mode 100644 index 0000000..121493c --- /dev/null +++ b/Assets/ARDK/AR/Configuration/ARSessionChangesCollector.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 1de6d853267447e09259eeea8f6d67a9 +timeCreated: 1614110348 \ No newline at end of file diff --git a/Assets/ARDK/AR/Configuration/ARSoftwareSupport.cs b/Assets/ARDK/AR/Configuration/ARSoftwareSupport.cs new file mode 100644 index 0000000..feca2d7 --- /dev/null +++ b/Assets/ARDK/AR/Configuration/ARSoftwareSupport.cs @@ -0,0 +1,19 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.AR.Configuration +{ + /// Possible states of support by the currently installed software for a particular + /// configuration. + public enum ARSoftwareSupport + { + /// The current software level does not support a particular configuration. + NotSupported = 0, + + /// Software of operating system or native AR service too low for a particular configuration. + /// Or specific software is not installed (e.g. ArCore) + SupportedNeedsUpdate = 1, + + /// Software supports a particular configuration. + Supported = 2, + } +} diff --git a/Assets/ARDK/AR/Configuration/ARSoftwareSupport.cs.meta b/Assets/ARDK/AR/Configuration/ARSoftwareSupport.cs.meta new file mode 100644 index 0000000..c173f45 --- /dev/null +++ b/Assets/ARDK/AR/Configuration/ARSoftwareSupport.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 183b1bd647fc4b1f9be0ecafba1fef65 +timeCreated: 1594225485 \ No newline at end of file diff --git a/Assets/ARDK/AR/Configuration/ARWorldTrackingConfigurationFactory.cs b/Assets/ARDK/AR/Configuration/ARWorldTrackingConfigurationFactory.cs new file mode 100644 index 0000000..aa5c6a3 --- /dev/null +++ b/Assets/ARDK/AR/Configuration/ARWorldTrackingConfigurationFactory.cs @@ -0,0 +1,113 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.AR.Awareness.Depth.Generators; + +namespace Niantic.ARDK.AR.Configuration +{ + public static class ARWorldTrackingConfigurationFactory + { + /// Perform an asynchronous check as to whether the hardware and software are capable of and + /// support the ARWorldTrackingConfiguration. + /// @note + /// Returns ARHardwareCapability.Capable and ARSoftwareSupport.Supported when run + /// in the Unity Editor. + public static void CheckCapabilityAndSupport + ( + Action callback + ) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NativeARWorldTrackingConfiguration._CheckCapabilityAndSupport(callback); + #pragma warning disable 0162 + else + callback(ARHardwareCapability.Capable, ARSoftwareSupport.Supported); + #pragma warning restore 0162 + } + + /// Check whether the device supports lidar depth. + /// @note Returns false when run in the Unity Editor. + public static bool CheckLidarDepthSupport() + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _NativeARWorldTrackingConfiguration._CheckLidarDepthSupport(); + + #pragma warning disable 0162 + return false; + #pragma warning restore 0162 + } + + /// Check whether the device supports depth estimation. + /// @note Returns true when run in the Unity Editor. + public static bool CheckDepthEstimationSupport() + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _NativeARWorldTrackingConfiguration._CheckDepthEstimationSupport(); + + #pragma warning disable 0162 + return true; + #pragma warning restore 0162 + } + + /// Check whether the device supports depth + /// @note Returns true when run in the Unity Editor. + public static bool CheckDepthSupport() + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _NativeARWorldTrackingConfiguration._CheckDepthSupport(); + + #pragma warning disable 0162 + return true; + #pragma warning restore 0162 + } + + /// Check whether the device supports semantic segmentation. + /// @note Returns true when run in the Unity Editor. + public static bool CheckSemanticSegmentationSupport() + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _NativeARWorldTrackingConfiguration._CheckSemanticSegmentationSupport(); + + #pragma warning disable 0162 + return true; + #pragma warning restore 0162 + } + + /// Check whether the device supports meshing. + /// @note Returns true when run in the Unity Editor. + public static bool CheckMeshingSupport() + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _NativeARWorldTrackingConfiguration._CheckMeshingSupport(); + + #pragma warning disable 0162 + return true; + #pragma warning restore 0162 + } + + /// Initializes a new instance of the ARWorldTrackingConfiguration class. + public static IARWorldTrackingConfiguration Create() + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return new _NativeARWorldTrackingConfiguration(); + + #pragma warning disable 0162 + return new _SerializableARWorldTrackingConfiguration(); + #pragma warning restore 0162 + } + + /// Initializes a new instance of the ARWorldTrackingConfiguration class. + /// @note this is an experimental feature + internal static IARWorldTrackingConfiguration _CreatePlaybackConfig() + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + // Enable playback + return new _NativeARWorldTrackingConfiguration(true); + + #pragma warning disable 0162 + return new _SerializableARWorldTrackingConfiguration(); + #pragma warning restore 0162 + } + } +} diff --git a/Assets/ARDK/AR/Configuration/ARWorldTrackingConfigurationFactory.cs.meta b/Assets/ARDK/AR/Configuration/ARWorldTrackingConfigurationFactory.cs.meta new file mode 100644 index 0000000..bc87407 --- /dev/null +++ b/Assets/ARDK/AR/Configuration/ARWorldTrackingConfigurationFactory.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a3a328bae93d48ef9659c7c1665ec378 +timeCreated: 1594242197 \ No newline at end of file diff --git a/Assets/ARDK/AR/Configuration/DepthFeatures.cs b/Assets/ARDK/AR/Configuration/DepthFeatures.cs new file mode 100644 index 0000000..0aff627 --- /dev/null +++ b/Assets/ARDK/AR/Configuration/DepthFeatures.cs @@ -0,0 +1,18 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +namespace Niantic.ARDK.AR.Configuration +{ + [Flags] + public enum DepthFeatures + { + None = 0, + + /// Basic depth estimation. Will result in a DisparityBuffer provided alongside ARFrame objects + Depth = 1, + + /// Transforms DisparityBuffer frames into a set of world space points, stored in ARFrame + PointCloud = 2, + } +} diff --git a/Assets/ARDK/AR/Configuration/DepthFeatures.cs.meta b/Assets/ARDK/AR/Configuration/DepthFeatures.cs.meta new file mode 100644 index 0000000..c893d13 --- /dev/null +++ b/Assets/ARDK/AR/Configuration/DepthFeatures.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 33fc98ab6dcf4c17bc08f9caf6ee369c +timeCreated: 1594225558 \ No newline at end of file diff --git a/Assets/ARDK/AR/Configuration/IARConfiguration.cs b/Assets/ARDK/AR/Configuration/IARConfiguration.cs new file mode 100644 index 0000000..9490757 --- /dev/null +++ b/Assets/ARDK/AR/Configuration/IARConfiguration.cs @@ -0,0 +1,38 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.ObjectModel; + +namespace Niantic.ARDK.AR.Configuration +{ + /// The interface for AR session configurations. + /// @note + /// You will not create or work with instances of this interface. Instead, you create + /// one of the more specialized sub-classes. In order to run an AR session, + /// you must pass in a configuration (one of these sub-classes) that most matches the type of + /// AR experience you wish to provide with your app or game. + public interface IARConfiguration: + IDisposable + { + /// A boolean specifying whether or not camera images are analyzed to estimate scene lighting. + bool IsLightEstimationEnabled { get; set; } + + /// A value specifying how the session maps the real-world device motion into a + /// coordinate system. + /// @note This is an iOS-only value. + WorldAlignment WorldAlignment { get; set; } + + /// Returns a collection of supported video formats by this configuration and device. + /// @note iOS-only value. + /// @note Not supported in Virtual Studio. + ReadOnlyCollection SupportedVideoFormats { get; } + + /// A value specifying the options to use for the output video stream. + /// @note This is an iOS-only value. + /// @note **May be null** depending on system version. + IARVideoFormat VideoFormat { get; set; } + + /// Copies the values of this configuration into the target configuration. + void CopyTo(IARConfiguration target); + } +} diff --git a/Assets/ARDK/AR/Configuration/IARConfiguration.cs.meta b/Assets/ARDK/AR/Configuration/IARConfiguration.cs.meta new file mode 100644 index 0000000..6cf5252 --- /dev/null +++ b/Assets/ARDK/AR/Configuration/IARConfiguration.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 1860efd3fac74d9e8c85050eaa959379 +timeCreated: 1594226041 \ No newline at end of file diff --git a/Assets/ARDK/AR/Configuration/IARWorldTrackingConfiguration.cs b/Assets/ARDK/AR/Configuration/IARWorldTrackingConfiguration.cs new file mode 100644 index 0000000..92abaec --- /dev/null +++ b/Assets/ARDK/AR/Configuration/IARWorldTrackingConfiguration.cs @@ -0,0 +1,72 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; + +using Niantic.ARDK.AR.Awareness.Depth.Generators; +using Niantic.ARDK.AR.ReferenceImage; +using Niantic.ARDK.AR.SLAM; +using Niantic.ARDK.Utilities.Collections; + +namespace Niantic.ARDK.AR.Configuration +{ + public interface IARWorldTrackingConfiguration: + IARConfiguration + { + /// A value specifying how and whether the session will detect real-world surfaces. + /// @note Defaults to PlaneDetection.None. + PlaneDetection PlaneDetection { get; set; } + + /// Used to get or set the reference images to detect when running this configuration. + /// @note Not supported in Editor. + IReadOnlyCollection DetectionImages { get; set; } + + /// A value specifying whether the camera should use autofocus or not when running. + bool IsAutoFocusEnabled { get; set; } + + /// A boolean specifying whether the session will generate the necessary data to enable peer-to-peer AR experiences. + /// Defaults to false + bool IsSharedExperienceEnabled { get; set; } + + /// A boolean specifying whether or not depths are enabled. + bool IsDepthEnabled { get; set; } + + /// A boolean specifying whether or not depth point cloud generation are enabled. + bool IsDepthPointCloudEnabled { get; set; } + + /// A value specifying how many times the depth generation routine + /// should target running per second. + UInt32 DepthTargetFrameRate { get; set; } + + /// A boolean specifying whether or not semantic segmentation is enabled. + bool IsSemanticSegmentationEnabled { get; set; } + + /// A value specifying how many times the semantic segmentation routine + /// should target running per second. + UInt32 SemanticTargetFrameRate { get; set; } + + /// A boolean specifying whether or not meshing is enabled. + bool IsMeshingEnabled { get; set; } + + /// A value specifying how many times the meshing routine + /// should target running per second. + UInt32 MeshingTargetFrameRate { get; set; } + + /// A value specifying the radius in meters of the meshed area around the player. The minimum value is 5 meters. + /// The default value is 0, meaning that there is no limitations while the mesh grows forever. + float MeshingRadius { get; set; } + + /// A value specifying the target size of a mesh block in meters. + float MeshingTargetBlockSize { get; set; } + + /// + /// Set the detection images for this configuration asynchronously. The provided callback will + /// be called upon completion. + /// + void SetDetectionImagesAsync + ( + IReadOnlyCollection detectionImages, + Action completionHandler + ); + } +} diff --git a/Assets/ARDK/AR/Configuration/IARWorldTrackingConfiguration.cs.meta b/Assets/ARDK/AR/Configuration/IARWorldTrackingConfiguration.cs.meta new file mode 100644 index 0000000..04a9984 --- /dev/null +++ b/Assets/ARDK/AR/Configuration/IARWorldTrackingConfiguration.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 94808e4116a7494c9e6be4117238841e +timeCreated: 1594226665 \ No newline at end of file diff --git a/Assets/ARDK/AR/Configuration/PlaneDetection.cs b/Assets/ARDK/AR/Configuration/PlaneDetection.cs new file mode 100644 index 0000000..1116a66 --- /dev/null +++ b/Assets/ARDK/AR/Configuration/PlaneDetection.cs @@ -0,0 +1,25 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +namespace Niantic.ARDK.AR.Configuration +{ + /// + /// Options for detecting real-world surfaces with a world-tracking configuration. + /// + /// Limit changing this enum, because it is used in comparisons with the + /// ARDK.AR.Anchors.PlaneAlignment enum. This rigidness is due to how these enums + /// are backed in ARKit and ARCore. + [Flags] + public enum PlaneDetection + { + /// No plane detection. + None = 0, + + /// Used for detecting planar surfaces perpendicular to gravity. + Horizontal = 1, + + /// Used for detecting planar surfaces parallel to gravity. + Vertical = 2, + } +} diff --git a/Assets/ARDK/AR/Configuration/PlaneDetection.cs.meta b/Assets/ARDK/AR/Configuration/PlaneDetection.cs.meta new file mode 100644 index 0000000..707e70e --- /dev/null +++ b/Assets/ARDK/AR/Configuration/PlaneDetection.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 1d74119e970d4296b89d6347458f1f4e +timeCreated: 1594225644 \ No newline at end of file diff --git a/Assets/ARDK/AR/Configuration/WorldAlignment.cs b/Assets/ARDK/AR/Configuration/WorldAlignment.cs new file mode 100644 index 0000000..17df8bb --- /dev/null +++ b/Assets/ARDK/AR/Configuration/WorldAlignment.cs @@ -0,0 +1,21 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.AR.Configuration +{ + /// @brief Options for how a scene coordinate system is contructed based on real-world device motion. + /// @note This is an iOS-only enum. + public enum WorldAlignment + { + /// The coordinate system's y-axis is parallel to gravity, and it's origin + /// is the initial position of the device. + Gravity = 0, + + /// The coordinate system's y-axis is parallel to gravity, and the x and z-axes + /// are aligned to east and south, respectively. Note, the origin remains the + /// initial position of the device. + GravityAndHeading = 1, + + /// The coordinate system is locked to match the orientation of the device camera. + Camera = 2, + } +} diff --git a/Assets/ARDK/AR/Configuration/WorldAlignment.cs.meta b/Assets/ARDK/AR/Configuration/WorldAlignment.cs.meta new file mode 100644 index 0000000..18e5e53 --- /dev/null +++ b/Assets/ARDK/AR/Configuration/WorldAlignment.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3606e391a4674a7c82dca0cc48649242 +timeCreated: 1594225386 \ No newline at end of file diff --git a/Assets/ARDK/AR/Configuration/_ARConfigurationValidator.cs b/Assets/ARDK/AR/Configuration/_ARConfigurationValidator.cs new file mode 100644 index 0000000..081a3a8 --- /dev/null +++ b/Assets/ARDK/AR/Configuration/_ARConfigurationValidator.cs @@ -0,0 +1,152 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.AR.SLAM; +using Niantic.ARDK.Configuration; +using Niantic.ARDK.VirtualStudio.AR; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Configuration +{ + internal static class _ARConfigurationValidator + { + private static bool IsValidConfiguration(this IARConfiguration config, out string message) + { + message = string.Empty; + + if (config is IARWorldTrackingConfiguration worldConfig) + { + var hasHeadingAlignment = (worldConfig.WorldAlignment == WorldAlignment.GravityAndHeading); + if (worldConfig.IsSharedExperienceEnabled && hasHeadingAlignment) + { + message = + "Configuration with SharedExperienceEnabled can not use GravityAndHeading world " + + "alignment."; + + return false; + } + + if (worldConfig.IsMeshingEnabled && hasHeadingAlignment) + { + message = + "Configuration with IsMeshingEnabled can not use GravityAndHeading world alignment."; + + return false; + } + } + + return true; + } + + private static void SetMissingValues(this IARConfiguration config) + { + var worldConfig = config as IARWorldTrackingConfiguration; + + if (worldConfig == null) + return; + + + var isDepthEnabled = worldConfig.IsDepthEnabled; + var isPointCloudEnabled = worldConfig.IsDepthPointCloudEnabled; + + if (isPointCloudEnabled && !isDepthEnabled) + { + ARLog._WarnRelease + ( + "Enabling depth because depth point clouds were enabled. Use the ARDepthManager " + + "component or the IARWorldTrackingConfiguration properties to further configure depth " + + "functionality." + ); + + worldConfig.IsDepthEnabled = true; + } + + if (worldConfig.IsMeshingEnabled && !isDepthEnabled) + { + ARLog._WarnRelease + ( + "Enabling depth because meshing was enabled. Use the ARDepthManager component or " + + "the IARWorldTrackingConfiguration properties to further configure depth functionality." + ); + + worldConfig.IsDepthEnabled = true; + } + + var needsContextAwarenessUrl = + isDepthEnabled || + worldConfig.IsMeshingEnabled || + worldConfig.IsSemanticSegmentationEnabled; + + var hasEmptyUrl = string.IsNullOrEmpty(ArdkGlobalConfig.GetContextAwarenessUrl()); + + if (needsContextAwarenessUrl && hasEmptyUrl) + { + ARLog._Debug("Context Awareness URL was not set. The default URL will be used."); + ArdkGlobalConfig.SetContextAwarenessUrl(""); + } + } + + private static void CheckDeviceSupport(this IARConfiguration config) + { + var worldConfig = config as IARWorldTrackingConfiguration; + + if (worldConfig == null) + return; + + if (worldConfig.IsDepthEnabled && + !ARWorldTrackingConfigurationFactory.CheckDepthEstimationSupport()) + { + ARLog._Error + ( + "Depth estimation is not supported on this device. " + + "Unexpected behaviour or crashes may occur." + ); + } + + if (worldConfig.IsMeshingEnabled && + !ARWorldTrackingConfigurationFactory.CheckMeshingSupport()) + { + ARLog._Error + ( + "Meshing is not supported on this device. " + + "Unexpected behaviour or crashes may occur." + ); + } + + if (worldConfig.IsSemanticSegmentationEnabled && + !ARWorldTrackingConfigurationFactory.CheckSemanticSegmentationSupport()) + { + ARLog._Error + ( + "Semantic segmentation is not supported on this device. " + + "Unexpected behaviour or crashes may occur." + ); + } + } + + public static bool RunAllChecks + ( + IARSession arSession, + IARConfiguration newConfiguration + ) + { + string validConfigCheckMessage; + if (!newConfiguration.IsValidConfiguration(out validConfigCheckMessage)) + { + ARLog._Error(validConfigCheckMessage); + return false; + } + + newConfiguration.SetMissingValues(); + + // ARDK's device support checks serve as recommendations, not a hard block. + // Devices are still able to try to run unsupported features. + newConfiguration.CheckDeviceSupport(); + + return true; + } + } +} diff --git a/Assets/ARDK/AR/Configuration/_ARConfigurationValidator.cs.meta b/Assets/ARDK/AR/Configuration/_ARConfigurationValidator.cs.meta new file mode 100644 index 0000000..0792a8e --- /dev/null +++ b/Assets/ARDK/AR/Configuration/_ARConfigurationValidator.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3ac7248d033f4fab95b57144f065cd5d +timeCreated: 1603985358 \ No newline at end of file diff --git a/Assets/ARDK/AR/Configuration/_ARWorldTrackingConfigurationSerializer.cs b/Assets/ARDK/AR/Configuration/_ARWorldTrackingConfigurationSerializer.cs new file mode 100644 index 0000000..15c7d23 --- /dev/null +++ b/Assets/ARDK/AR/Configuration/_ARWorldTrackingConfigurationSerializer.cs @@ -0,0 +1,80 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +#if (UNITY_IOS || UNITY_ANDROID) && !UNITY_EDITOR +using T = Niantic.ARDK.AR.Configuration._NativeARWorldTrackingConfiguration; +#else +using T = Niantic.ARDK.AR.Configuration._SerializableARWorldTrackingConfiguration; +#endif +using System; + +using Niantic.ARDK.AR.SLAM; +using Niantic.ARDK.Utilities.BinarySerialization; +using Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers; + +namespace Niantic.ARDK.AR.Configuration +{ + internal sealed class _ARWorldTrackingConfigurationSerializer: + BaseItemSerializer + { + internal static readonly _ARWorldTrackingConfigurationSerializer _instance = + new _ARWorldTrackingConfigurationSerializer(); + + private _ARWorldTrackingConfigurationSerializer() + { + } + + protected override void DoSerialize(BinarySerializer serializer, T item) + { + // Base + BooleanSerializer.Instance.Serialize(serializer, item.IsAutoFocusEnabled); + BooleanSerializer.Instance.Serialize(serializer, item.IsSharedExperienceEnabled); + + // World Tracking + BooleanSerializer.Instance.Serialize(serializer, item.IsLightEstimationEnabled); + EnumSerializer.ForType().Serialize(serializer, item.WorldAlignment); + EnumSerializer.ForType().Serialize(serializer, item.PlaneDetection); + + // Depth + BooleanSerializer.Instance.Serialize(serializer, item.IsDepthEnabled); + CompressedUInt32Serializer.Instance.Serialize(serializer, item.DepthTargetFrameRate); + + // Semantics + BooleanSerializer.Instance.Serialize(serializer, item.IsSemanticSegmentationEnabled); + CompressedUInt32Serializer.Instance.Serialize(serializer, item.SemanticTargetFrameRate); + + // Meshing + BooleanSerializer.Instance.Serialize(serializer, item.IsMeshingEnabled); + CompressedUInt32Serializer.Instance.Serialize(serializer, item.MeshingTargetFrameRate); + FloatSerializer.Instance.Serialize(serializer, item.MeshingTargetBlockSize); + } + + protected override T DoDeserialize(BinaryDeserializer deserializer) + { + var result = new T(); + + // Base + result.IsAutoFocusEnabled = BooleanSerializer.Instance.Deserialize(deserializer); + result.IsSharedExperienceEnabled = BooleanSerializer.Instance.Deserialize(deserializer); + + // World Tracking + result.IsLightEstimationEnabled = BooleanSerializer.Instance.Deserialize(deserializer); + result.WorldAlignment = EnumSerializer.ForType().Deserialize(deserializer); + result.PlaneDetection = EnumSerializer.ForType().Deserialize(deserializer); + + // Depth + result.IsDepthEnabled = BooleanSerializer.Instance.Deserialize(deserializer); + result.DepthTargetFrameRate = CompressedUInt32Serializer.Instance.Deserialize(deserializer); + + // Semantics + result.IsSemanticSegmentationEnabled = BooleanSerializer.Instance.Deserialize(deserializer); + result.SemanticTargetFrameRate = CompressedUInt32Serializer.Instance.Deserialize(deserializer); + + // Meshing + result.IsMeshingEnabled = BooleanSerializer.Instance.Deserialize(deserializer); + result.MeshingTargetFrameRate = CompressedUInt32Serializer.Instance.Deserialize(deserializer); + result.MeshingTargetBlockSize = FloatSerializer.Instance.Deserialize(deserializer); + + return result; + } + } +} diff --git a/Assets/ARDK/AR/Configuration/_ARWorldTrackingConfigurationSerializer.cs.meta b/Assets/ARDK/AR/Configuration/_ARWorldTrackingConfigurationSerializer.cs.meta new file mode 100644 index 0000000..55e6e3a --- /dev/null +++ b/Assets/ARDK/AR/Configuration/_ARWorldTrackingConfigurationSerializer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6837a7f07c6e4a1db91970fc76b3fb6c +timeCreated: 1594247622 \ No newline at end of file diff --git a/Assets/ARDK/AR/Configuration/_NativeARConfiguration.cs b/Assets/ARDK/AR/Configuration/_NativeARConfiguration.cs new file mode 100644 index 0000000..05ef294 --- /dev/null +++ b/Assets/ARDK/AR/Configuration/_NativeARConfiguration.cs @@ -0,0 +1,220 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.ObjectModel; +using System.Runtime.InteropServices; + +using AOT; + +using Niantic.ARDK.AR.Awareness.Depth.Generators; +using Niantic.ARDK.AR.VideoFormat; +using Niantic.ARDK.Internals; +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.AR.Configuration +{ + internal abstract class _NativeARConfiguration: + IARConfiguration + { + static _NativeARConfiguration() + { + Platform.Init(); + } + + internal _NativeARConfiguration(IntPtr nativeHandle) + { + if (nativeHandle == IntPtr.Zero) + throw new ArgumentException("nativeHandle can't be Zero.", nameof(nativeHandle)); + + _nativeHandle = nativeHandle; + GC.AddMemoryPressure(_MemoryPressure); + } + + private static void _ReleaseImmediate(IntPtr nativeHandle) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARConfiguration_Release(nativeHandle); + } + + ~_NativeARConfiguration() + { + _ReleaseImmediate(_nativeHandle); + GC.RemoveMemoryPressure(_MemoryPressure); + } + + public void Dispose() + { + GC.SuppressFinalize(this); + + var nativeHandle = _nativeHandle; + if (nativeHandle != IntPtr.Zero) + { + _nativeHandle = IntPtr.Zero; + + _ReleaseImmediate(nativeHandle); + GC.RemoveMemoryPressure(_MemoryPressure); + } + } + + private IntPtr _nativeHandle; + internal IntPtr _NativeHandle + { + get { return _nativeHandle; } + } + + // Used to inform the C# GC that there is managed memory held by this object. + protected virtual long _MemoryPressure + { + get { return (1L * 1L) + (1L * 8L); } + } + + public abstract ReadOnlyCollection SupportedVideoFormats { get; } + + public bool IsLightEstimationEnabled + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _NARConfiguration_IsLightEstimationEnabled(_nativeHandle) != 0; + + #pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + } + set + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARConfiguration_SetLightEstimationEnabled(_nativeHandle, value ? 1 : (UInt32)0); + } + } + + public WorldAlignment WorldAlignment + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return (WorldAlignment)_NARConfiguration_GetWorldAlignment(_nativeHandle); + +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + set + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARConfiguration_SetWorldAlignment(_nativeHandle, (UInt64)value); + } + } + + // TODO: Maybe we should review this. It seems we create a new instance every time we call + // get. Are users disposing it? Are they allowed to dispose it? + public IARVideoFormat VideoFormat + { + get + { + var videoFormatHandle = _NARConfiguration_GetVideoFormat(_nativeHandle); + + if (videoFormatHandle == IntPtr.Zero) + return null; + + return _NativeARVideoFormat._FromNativeHandle(videoFormatHandle); + } + set + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + if (!(value is _NativeARVideoFormat nativeFormat)) + return; + + _NARConfiguration_SetVideoFormat(_nativeHandle, nativeFormat._NativeHandle); + } + } + } + + public virtual void CopyTo(IARConfiguration target) + { + target.IsLightEstimationEnabled = IsLightEstimationEnabled; + target.WorldAlignment = WorldAlignment; + var videoFormat = VideoFormat; + if (videoFormat != null) + target.VideoFormat = videoFormat; + } + + [MonoPInvokeCallback(typeof(_ARConfiguration_CheckCapabilityAndSupport_Callback))] + protected static void ConfigurationCheckCapabilityAndSupportCallback + ( + IntPtr context, + UInt64 hardwareCapability, + UInt64 softwareSupport + ) + { + var safeHandle = + SafeGCHandle>.FromIntPtr(context); + + var callback = safeHandle.TryGetInstance(); + safeHandle.Free(); + + if (callback == null) + { + // callback was deallocated + return; + } + + _CallbackQueue.QueueCallback + ( + () => + { + callback((ARHardwareCapability)hardwareCapability, (ARSoftwareSupport)softwareSupport); + } + ); + } + + [DllImport(_ARDKLibrary.libraryName)] + protected static extern void _NARConfiguration_CheckCapabilityAndSupport + ( + UInt64 type, + IntPtr applicationContext, + _ARConfiguration_CheckCapabilityAndSupport_Callback callback + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARConfiguration_Release(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern UInt32 _NARConfiguration_IsLightEstimationEnabled(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARConfiguration_SetLightEstimationEnabled + ( + IntPtr nativeHandle, + UInt32 enabled + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern UInt64 _NARConfiguration_GetWorldAlignment(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARConfiguration_SetWorldAlignment + ( + IntPtr nativeHandle, + UInt64 worldAlignment + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NARConfiguration_GetVideoFormat(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARConfiguration_SetVideoFormat + ( + IntPtr nativeHandle, + IntPtr nativeVideoFormat + ); + + protected delegate void _ARConfiguration_CheckCapabilityAndSupport_Callback + ( + IntPtr context, + UInt64 hardwareCapability, + UInt64 softwareSupport + ); + } +} diff --git a/Assets/ARDK/AR/Configuration/_NativeARConfiguration.cs.meta b/Assets/ARDK/AR/Configuration/_NativeARConfiguration.cs.meta new file mode 100644 index 0000000..96a017e --- /dev/null +++ b/Assets/ARDK/AR/Configuration/_NativeARConfiguration.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 27f975d127ec484a9b1e980e4e0130db +timeCreated: 1594230588 \ No newline at end of file diff --git a/Assets/ARDK/AR/Configuration/_NativeARWorldTrackingConfiguration.cs b/Assets/ARDK/AR/Configuration/_NativeARWorldTrackingConfiguration.cs new file mode 100644 index 0000000..a1b4566 --- /dev/null +++ b/Assets/ARDK/AR/Configuration/_NativeARWorldTrackingConfiguration.cs @@ -0,0 +1,718 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Runtime.InteropServices; + +using AOT; + +using Niantic.ARDK.AR.Awareness.Depth.Generators; +using Niantic.ARDK.AR.ReferenceImage; +using Niantic.ARDK.AR.SLAM; +using Niantic.ARDK.AR.VideoFormat; +using Niantic.ARDK.Internals; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Collections; +using Niantic.ARDK.Utilities.Logging; + +namespace Niantic.ARDK.AR.Configuration +{ + internal sealed class _NativeARWorldTrackingConfiguration: + _NativeARConfiguration, + IARWorldTrackingConfiguration + { + /// Perform an asynchronous check as to whether the hardware and software are capable of and + /// support the ARWorldTrackingConfiguration. + internal static void _CheckCapabilityAndSupport + ( + Action callback + ) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + try + { + _NARConfiguration_CheckCapabilityAndSupport + ( + 1, + SafeGCHandle.AllocAsIntPtr(callback), + ConfigurationCheckCapabilityAndSupportCallback + ); + } + catch (DllNotFoundException e) + { + ARLog._DebugFormat("Failed to check ARDK system compatibility: {0}", false, e); + callback(ARHardwareCapability.NotCapable, ARSoftwareSupport.NotSupported); + } + } + } + + internal static bool _CheckLidarDepthSupport() + { + try + { + return _NARConfiguration_CheckLidarDepthSupport(); + } + catch (DllNotFoundException e) + { + ARLog._DebugFormat("Failed to check ARDK system compatibility: {0}", false, e); + return false; + } + } + + internal static bool _CheckDepthEstimationSupport() + { + try + { + return _NARConfiguration_CheckDepthEstimationSupport(); + } + catch (DllNotFoundException e) + { + ARLog._DebugFormat("Failed to check ARDK system compatibility: {0}", false, e); + return false; + } + } + + internal static bool _CheckDepthSupport() + { + try + { + return _NARConfiguration_CheckDepthSupport(); + } + catch (DllNotFoundException e) + { + ARLog._DebugFormat("Failed to check ARDK system compatibility: {0}", false, e); + return false; + } + } + + internal static bool _CheckSemanticSegmentationSupport() + { + try + { + return _NARConfiguration_CheckSemanticSegmentationSupport(); + } + catch (DllNotFoundException e) + { + ARLog._DebugFormat("Failed to check ARDK system compatibility: {0}", false, e); + return false; + } + } + + internal static bool _CheckMeshingSupport() + { + try + { + return _NARConfiguration_CheckMeshingSupport(); + } + catch (DllNotFoundException e) + { + ARLog._DebugFormat("Failed to check ARDK system compatibility: {0}", false, e); + return false; + } + } + + private static IntPtr InitNativeHandle(bool playbackEnabled) + { +#pragma warning disable 0429 + IntPtr result = new IntPtr(0); + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + result = playbackEnabled ? _NARPlaybackWorldTrackingConfiguration_Init() : _NARWorldTrackingConfiguration_Init(); + } + return result; +#pragma warning restore 0429 + } + + internal _NativeARWorldTrackingConfiguration(bool playbackEnabled=false): + this(InitNativeHandle(playbackEnabled)) + { + } + + internal _NativeARWorldTrackingConfiguration(IntPtr nativeHandle): + base(nativeHandle) + { + } + + protected override long _MemoryPressure + { + get { return base._MemoryPressure + 8; } + } + + public override ReadOnlyCollection SupportedVideoFormats + { + get + { + var rawFormats = EmptyArray.Instance; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + while (true) + { + var obtained = + _NARWorldTrackingConfiguration_GetSupportedVideoFormats + ( + _NativeHandle, + rawFormats.Length, + rawFormats + ); + + if (obtained == rawFormats.Length) + break; + + rawFormats = new IntPtr[Math.Abs(obtained)]; + } + } + + var count = rawFormats.Length; + + if (count == 0) + return EmptyReadOnlyCollection.Instance; + + var formats = new IARVideoFormat[count]; + + for (var i = 0; i < count; i++) + formats[i] = _NativeARVideoFormat._FromNativeHandle(rawFormats[i]); + + return new ReadOnlyCollection(formats); + } + } + + public PlaneDetection PlaneDetection + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return (PlaneDetection)_NARWorldTrackingConfiguration_GetPlaneDetection(_NativeHandle); + + #pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + } + set + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARWorldTrackingConfiguration_SetPlaneDetection(_NativeHandle, (UInt64)value); + } + } + + public IReadOnlyCollection DetectionImages + { + get + { + var rawImages = EmptyArray.Instance; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + while (true) + { + var obtained = + _NARWorldTrackingConfiguration_GetDetectionImages + ( + _NativeHandle, + rawImages.Length, + rawImages + ); + + if (obtained == rawImages.Length) + break; + + rawImages = new IntPtr[Math.Abs(obtained)]; + } + } + + var images = new HashSet(); + var count = rawImages.Length; + + for (var i = 0; i < count; i++) + images.Add(_NativeARReferenceImage._FromNativeHandle(rawImages[i])); + + return images.AsArdkReadOnly(); + } + set + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + var rawImages = + (from image in value select ((_NativeARReferenceImage)image)._NativeHandle).ToArray(); + + _NARWorldTrackingConfiguration_SetDetectionImages + ( + _NativeHandle, + rawImages, + (UInt64)rawImages.Length + ); + } + } + } + + public bool IsAutoFocusEnabled + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _NARWorldTrackingConfiguration_IsAutoFocusEnabled(_NativeHandle) != 0; + + #pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + } + set + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARWorldTrackingConfiguration_SetAutoFocusEnabled(_NativeHandle, value ? 1 : (UInt32)0); + } + } + + public bool IsSharedExperienceEnabled + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _NARWorldTrackingConfiguration_IsCollaborationEnabled(_NativeHandle) != 0; + + #pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + } + set + { + UInt32 uintValue = value ? 1 : (UInt32)0; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARWorldTrackingConfiguration_SetCollaborationEnabled(_NativeHandle, uintValue); + } + } + + public uint DepthTargetFrameRate + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _NARConfiguration_GetDepthTargetFrameRate(_NativeHandle); + + #pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + } + set + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARConfiguration_SetDepthTargetFrameRate(_NativeHandle, value); + } + } + + public uint SemanticTargetFrameRate + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _NARConfiguration_GetSemanticTargetFrameRate(_NativeHandle); + + #pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + } + set + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARConfiguration_SetSemanticTargetFrameRate(_NativeHandle, value); + } + } + + public bool IsDepthEnabled + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _NARConfiguration_IsDepthEnabled(_NativeHandle) != 0; + +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + set + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARConfiguration_SetDepthEnabled(_NativeHandle, value ? 1 : (UInt32)0); + } + } + + public bool IsDepthPointCloudEnabled { get; set; } + + public bool IsSemanticSegmentationEnabled + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _NARConfiguration_IsSemanticSegmentationEnabled(_NativeHandle) != 0; +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + set + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARConfiguration_SetSemanticSegmentationEnabled(_NativeHandle, value ? 1 : (UInt32)0); + } + } + + public bool IsMeshingEnabled + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _NARConfiguration_IsMeshingEnabled(_NativeHandle) != 0; +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + set + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARConfiguration_SetMeshingEnabled(_NativeHandle, value ? 1 : (UInt32)0); + } + } + + public uint MeshingTargetFrameRate + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _NARConfiguration_GetMeshingTargetFrameRate(_NativeHandle); +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + set + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARConfiguration_SetMeshingTargetFrameRate(_NativeHandle, value); + } + } + + public float MeshingRadius + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _NARConfiguration_GetMeshingRadius(_NativeHandle); + #pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + } + set + { + if (value > 0 && value < 5) + { + ARLog._Error + ( + "The smallest meshing radius possible is 5 meters. " + + "Set the value to 0 for an infinite radius." + ); + + return; + } + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARConfiguration_SetMeshingRadius(_NativeHandle, value); + } + } + + public float MeshingTargetBlockSize + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _NARConfiguration_GetMeshingTargetBlockSize(_NativeHandle); +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + set + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARConfiguration_SetMeshingTargetBlockSize(_NativeHandle, value); + } + } + + public void SetDetectionImagesAsync + ( + IReadOnlyCollection detectionImages, + Action completionHandler + ) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + var rawImages = + (from image in detectionImages select ((_NativeARReferenceImage)image)._NativeHandle) + .ToArray(); + + _NARWorldTrackingConfiguration_SetDetectionImagesAsync + ( + _NativeHandle, + rawImages, + (UInt64)rawImages.Length, + SafeGCHandle.AllocAsIntPtr(completionHandler), + SetDetectionImagesAsyncCallback + ); + } + } + + public override void CopyTo(IARConfiguration target) + { + if (!(target is IARWorldTrackingConfiguration worldTarget)) + { + var msg = + "ARWorldTrackingConfiguration cannot be copied into a non-ARWorldTrackingConfiguration."; + + throw new ArgumentException(msg); + } + + base.CopyTo(target); + + worldTarget.PlaneDetection = PlaneDetection; + worldTarget.IsAutoFocusEnabled = IsAutoFocusEnabled; + worldTarget.IsSharedExperienceEnabled = IsSharedExperienceEnabled; + worldTarget.DetectionImages = DetectionImages; + + worldTarget.IsDepthEnabled = IsDepthEnabled; + worldTarget.DepthTargetFrameRate = DepthTargetFrameRate; + worldTarget.IsDepthPointCloudEnabled = IsDepthPointCloudEnabled; + + worldTarget.IsSemanticSegmentationEnabled = IsSemanticSegmentationEnabled; + worldTarget.SemanticTargetFrameRate = SemanticTargetFrameRate; + + worldTarget.IsMeshingEnabled = IsMeshingEnabled; + worldTarget.MeshingTargetFrameRate = MeshingTargetFrameRate; + worldTarget.MeshingTargetBlockSize = MeshingTargetBlockSize; + worldTarget.MeshingRadius = MeshingRadius; + } + + [MonoPInvokeCallback(typeof(_ARWorldTrackingConfiguration_SetDetectionImagesAsync_Handler))] + private static void SetDetectionImagesAsyncCallback(IntPtr context) + { + var actionHandle = SafeGCHandle.FromIntPtr(context); + var callback = actionHandle.TryGetInstance(); + actionHandle.Free(); + + if (callback != null) + _CallbackQueue.QueueCallback(() => { callback(); }); + } + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NARWorldTrackingConfiguration_Init(); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NARPlaybackWorldTrackingConfiguration_Init(); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern Int32 _NARWorldTrackingConfiguration_GetSupportedVideoFormats + ( + IntPtr nativeHandle, + Int32 lengthOfOutSupportedVideoFormats, + IntPtr[] outSupportedVideoFormats + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern UInt64 _NARWorldTrackingConfiguration_GetPlaneDetection + ( + IntPtr nativeHandle + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARWorldTrackingConfiguration_SetPlaneDetection + ( + IntPtr nativeHandle, + UInt64 planeDetection + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern Int32 _NARWorldTrackingConfiguration_GetDetectionImages + ( + IntPtr nativeHandle, + Int32 lengthOfOutDetectionImages, + IntPtr[] outDetectionImages + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARWorldTrackingConfiguration_SetDetectionImages + ( + IntPtr nativeHandle, + IntPtr[] detectionImages, + UInt64 detectionImageCount + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARWorldTrackingConfiguration_SetDetectionImagesAsync + ( + IntPtr nativeHandle, + IntPtr[] detectionImages, + UInt64 detectionImageCount, + IntPtr applicationContext, + _ARWorldTrackingConfiguration_SetDetectionImagesAsync_Handler completionHandler + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern UInt32 _NARWorldTrackingConfiguration_IsAutoFocusEnabled + ( + IntPtr nativeHandle + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARWorldTrackingConfiguration_SetAutoFocusEnabled + ( + IntPtr nativeHandle, + UInt32 enabled + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern UInt32 _NARWorldTrackingConfiguration_IsCollaborationEnabled + ( + IntPtr nativeHandle + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARWorldTrackingConfiguration_SetCollaborationEnabled + ( + IntPtr nativeHandle, + UInt32 enabled + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern UInt32 _NARWorldTrackingConfiguration_GetMappingRole + ( + IntPtr nativeHandle + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARWorldTrackingConfiguration_SetMappingRole + ( + IntPtr nativeHandle, + UInt32 role + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern Guid _NARWorldTrackingConfiguration_GetMapLayerIdentifier + ( + IntPtr nativeHandle + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARWorldTrackingConfiguration_SetMapLayerIdentifier + ( + IntPtr nativeHandle, + Guid identifier + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern UInt32 _NARConfiguration_IsDepthEnabled(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARConfiguration_SetDepthEnabled + ( + IntPtr nativeHandle, + UInt32 enabled + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern UInt32 _NARConfiguration_GetDepthTargetFrameRate(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARConfiguration_SetDepthTargetFrameRate + ( + IntPtr nativeHandle, + UInt32 targetFrameRate + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern UInt32 _NARConfiguration_IsSemanticSegmentationEnabled(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARConfiguration_SetSemanticSegmentationEnabled + ( + IntPtr nativeHandle, + UInt32 enabled + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern UInt32 _NARConfiguration_GetSemanticTargetFrameRate(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARConfiguration_SetSemanticTargetFrameRate + ( + IntPtr nativeHandle, + UInt32 targetFrameRate + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARConfiguration_SetSemanticThreshold + ( + IntPtr nativeHandle, + string channelName, + float threshold + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern UInt32 _NARConfiguration_IsMeshingEnabled(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARConfiguration_SetMeshingEnabled + ( + IntPtr nativeHandle, + UInt32 enabled + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern UInt32 _NARConfiguration_GetMeshingTargetFrameRate(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARConfiguration_SetMeshingTargetFrameRate + ( + IntPtr nativeHandle, + UInt32 targetFrameRate + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern float _NARConfiguration_GetMeshingRadius(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARConfiguration_SetMeshingRadius + ( + IntPtr nativeHandle, + float meshingRadius + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern float _NARConfiguration_GetMeshingTargetBlockSize(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARConfiguration_SetMeshingTargetBlockSize + ( + IntPtr nativeHandle, + float targetFrameRate + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern bool _NARConfiguration_CheckLidarDepthSupport(); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern bool _NARConfiguration_CheckDepthEstimationSupport(); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern bool _NARConfiguration_CheckDepthSupport(); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern bool _NARConfiguration_CheckSemanticSegmentationSupport(); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern bool _NARConfiguration_CheckMeshingSupport(); + + private delegate void _ARWorldTrackingConfiguration_SetDetectionImagesAsync_Handler + ( + IntPtr context + ); + } +} diff --git a/Assets/ARDK/AR/Configuration/_NativeARWorldTrackingConfiguration.cs.meta b/Assets/ARDK/AR/Configuration/_NativeARWorldTrackingConfiguration.cs.meta new file mode 100644 index 0000000..a3003a1 --- /dev/null +++ b/Assets/ARDK/AR/Configuration/_NativeARWorldTrackingConfiguration.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 8e02b1f6aebd422dac173618b6932eea +timeCreated: 1594240280 \ No newline at end of file diff --git a/Assets/ARDK/AR/Configuration/_SerializableARConfiguration.cs b/Assets/ARDK/AR/Configuration/_SerializableARConfiguration.cs new file mode 100644 index 0000000..45c7290 --- /dev/null +++ b/Assets/ARDK/AR/Configuration/_SerializableARConfiguration.cs @@ -0,0 +1,60 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; + +using Niantic.ARDK.AR.Awareness.Depth.Generators; +using Niantic.ARDK.Utilities.Collections; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Configuration +{ + internal abstract class _SerializableARConfiguration: + IARConfiguration + { + public bool IsLightEstimationEnabled { get; set; } + public WorldAlignment WorldAlignment { get; set; } + + private const string _supportedVideoFormatsLogMessage = + "ARWorldTrackingConfiguration.SupportedVideoFormats unsupported in Editor or Standalone!"; + + public ReadOnlyCollection SupportedVideoFormats + { + get + { + ARLog._Error(_supportedVideoFormatsLogMessage); + return EmptyReadOnlyCollection.Instance; + } + } + + public IARVideoFormat VideoFormat + { + get + { + ARLog._Error(_supportedVideoFormatsLogMessage); + return null; + } + set + { + ARLog._Error(_supportedVideoFormatsLogMessage); + } + } + + + + public virtual void CopyTo(IARConfiguration target) + { + target.IsLightEstimationEnabled = IsLightEstimationEnabled; + target.WorldAlignment = WorldAlignment; + } + + void IDisposable.Dispose() + { + // Do nothing. This implementation of IARConfiguration is fully managed. + } + } +} + diff --git a/Assets/ARDK/AR/Configuration/_SerializableARConfiguration.cs.meta b/Assets/ARDK/AR/Configuration/_SerializableARConfiguration.cs.meta new file mode 100644 index 0000000..9d06ebc --- /dev/null +++ b/Assets/ARDK/AR/Configuration/_SerializableARConfiguration.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: dc1de786252f4a54895cfecf30165743 +timeCreated: 1594227380 \ No newline at end of file diff --git a/Assets/ARDK/AR/Configuration/_SerializableARWorldTrackingConfiguration.cs b/Assets/ARDK/AR/Configuration/_SerializableARWorldTrackingConfiguration.cs new file mode 100644 index 0000000..0a60903 --- /dev/null +++ b/Assets/ARDK/AR/Configuration/_SerializableARWorldTrackingConfiguration.cs @@ -0,0 +1,120 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.AR.SLAM; +using System; +using System.Collections.Generic; + +using Niantic.ARDK.AR.Awareness.Depth.Generators; +using Niantic.ARDK.AR.ReferenceImage; +using Niantic.ARDK.Utilities.Collections; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Configuration +{ + internal sealed class _SerializableARWorldTrackingConfiguration: + _SerializableARConfiguration, + IARWorldTrackingConfiguration + { + public PlaneDetection PlaneDetection { get; set; } + + public bool IsAutoFocusEnabled { get; set; } + + public bool IsSharedExperienceEnabled { get; set; } + + public bool IsDepthEnabled { get; set; } + + public bool IsDepthPointCloudEnabled { get; set; } + + public uint DepthTargetFrameRate { get; set; } + + public bool IsSemanticSegmentationEnabled { get; set; } + + public uint SemanticTargetFrameRate { get; set; } + + public bool IsMeshingEnabled { get; set; } + + public uint MeshingTargetFrameRate { get; set; } + + public float MeshingTargetBlockSize { get; set; } + + public float MeshingRadius + { + get { return _meshingRadius; } + set + { + if (value > 0 && value < 5) + { + ARLog._Error + ( + "The smallest meshing radius possible is 5 meters. " + + "Set the value to 0 for an infinite radius." + ); + + return; + } + + _meshingRadius = value; + } + } + + private float _meshingRadius; + + private IReadOnlyCollection _detectionImages = + EmptyArdkReadOnlyCollection.Instance; + public IReadOnlyCollection DetectionImages + { + get + { + return _detectionImages; + } + set + { + _detectionImages = value; + } + } + + public void SetDetectionImagesAsync + ( + IReadOnlyCollection detectionImages, + Action completionHandler + ) + { + _detectionImages = detectionImages; + completionHandler(); + } + + public override void CopyTo(IARConfiguration target) + { + if (!(target is IARWorldTrackingConfiguration worldTarget)) + { + var msg = + "ARWorldTrackingConfiguration cannot be copied into a non-ARWorldTrackingConfiguration."; + + throw new ArgumentException(msg); + } + + base.CopyTo(target); + + worldTarget.PlaneDetection = PlaneDetection; + worldTarget.IsAutoFocusEnabled = IsAutoFocusEnabled; + + worldTarget.IsSharedExperienceEnabled = IsSharedExperienceEnabled; + + worldTarget.IsDepthEnabled = IsDepthEnabled; + worldTarget.DepthTargetFrameRate = DepthTargetFrameRate; + worldTarget.IsDepthPointCloudEnabled = IsDepthPointCloudEnabled; + + worldTarget.IsSemanticSegmentationEnabled = IsSemanticSegmentationEnabled; + worldTarget.SemanticTargetFrameRate = SemanticTargetFrameRate; + + worldTarget.IsMeshingEnabled = IsMeshingEnabled; + worldTarget.MeshingTargetFrameRate = MeshingTargetFrameRate; + worldTarget.MeshingTargetBlockSize = MeshingTargetBlockSize; + worldTarget.MeshingRadius = MeshingRadius; + + // Not copying DetectionImages because ARReferenceImage is not supported in Editor. + } + } +} diff --git a/Assets/ARDK/AR/Configuration/_SerializableARWorldTrackingConfiguration.cs.meta b/Assets/ARDK/AR/Configuration/_SerializableARWorldTrackingConfiguration.cs.meta new file mode 100644 index 0000000..d841247 --- /dev/null +++ b/Assets/ARDK/AR/Configuration/_SerializableARWorldTrackingConfiguration.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 67f5415256bc450196322044603dab5c +timeCreated: 1594230022 \ No newline at end of file diff --git a/Assets/ARDK/AR/ContextAwarenessArgs.cs b/Assets/ARDK/AR/ContextAwarenessArgs.cs new file mode 100644 index 0000000..c1c11c1 --- /dev/null +++ b/Assets/ARDK/AR/ContextAwarenessArgs.cs @@ -0,0 +1,39 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; + +using Niantic.ARDK.AR.Awareness; +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.AR.Awareness +{ + public class ContextAwarenessArgs: + IArdkEventArgs + where TBuffer: class, IAwarenessBuffer, IDisposable + { + /// The context awareness processor. + public readonly AwarenessBufferProcessor Sender; + + public ContextAwarenessArgs(AwarenessBufferProcessor sender) + { + Sender = sender; + } + } + + public class ContextAwarenessStreamUpdatedArgs: + ContextAwarenessArgs + where TBuffer: class, IAwarenessBuffer, IDisposable + { + /// Whether the contents of the buffer has been updated. + public readonly bool IsKeyFrame; + + public ContextAwarenessStreamUpdatedArgs + ( + AwarenessBufferProcessor sender, + bool isKeyFrame + ) + : base(sender) + { + IsKeyFrame = isKeyFrame; + } + } +} diff --git a/Assets/ARDK/AR/ContextAwarenessArgs.cs.meta b/Assets/ARDK/AR/ContextAwarenessArgs.cs.meta new file mode 100644 index 0000000..9fce9dd --- /dev/null +++ b/Assets/ARDK/AR/ContextAwarenessArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3897febd288646e994d56dba900c8bac +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Frame.meta b/Assets/ARDK/AR/Frame.meta new file mode 100644 index 0000000..8c64e1b --- /dev/null +++ b/Assets/ARDK/AR/Frame.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0819a6419cc6a41f7ac7ba3d816db7c0 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Frame/_ARFrameFactory.cs b/Assets/ARDK/AR/Frame/_ARFrameFactory.cs new file mode 100644 index 0000000..512b2b6 --- /dev/null +++ b/Assets/ARDK/AR/Frame/_ARFrameFactory.cs @@ -0,0 +1,100 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.Linq; + +using Niantic.ARDK.AR.Anchors; +using Niantic.ARDK.AR.Awareness; +using Niantic.ARDK.AR.Awareness.Depth; +using Niantic.ARDK.AR.Awareness.Semantics; +using Niantic.ARDK.AR.Camera; +using Niantic.ARDK.AR.Image; +using Niantic.ARDK.AR.LightEstimate; +using Niantic.ARDK.AR.PointCloud; +using Niantic.ARDK.AR.SLAM; +using Niantic.ARDK.Utilities.Collections; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Frame +{ + internal static class _ARFrameFactory + { + internal static _SerializableARFrame _AsSerializable + ( + this IARFrame source, + bool includeImageBuffers = true, + bool includeAwarenessBuffers = true, + int compressionLevel = 70, + bool includeFeaturePoints = false + ) + { + if (source == null) + return null; + + if (source is _SerializableARFrame possibleResult) + return possibleResult; + + var serializedFrame = NewSerializableFrameWithoutBuffers(source); + + if (includeImageBuffers) + { + var imageBuffer = source.CapturedImageBuffer; + if (imageBuffer != null) + serializedFrame.CapturedImageBuffer = imageBuffer._AsSerializable(compressionLevel); + } + + if (includeAwarenessBuffers) + { + IDepthBuffer depthBuffer = source.Depth; + if (depthBuffer != null) + serializedFrame.DepthBuffer = depthBuffer._AsSerializable(); + + ISemanticBuffer semanticBuffer = source.Semantics; + if (semanticBuffer != null) + serializedFrame.SemanticBuffer = semanticBuffer._AsSerializable(); + } + + if (includeFeaturePoints) + serializedFrame.RawFeaturePoints = source.RawFeaturePoints._AsSerializable(); + + return serializedFrame; + } + + private static _SerializableARFrame NewSerializableFrameWithoutBuffers(IARFrame source) + { + var serializedAnchors = + ( + from anchor in source.Anchors + select anchor._AsSerializable() + ).ToArray(); + + var estimatedDisplayTransform = + source.CalculateDisplayTransform + ( + Screen.orientation, + Screen.width, + Screen.height + ); + + var serializableMaps = + ( + from map in source.Maps + select map._AsSerializable() + ).ToArray(); + + return + new _SerializableARFrame + ( + capturedImageBuffer: null, + depthBuffer: null, + semanticBuffer: null, + source.Camera._AsSerializable(), + source.LightEstimate._AsSerializable(), + serializedAnchors.AsNonNullReadOnly(), + serializableMaps, + source.WorldScale, + estimatedDisplayTransform + ); + } + } +} diff --git a/Assets/ARDK/AR/Frame/_ARFrameFactory.cs.meta b/Assets/ARDK/AR/Frame/_ARFrameFactory.cs.meta new file mode 100644 index 0000000..a8194a2 --- /dev/null +++ b/Assets/ARDK/AR/Frame/_ARFrameFactory.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c2d2152e163145288ae95aad6813fd16 +timeCreated: 1595009952 \ No newline at end of file diff --git a/Assets/ARDK/AR/Frame/_IARFrame.cs b/Assets/ARDK/AR/Frame/_IARFrame.cs new file mode 100644 index 0000000..7f1fad1 --- /dev/null +++ b/Assets/ARDK/AR/Frame/_IARFrame.cs @@ -0,0 +1,10 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using Niantic.ARDK.AR.Awareness.Depth; + +namespace Niantic.ARDK.AR.Frame +{ + internal interface _IARFrame: IARFrame + { + new IDepthPointCloud DepthPointCloud { get; set; } + } +} diff --git a/Assets/ARDK/AR/Frame/_IARFrame.cs.meta b/Assets/ARDK/AR/Frame/_IARFrame.cs.meta new file mode 100644 index 0000000..4df7d25 --- /dev/null +++ b/Assets/ARDK/AR/Frame/_IARFrame.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 7f584781b8ea47caa501d441e7d428e8 +timeCreated: 1646350388 \ No newline at end of file diff --git a/Assets/ARDK/AR/Frame/_NativeARFrame.cs b/Assets/ARDK/AR/Frame/_NativeARFrame.cs new file mode 100644 index 0000000..108cb7a --- /dev/null +++ b/Assets/ARDK/AR/Frame/_NativeARFrame.cs @@ -0,0 +1,716 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.Runtime.InteropServices; + +using Niantic.ARDK.AR.Anchors; +using Niantic.ARDK.AR.Awareness.Depth; +using Niantic.ARDK.AR.Awareness.Semantics; +using Niantic.ARDK.AR.Camera; +using Niantic.ARDK.AR.HitTest; +using Niantic.ARDK.AR.Image; +using Niantic.ARDK.AR.LightEstimate; +using Niantic.ARDK.AR.PointCloud; +using Niantic.ARDK.AR.SLAM; +using Niantic.ARDK.Internals; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Collections; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Frame +{ + internal sealed class _NativeARFrame: + _IARFrame + { + // Used to inform the GC about how many unmanaged memory our type holds. + // image + camera + anchors + raw feature points + maps + private const long _MemoryPressure = + (1L * 1080L * 1920L) + + (2L * 1080L * (1920L / 2L)) + + (1L * 8L) + + (1L * 8L) + + (1L * 8L); + + static _NativeARFrame() + { + Platform.Init(); + } + + internal static void _ReleaseImmediate(IntPtr framePtr) + { + switch (NativeAccess.Mode) + { + case NativeAccess.ModeType.Native: + _NARFrame_ReleaseImageAndTextures(framePtr); + _NARFrame_Release(framePtr); + break; + +#pragma warning disable 0162 + case NativeAccess.ModeType.Testing: + _TestingShim.ReleasedHandles.Add(framePtr); + break; +#pragma warning restore 0162 + } + } + private readonly _ThreadCheckedObject _threadChecker = new _ThreadCheckedObject(); +#if DEBUG + private readonly StackTrace _creationStack = new StackTrace(); +#endif + + internal _NativeARFrame(IntPtr nativeHandle, float worldScale) + { + if (nativeHandle == IntPtr.Zero) + throw new ArgumentException("nativeHandle can't be Zero.", nameof(nativeHandle)); + + _NativeHandle = nativeHandle; + GC.AddMemoryPressure(_MemoryPressure); + + WorldScale = worldScale; + } + + ~_NativeARFrame() + { + ARLog._Error + ( + "_NativeARFrame destructor invoked. This shouldn't happen.\n"+ + "If you are using a DisposalPolicy different from Dispose, you should manually dispose " + + "of the frames by calling Dispose() on them." +#if DEBUG + + "\nCreation Stack:\n" + _creationStack +#endif + ); + + _ReleaseImmediate(_NativeHandle); + GC.RemoveMemoryPressure(_MemoryPressure); + } + + public void Dispose() + { + _threadChecker._CheckThread(); + + GC.SuppressFinalize(this); + + ReleaseImageAndTextures(); + + var nativeHandle = _NativeHandle; + if (nativeHandle != IntPtr.Zero) + { + _NativeHandle = IntPtr.Zero; + + _ReleaseImmediate(nativeHandle); + GC.RemoveMemoryPressure(_MemoryPressure); + } + } + + internal IntPtr _NativeHandle { get; private set; } + + public ARFrameDisposalPolicy? DisposalPolicy { get; set; } + + public IDepthPointCloud DepthPointCloud { get; set; } + + public float WorldScale { get; } + + private IntPtr[] _capturedImageTextures; + public IntPtr[] CapturedImageTextures + { + get + { + _threadChecker._CheckThread(); + + #pragma warning disable 0162 + if (NativeAccess.Mode != NativeAccess.ModeType.Native) + return EmptyArray.Instance; + #pragma warning restore 0162 + if (_capturedImageTextures != null) + return _capturedImageTextures; + + var capturedImageTextures = EmptyArray.Instance; + while (true) + { + // When _NARFrame_GetGPUTextures receives a buffer smaller than the number of items, it + // returns a negative value telling the amount of items the buffer needs to support. + var obtained = + _NARFrame_GetGPUTextures + ( + _NativeHandle, + capturedImageTextures.Length, + capturedImageTextures + ); + + if (obtained == capturedImageTextures.Length) + { + _capturedImageTextures = capturedImageTextures; + return capturedImageTextures; + } + + capturedImageTextures = new IntPtr[Math.Abs(obtained)]; + } + } + } + + private _NativeImageBuffer _capturedImageBuffer; + private bool _capturedImageBufferRead; + + public _NativeImageBuffer CapturedImageBuffer + { + get + { + _threadChecker._CheckThread(); + + if (_capturedImageBufferRead) + return _capturedImageBuffer; + + _capturedImageBufferRead = true; + + IntPtr imageBufferHandle = IntPtr.Zero; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + imageBufferHandle = _NARFrame_GetCPUImage(_NativeHandle); + + if (imageBufferHandle == IntPtr.Zero) + return null; + + _capturedImageBuffer = new _NativeImageBuffer(imageBufferHandle); + return _capturedImageBuffer; + } + } + + private _NativeDepthBuffer _depthBuffer; + private _NativeSemanticBuffer _semanticBuffer; + private bool _depthBufferRead; + private bool _semanticBufferRead; + + public _NativeDepthBuffer Depth + { + get + { + _threadChecker._CheckThread(); + + if (_depthBufferRead) + return _depthBuffer; + + _depthBufferRead = true; + + IntPtr handle = IntPtr.Zero; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + handle = _NARFrame_GetDepthBuffer(_NativeHandle); + + if (handle == IntPtr.Zero) + return null; + + _depthBuffer = new _NativeDepthBuffer(handle, WorldScale, Camera.Intrinsics); + + return _depthBuffer; + } + } + + public _NativeSemanticBuffer Semantics + { + get + { + _threadChecker._CheckThread(); + + if (_semanticBufferRead) + return _semanticBuffer; + + _semanticBufferRead = true; + + IntPtr handle = IntPtr.Zero; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + handle = _NARFrame_GetSemanticBuffer(_NativeHandle); + + if (handle == IntPtr.Zero) + return null; + + _semanticBuffer = new _NativeSemanticBuffer(handle, WorldScale, Camera.Intrinsics); + + return _semanticBuffer; + } + } + + private _NativeARCamera _camera; + + public _NativeARCamera Camera + { + get + { + _threadChecker._CheckThread(); + + var result = _camera; + + if (result == null) + { + IntPtr cameraHandle = IntPtr.Zero; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + cameraHandle = _NARFrame_GetCamera(_NativeHandle); + + // Using a constructor here instead of caching + reusing objects in _NativeARCamera._FromNativeHandle + // We are disposing the camera every frame to prevent a crash on exit. Reintroduce caching + // in a way that supports disposing. + result = new _NativeARCamera(cameraHandle, WorldScale); + _camera = result; + } + + return result; + } + } + + private _NativeARLightEstimate _lightEstimate; + private bool _lightEstimateRead; + + public _NativeARLightEstimate LightEstimate + { + get + { + _threadChecker._CheckThread(); + + if (_lightEstimateRead) + return _lightEstimate; + + _lightEstimateRead = true; + + var lightEstimateHandle = IntPtr.Zero; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + lightEstimateHandle = _NARFrame_GetLightEstimate(_NativeHandle); + + if (lightEstimateHandle == IntPtr.Zero) + return null; + + var result = new _NativeARLightEstimate(lightEstimateHandle); + _lightEstimate = result; + return result; + } + } + + private ReadOnlyCollection _anchors; + + public ReadOnlyCollection Anchors + { + get + { + _threadChecker._CheckThread(); + + var result = _anchors; + + if (result == null) + { + result = _GetAnchorArray().AsNonNullReadOnly(); + _anchors = result; + } + + return result; + } + } + + private _NativeARAnchor[] _anchorArray; + + private _NativeARAnchor[] _GetAnchorArray() + { + if (_anchorArray != null) + return _anchorArray; + + var rawAnchors = EmptyArray.Instance; + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + while (true) + { + var obtained = _NARFrame_GetAnchors(_NativeHandle, rawAnchors.Length, rawAnchors); + if (obtained == rawAnchors.Length) + break; + + rawAnchors = new IntPtr[Math.Abs(obtained)]; + } + } + + var anchorCount = rawAnchors.Length; + var anchors = EmptyArray<_NativeARAnchor>.Instance; + + if (anchorCount > 0) + { + // Create the native types + anchors = new _NativeARAnchor[anchorCount]; + + for (var i = 0; i < anchorCount; i++) + { + var rawAnchor = rawAnchors[i]; + anchors[i] = _ARAnchorFactory._FromNativeHandle(rawAnchor); + } + } + + _anchorArray = anchors; + return anchors; + } + + private ReadOnlyCollection _maps; + + public ReadOnlyCollection Maps + { + get + { + _threadChecker._CheckThread(); + + var result = _maps; + + if (result == null) + { + result = _GetMapArray().AsNonNullReadOnly(); + _maps = result; + } + + return result; + } + } + + private _NativeARMap[] _mapArray; + + private _NativeARMap[] _GetMapArray() + { + if (_mapArray != null) + return _mapArray; + + var rawMaps = EmptyArray.Instance; + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + while (true) + { + var obtained = _NARFrame_GetMaps(_NativeHandle, rawMaps.Length, rawMaps); + if (obtained == rawMaps.Length) + break; + + rawMaps = new IntPtr[Math.Abs(obtained)]; + } + } + + var mapCount = rawMaps.Length; + var maps = EmptyArray<_NativeARMap>.Instance; + + if (mapCount > 0) + { + // Create the native types + maps = new _NativeARMap[mapCount]; + + for (var i = 0; i < mapCount; i++) + { + var rawMap = rawMaps[i]; + maps[i] = _NativeARMap._FromNativeHandle(rawMap, WorldScale); + } + } + + _mapArray = maps; + return maps; + } + + private _NativeARPointCloud _rawFeaturePoints; + private bool _rawFeaturePointsRead; + + public _NativeARPointCloud RawFeaturePoints + { + get + { + _threadChecker._CheckThread(); + + if (_rawFeaturePointsRead) + return _rawFeaturePoints; + + _rawFeaturePointsRead = true; + + var rawFeaturePointsHandle = IntPtr.Zero; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + rawFeaturePointsHandle = _NARFrame_GetFeaturePoints(_NativeHandle); + + if (rawFeaturePointsHandle == IntPtr.Zero) + return null; + + var result = new _NativeARPointCloud(rawFeaturePointsHandle, WorldScale); + _rawFeaturePoints = result; + return result; + } + } + + + public ReadOnlyCollection HitTest + ( + int viewportWidth, + int viewportHeight, + Vector2 screenPoint, + ARHitTestResultType types + ) + { + _threadChecker._CheckThread(); + + var viewportPoint = + new Vector2 + ( + screenPoint.x / viewportWidth, + screenPoint.y / viewportHeight + ); + + // Get the count and the handle to the hit test results + var hitTestResultsHandle = IntPtr.Zero; + uint hitCount = 0; + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + hitCount = _NARFrame_HitTestAgainstTypes + ( + _NativeHandle, + (UInt64)Screen.orientation, + viewportWidth, + viewportHeight, + viewportPoint.x, + viewportPoint.y, + (UInt64)types, + ref hitTestResultsHandle + ); + } + + // Return zero if none + if (hitTestResultsHandle == IntPtr.Zero) + return EmptyReadOnlyCollection.Instance; + + if (hitCount == 0) + { + _Memory.Free(hitTestResultsHandle); + return EmptyReadOnlyCollection.Instance; + } + + // Copy directly into the IntPtr array, then free the handle + var rawHitTestResults = new IntPtr[hitCount]; + Marshal.Copy(hitTestResultsHandle, rawHitTestResults, 0, (int)hitCount); + _Memory.Free(hitTestResultsHandle); + + // Copy and create the C# types + var hitTestResults = new IARHitTestResult[hitCount]; + + for (var i = 0; i < (int)hitCount; i++) + hitTestResults[i] = new _NativeARHitTestResult(rawHitTestResults[i], WorldScale); + + return hitTestResults.AsNonNullReadOnly(); + } + + public Matrix4x4 CalculateDisplayTransform + ( + ScreenOrientation orientation, + int viewportWidth, + int viewportHeight + ) + { + _threadChecker._CheckThread(); + + var nativeDisplayTransform = new float[6]; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + _NARFrame_CalculateDisplayTransform + ( + _NativeHandle, + (UInt64)orientation, + viewportWidth, + viewportHeight, + nativeDisplayTransform + ); + } + #pragma warning disable 0162 + else + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + + return _Convert.DisplayAffineToMatrix4x4(nativeDisplayTransform); + } + + public void ReleaseImageAndTextures() + { + _threadChecker._CheckThread(); + + if (_capturedImageBufferRead) + { + var capturedBuffer = _capturedImageBuffer; + if (capturedBuffer != null) + { + _capturedImageBuffer = null; + capturedBuffer.Dispose(); + } + + _capturedImageBufferRead = false; + } + + if (_depthBufferRead) + { + var depthBuffer = _depthBuffer; + if (depthBuffer != null) + { + _depthBuffer = null; + depthBuffer.Dispose(); + } + + _depthBufferRead = false; + } + if (_semanticBufferRead) + { + var semanticBuffer = _semanticBuffer; + if (semanticBuffer != null) + { + _semanticBuffer = null; + semanticBuffer.Dispose(); + } + + _semanticBufferRead = false; + } + + if (_camera != null) { + _camera.Dispose(); + _camera = null; + } + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARFrame_ReleaseImageAndTextures(_NativeHandle); +#pragma warning disable 0162 + else + _TestingShim.FramesWithReleasedTextures.Add(this); +#pragma warning restore 0162 + } + + IImageBuffer IARFrame.CapturedImageBuffer + { + get => CapturedImageBuffer; + } + + IDepthBuffer IARFrame.Depth + { + get => Depth; + } + + ISemanticBuffer IARFrame.Semantics + { + get => Semantics; + } + + + IARCamera IARFrame.Camera + { + get => Camera; + } + + IARLightEstimate IARFrame.LightEstimate + { + get => LightEstimate; + } + + IARPointCloud IARFrame.RawFeaturePoints + { + get => RawFeaturePoints; + } + +#region TestingShim + internal static class _TestingShim + { + // This stores all native handles that would normally be freed by passing them to + // _NARFrame_Release. + public static List ReleasedHandles = new List(); + + public static List<_NativeARFrame> FramesWithReleasedTextures = new List<_NativeARFrame>(); + + // There is no guarantee that static objects will be cleaned up between tests, or multiple + // runs of tests. Explicitly clean up cached data that may affect other tests. + public static void Reset() + { + ReleasedHandles.Clear(); + FramesWithReleasedTextures.Clear(); + } + } +#endregion + + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARFrame_Release(IntPtr nativeHandle); + + // Returns a negative value if the provided buffer size is wrong. Such a negative value, if converted to positive, + // represents the number of items the gpuTextures array should have. When a negative result is returned, nothing + // was modified. + [DllImport(_ARDKLibrary.libraryName)] + private static extern int _NARFrame_GetGPUTextures + ( + IntPtr nativeHandle, + int gpuTexturesLength, + IntPtr[] gpuTextures + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NARFrame_GetCPUImage(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NARFrame_GetDepthBuffer(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NARFrame_GetSemanticBuffer(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARFrame_ReleaseImageAndTextures(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern double _NARFrame_GetTimestamp(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NARFrame_GetCamera(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NARFrame_GetLightEstimate(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARFrame_CalculateDisplayTransform + ( + IntPtr nativeHandle, + UInt64 interfaceOrientation, + Int32 viewportWidth, + Int32 viewportHeight, + float[] outTransform + ); + + // Returns a negative value if the provided buffer size is wrong. Such a negative value, if converted to positive, + // represents the number of items the outAnchors array should have. When a negative result is returned, nothing + // was modified. + [DllImport(_ARDKLibrary.libraryName)] + private static extern int _NARFrame_GetAnchors + ( + IntPtr nativeHandle, + int outAnchorsLength, + IntPtr[] outAnchors + ); + + // Returns a negative value if the provided buffer size is wrong. Such a negative value, if converted to positive, + // represents the number of items the outMaps array should have. When a negative result is returned, nothing + // was modified. + [DllImport(_ARDKLibrary.libraryName)] + private static extern int _NARFrame_GetMaps + ( + IntPtr nativeHandle, + int outMapsLength, + IntPtr[] outMaps + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern UInt32 _NARFrame_HitTestAgainstTypes + ( + IntPtr nativeHandle, + UInt64 interfaceOrientation, + Int32 viewportWidth, + Int32 viewportHeight, + float pointX, + float pointY, + UInt64 types, + ref IntPtr hitTestResultsHandle + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NARFrame_GetFeaturePoints(IntPtr nativeHandle); + } +} diff --git a/Assets/ARDK/AR/Frame/_NativeARFrame.cs.meta b/Assets/ARDK/AR/Frame/_NativeARFrame.cs.meta new file mode 100644 index 0000000..07b78cb --- /dev/null +++ b/Assets/ARDK/AR/Frame/_NativeARFrame.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: aff55f88b5754f0a9ec36086f9a1f641 +timeCreated: 1594924116 \ No newline at end of file diff --git a/Assets/ARDK/AR/Frame/_SerializableARFrame.cs b/Assets/ARDK/AR/Frame/_SerializableARFrame.cs new file mode 100644 index 0000000..af3fb38 --- /dev/null +++ b/Assets/ARDK/AR/Frame/_SerializableARFrame.cs @@ -0,0 +1,214 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Numerics; + +using Niantic.ARDK.AR.Anchors; +using Niantic.ARDK.AR.Camera; +using Niantic.ARDK.AR.Awareness.Depth; +using Niantic.ARDK.AR.Awareness.Semantics; +using Niantic.ARDK.AR.HitTest; +using Niantic.ARDK.AR.Image; +using Niantic.ARDK.AR.LightEstimate; +using Niantic.ARDK.AR.PointCloud; +using Niantic.ARDK.AR.SLAM; +using Niantic.ARDK.VirtualStudio.AR; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Collections; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; + +using Matrix4x4 = UnityEngine.Matrix4x4; +using Quaternion = UnityEngine.Quaternion; +using Vector2 = UnityEngine.Vector2; +using Vector3 = UnityEngine.Vector3; + +namespace Niantic.ARDK.AR.Frame +{ + [Serializable] + internal sealed class _SerializableARFrame: + _SerializableARFrameBase + { + internal _SerializableARFrame() + { + } + + internal _SerializableARFrame + ( + _SerializableImageBuffer capturedImageBuffer, + _SerializableDepthBuffer depthBuffer, + _SerializableSemanticBuffer semanticBuffer, + _SerializableARCamera camera, + _SerializableARLightEstimate lightEstimate, + ReadOnlyCollection anchors, // Even native ARAnchors are directly serializable. + _SerializableARMap[] maps, + float worldScale, + Matrix4x4 estimatedDisplayTransform, + _SerializableARPointCloud rawFeaturePoints = null + ): + base + ( + capturedImageBuffer, + depthBuffer, + semanticBuffer, + camera, + lightEstimate, + anchors, + maps, + worldScale, + estimatedDisplayTransform, + rawFeaturePoints + ) + { + } + + public override ReadOnlyCollection HitTest + ( + int viewportWidth, + int viewportHeight, + Vector2 screenPoint, + ARHitTestResultType types + ) + { + if ((types & ~ARHitTestResultType.ExistingPlaneUsingExtent) != 0) + { + const string message = + "Only hit tests for ARHitTestResultType.ExistingPlaneUsingExtent " + + "is supported in Mock or Remote ARSessions."; + + ARLog._Debug(message); + } + + var anchors = Anchors; + if (anchors == null) + return EmptyReadOnlyCollection.Instance; + + // Simulated hit test + var hitTestResults = new List(); + + var planeAnchors = + from anchor in anchors + where anchor.AnchorType == AnchorType.Plane + select (IARPlaneAnchor) anchor; + + var camera = UnityEngine.Camera.main; + if (camera == null) + { + string message = + "ARFrame.HitTest requires a camera tagged " + + "`MainCamera` in the scene, but one was not found."; + + ARLog._Error(message); + return hitTestResults.AsReadOnly(); + } + + var ray = camera.ScreenPointToRay(screenPoint); + var v = new Vector3[4]; + + foreach (var plane in planeAnchors) + { + var worldCenter = plane.Transform.ToPosition() + plane.Center; + var orientation = plane.Transform.ToRotation(); + GetWorldVertices(worldCenter, plane.Extent, orientation, ref v); + + // Calculate intersection point of ray and plane. + // Unity uses the left hand rule. + var normal = Vector3.Cross(v[3] - v[0], v[1] - v[0]); + if (!PlaneRaycast(ray, worldCenter, normal, out Vector3 hitPosition, out float distance)) + continue; + + // Inside-outside test. + // There's a few vector subtractions duplicated by pulling these calculations into methods, + // but there would/should not be 100s of planes in a scene so cleaner code is prioritized. + if + ( + !IsInsideTriangle(normal, hitPosition, v[0], v[1], v[3]) && + !IsInsideTriangle(normal, hitPosition, v[1], v[2], v[3]) + ) + continue; + + Debug.DrawRay(worldCenter, normal * 2f, Color.blue, 10f); + Debug.DrawLine(ray.origin, hitPosition, Color.green, 10f); + + var hitTestResult = + new _SerializableARHitTestResult + ( + ARHitTestResultType.ExistingPlaneUsingExtent, + plane._AsSerializablePlane(), + distance, + Matrix4x4.identity, + Matrix4x4.TRS(hitPosition, Quaternion.identity, Vector3.one), + 1.0f + ); + + hitTestResults.Add(hitTestResult); + } + + hitTestResults.Sort((x, y) => x.Distance.CompareTo(y.Distance)); + return hitTestResults.AsReadOnly(); + } + + private static void GetWorldVertices + ( + Vector3 worldCenter, + Vector3 extent, + Quaternion orientation, + ref Vector3[] vertices + ) + { + var halfWidth = extent.x / 2; + var halfHeight = extent.z / 2; + + vertices[0] = worldCenter + orientation * new Vector3(-halfWidth, 0, halfHeight); + vertices[1] = worldCenter + orientation * new Vector3(-halfWidth, 0, -halfHeight); + vertices[2] = worldCenter + orientation * new Vector3(halfWidth, 0, -halfHeight); + vertices[3] = worldCenter + orientation * new Vector3(halfWidth, 0, halfHeight); + } + + private static bool IsInsideTriangle + ( + Vector3 normal, + Vector3 point, + Vector3 v0, + Vector3 v1, + Vector3 v2 + ) + { + return + (Vector3.Dot(normal, Vector3.Cross(point - v0, v1 - v0)) >= 0) && + (Vector3.Dot(normal, Vector3.Cross(point - v1, v2 - v1)) >= 0) && + (Vector3.Dot(normal, Vector3.Cross(point - v2, v0 - v2)) >= 0); + } + + private static bool PlaneRaycast + ( + Ray ray, + Vector3 center, + Vector3 normal, + out Vector3 hit, + out float distance + ) + { + var denominator = Vector3.Dot(ray.direction, normal); + if (Mathf.Abs(denominator) > 0.0001f) + { + var diff = center - ray.origin; + float t = Vector3.Dot(diff, normal) / denominator; + if (t > 0.0001f) + { + hit = ray.origin + (t * ray.direction); + distance = t; + return true; + } + } + + hit = Vector3.positiveInfinity; + distance = float.PositiveInfinity; + return false; + } + } +} diff --git a/Assets/ARDK/AR/Frame/_SerializableARFrame.cs.meta b/Assets/ARDK/AR/Frame/_SerializableARFrame.cs.meta new file mode 100644 index 0000000..2629879 --- /dev/null +++ b/Assets/ARDK/AR/Frame/_SerializableARFrame.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 20e48012c2a14b4d8f0c6206ac1ce3ca +timeCreated: 1594920633 \ No newline at end of file diff --git a/Assets/ARDK/AR/Frame/_SerializableARFrameBase.cs b/Assets/ARDK/AR/Frame/_SerializableARFrameBase.cs new file mode 100644 index 0000000..1f1abe5 --- /dev/null +++ b/Assets/ARDK/AR/Frame/_SerializableARFrameBase.cs @@ -0,0 +1,151 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.ObjectModel; + +using Niantic.ARDK.AR.Anchors; +using Niantic.ARDK.AR.Awareness.Depth; +using Niantic.ARDK.AR.Awareness.Semantics; +using Niantic.ARDK.AR.Camera; +using Niantic.ARDK.AR.HitTest; +using Niantic.ARDK.AR.Image; +using Niantic.ARDK.AR.LightEstimate; +using Niantic.ARDK.AR.PointCloud; +using Niantic.ARDK.AR.SLAM; +using Niantic.ARDK.Utilities.Collections; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Frame +{ + [Serializable] + internal abstract class _SerializableARFrameBase: + _IARFrame + { + protected _SerializableARFrameBase() + { + } + + protected _SerializableARFrameBase + ( + _SerializableImageBuffer capturedImageBuffer, + _SerializableDepthBuffer depthBuffer, + _SerializableSemanticBuffer buffer, + _SerializableARCamera camera, + _SerializableARLightEstimate lightEstimate, + ReadOnlyCollection anchors, // Even native ARAnchors are directly serializable. + _SerializableARMap[] maps, + float worldScale, + Matrix4x4 estimatedDisplayTransform, + _SerializableARPointCloud featurePoints + ) + { + CapturedImageBuffer = capturedImageBuffer; + DepthBuffer = depthBuffer; + SemanticBuffer = buffer; + Camera = camera; + LightEstimate = lightEstimate; + WorldScale = worldScale; + RawFeaturePoints = featurePoints; + Anchors = anchors; + Maps = maps.AsNonNullReadOnly(); + + _estimatedDisplayTransform = estimatedDisplayTransform; + } + + public void Dispose() + { + GC.SuppressFinalize(this); + ReleaseImageAndTextures(); + } + + public ARFrameDisposalPolicy? DisposalPolicy { get; set; } + public _SerializableImageBuffer CapturedImageBuffer { get; set; } + public _SerializableDepthBuffer DepthBuffer { get; set; } + public _SerializableSemanticBuffer SemanticBuffer { get; set; } + public _SerializableARCamera Camera { get; set; } + public _SerializableARLightEstimate LightEstimate { get; set; } + public ReadOnlyCollection Anchors { get; set; } + public IDepthPointCloud DepthPointCloud { get; set; } + public ReadOnlyCollection Maps { get; set; } + public float WorldScale { get; set; } + public _SerializableARPointCloud RawFeaturePoints { get; set; } + + public IntPtr[] CapturedImageTextures + { + get => EmptyArray.Instance; + } + + public abstract ReadOnlyCollection HitTest + ( + int viewportWidth, + int viewportHeight, + Vector2 screenPoint, + ARHitTestResultType types + ); + + private readonly Matrix4x4 _estimatedDisplayTransform; + public Matrix4x4 CalculateDisplayTransform + ( + ScreenOrientation orientation, + int viewportWidth, + int viewportHeight + ) + { + return _estimatedDisplayTransform; + } + + public void ReleaseImageAndTextures() + { + var capturedBuffer = CapturedImageBuffer; + if (capturedBuffer != null) + { + CapturedImageBuffer = null; + capturedBuffer.Dispose(); + } + + var depthBuffer = DepthBuffer; + if (depthBuffer != null) + { + DepthBuffer = null; + depthBuffer.Dispose(); + } + + var semanticBuffer = SemanticBuffer; + if (semanticBuffer != null) + { + SemanticBuffer = null; + semanticBuffer.Dispose(); + } + } + + IARPointCloud IARFrame.RawFeaturePoints + { + get => RawFeaturePoints; + } + + IImageBuffer IARFrame.CapturedImageBuffer + { + get => CapturedImageBuffer; + } + IDepthBuffer IARFrame.Depth + { + get => DepthBuffer; + } + + ISemanticBuffer IARFrame.Semantics + { + get => SemanticBuffer; + } + + IARCamera IARFrame.Camera + { + get => Camera; + } + + IARLightEstimate IARFrame.LightEstimate + { + get => LightEstimate; + } + } +} diff --git a/Assets/ARDK/AR/Frame/_SerializableARFrameBase.cs.meta b/Assets/ARDK/AR/Frame/_SerializableARFrameBase.cs.meta new file mode 100644 index 0000000..46b15bd --- /dev/null +++ b/Assets/ARDK/AR/Frame/_SerializableARFrameBase.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: cb6fce280700454d8875b73f58c3665d +timeCreated: 1594915719 \ No newline at end of file diff --git a/Assets/ARDK/AR/HitTest.meta b/Assets/ARDK/AR/HitTest.meta new file mode 100644 index 0000000..a564732 --- /dev/null +++ b/Assets/ARDK/AR/HitTest.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 07e5cb115bb3640fd8b007e302585ddd +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/HitTest/ARHitTestResultType.cs b/Assets/ARDK/AR/HitTest/ARHitTestResultType.cs new file mode 100644 index 0000000..e1834e8 --- /dev/null +++ b/Assets/ARDK/AR/HitTest/ARHitTestResultType.cs @@ -0,0 +1,48 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +namespace Niantic.ARDK.AR.HitTest +{ + /// Types of objects to hit-test against and also the type of objects found by the hit-test. + [Flags] + public enum ARHitTestResultType + { + /// Unrecognized hit-test result type. + None = 0, + + /// A point detected by an AR session representing a distinguishable + /// feature, but without a corresponding anchor. + /// @note This is not supported in VirtualStudio's Mock or Remote mode. + FeaturePoint = 1, + + /// A real-world planar surface detected by the search (without + /// a corresponding anchor), whose orientation is perpendicular to gravity. + /// @note This is an Android-only value. + EstimatedArbitraryPlane = 2, + + /// A real-world planar surface detected by the search (without + /// a corresponding anchor), whose orientation is perpendicular to gravity. + /// @note This is not supported in VirtualStudio's Mock or Remote mode. + EstimatedHorizontalPlane = 4, + + /// A real-world planar surface detected by the search (without + /// a corresponding anchor), whose orientation is parallel to gravity. + /// @note This is not supported in VirtualStudio's Mock or Remote mode. + EstimatedVerticalPlane = 8, + + /// A plane anchor already in the scene, without considering the plane's size. + /// @note This is not supported in VirtualStudio's Mock or Remote mode. + ExistingPlane = 16, + + /// A plane anchor already in the scene, respecting the plane's size. + ExistingPlaneUsingExtent = 32, + + /// A plane anchor already in the scene, respecting the plane's rough, physical geometry. + /// @note This is not supported in VirtualStudio's Mock or Remote mode. + ExistingPlaneUsingGeometry = 64, + + /// Any of the types above. + All = ~None, + } +} \ No newline at end of file diff --git a/Assets/ARDK/AR/HitTest/ARHitTestResultType.cs.meta b/Assets/ARDK/AR/HitTest/ARHitTestResultType.cs.meta new file mode 100644 index 0000000..561e874 --- /dev/null +++ b/Assets/ARDK/AR/HitTest/ARHitTestResultType.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 7231a5cc7780415e905929549649c5f0 +timeCreated: 1594776535 \ No newline at end of file diff --git a/Assets/ARDK/AR/HitTest/IARHitTestResult.cs b/Assets/ARDK/AR/HitTest/IARHitTestResult.cs new file mode 100644 index 0000000..4721af5 --- /dev/null +++ b/Assets/ARDK/AR/HitTest/IARHitTestResult.cs @@ -0,0 +1,35 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using Niantic.ARDK.AR.Anchors; +using UnityEngine; + +namespace Niantic.ARDK.AR.HitTest +{ + /// Information about a real-world surface found by examining a point + /// in the device camera view of an AR session. + /// @note Use the IARFrame.HitTest method to get an array of ARHitTestResults. + public interface IARHitTestResult: + IDisposable + { + /// The kind of detected feature this result represents. + ARHitTestResultType Type { get; } + + /// The anchor representing the detected surface, if any. + /// @note **May be null**. + IARAnchor Anchor { get; } + + /// The distance, in meters, from the camera to the hit test result. + float Distance { get; } + + /// The position and orientation of the hit test result relative to the nearest anchor or + /// feature point. + Matrix4x4 LocalTransform { get; } + + /// The position and orientation of the hit test result relative to the world coordinate system. + Matrix4x4 WorldTransform { get; } + + /// The scaling factor applied to this hitTestResult's data. + float WorldScale { get; } + } +} diff --git a/Assets/ARDK/AR/HitTest/IARHitTestResult.cs.meta b/Assets/ARDK/AR/HitTest/IARHitTestResult.cs.meta new file mode 100644 index 0000000..497bd1c --- /dev/null +++ b/Assets/ARDK/AR/HitTest/IARHitTestResult.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 4d03cd23d236494993c2b846ee9b2424 +timeCreated: 1594776664 \ No newline at end of file diff --git a/Assets/ARDK/AR/HitTest/_NativeARHitTestResult.cs b/Assets/ARDK/AR/HitTest/_NativeARHitTestResult.cs new file mode 100644 index 0000000..8ee0db7 --- /dev/null +++ b/Assets/ARDK/AR/HitTest/_NativeARHitTestResult.cs @@ -0,0 +1,189 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Runtime.InteropServices; + +using Niantic.ARDK.AR.Anchors; +using Niantic.ARDK.Internals; +using Niantic.ARDK.Utilities; + +using UnityEngine; + +namespace Niantic.ARDK.AR.HitTest +{ + internal sealed class _NativeARHitTestResult: + IARHitTestResult + { + // Used to inform the C# GC that there is managed memory held by this object + // type + anchor + distance + world transform + local transform + private const long _MemoryPressure = + (1L * 8L) + (1L * 8L) + (1L * 4L) + (16L * 4L) + (16L * 4L); + + static _NativeARHitTestResult() + { + Platform.Init(); + } + + private IntPtr _nativeHandle; + + internal _NativeARHitTestResult(IntPtr nativeHandle, float worldScale) + { + if (nativeHandle == IntPtr.Zero) + throw new ArgumentException("nativeHandle can't be Zero.", nameof(nativeHandle)); + + _nativeHandle = nativeHandle; + GC.AddMemoryPressure(_MemoryPressure); + WorldScale = worldScale; + } + + private static void _ReleaseImmediate(IntPtr nativeHandle) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARHitTestResult_Release(nativeHandle); + } + + ~_NativeARHitTestResult() + { + _ReleaseImmediate(_nativeHandle); + GC.RemoveMemoryPressure(_MemoryPressure); + } + + public void Dispose() + { + GC.SuppressFinalize(this); + + var nativeHandle = _nativeHandle; + if (nativeHandle != IntPtr.Zero) + { + _nativeHandle = IntPtr.Zero; + + _ReleaseImmediate(nativeHandle); + GC.RemoveMemoryPressure(_MemoryPressure); + } + } + + public float WorldScale { get; private set; } + + public ARHitTestResultType Type + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return (ARHitTestResultType) _NARHitTestResult_GetType(_nativeHandle); + + #pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + } + } + + public float Distance + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _NARHitTestResult_GetDistance(_nativeHandle) * WorldScale; + + #pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + } + } + + private _NativeARAnchor _anchor; + internal _NativeARAnchor Anchor + { + get + { + var result = _anchor; + + if (result == null) + { + var anchorHandle = IntPtr.Zero; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + anchorHandle = _NARHitTestResult_GetAnchor(_nativeHandle); + + if (anchorHandle == IntPtr.Zero) + return null; + + result = _ARAnchorFactory._FromNativeHandle(anchorHandle); + _anchor = result; + } + + return result; + } + } + + public Matrix4x4 LocalTransform + { + get + { + var nativeTransform = new float[16]; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARHitTestResult_GetLocalTransform(_nativeHandle, nativeTransform); + #pragma warning disable 0162 + else + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + + var transform = + NARConversions.FromNARToUnity(_Convert.InternalToMatrix4x4(nativeTransform)); + + return transform; + } + } + + public Matrix4x4 WorldTransform + { + get + { + var nativeTransform = new float[16]; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARHitTestResult_GetWorldTransform(_nativeHandle, nativeTransform); + #pragma warning disable 0162 + else + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + + var transform = NARConversions.FromNARToUnity(_Convert.InternalToMatrix4x4(nativeTransform)); + _Convert.ApplyScale(ref transform, WorldScale); + + return transform; + } + } + + IARAnchor IARHitTestResult.Anchor + { + get { return Anchor; } + } + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARHitTestResult_Release(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern UInt64 _NARHitTestResult_GetType(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NARHitTestResult_GetAnchor(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern float _NARHitTestResult_GetDistance(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARHitTestResult_GetWorldTransform + ( + IntPtr nativeHandle, + float[] outTransform + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARHitTestResult_GetLocalTransform + ( + IntPtr nativeHandle, + float[] outTransform + ); + } +} diff --git a/Assets/ARDK/AR/HitTest/_NativeARHitTestResult.cs.meta b/Assets/ARDK/AR/HitTest/_NativeARHitTestResult.cs.meta new file mode 100644 index 0000000..1600c92 --- /dev/null +++ b/Assets/ARDK/AR/HitTest/_NativeARHitTestResult.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 2e26b04b23634c2fa26d70a724fc297d +timeCreated: 1594777786 \ No newline at end of file diff --git a/Assets/ARDK/AR/HitTest/_SerializableARHitTestResult.cs b/Assets/ARDK/AR/HitTest/_SerializableARHitTestResult.cs new file mode 100644 index 0000000..9c07937 --- /dev/null +++ b/Assets/ARDK/AR/HitTest/_SerializableARHitTestResult.cs @@ -0,0 +1,49 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using Niantic.ARDK.AR.Anchors; +using UnityEngine; + +namespace Niantic.ARDK.AR.HitTest +{ + [Serializable] + internal sealed class _SerializableARHitTestResult: + IARHitTestResult + { + internal _SerializableARHitTestResult + ( + ARHitTestResultType type, + _SerializableARAnchor anchor, + float distance, + Matrix4x4 localTransform, + Matrix4x4 worldTransform, + float worldScale + ) + { + Type = type; + Anchor = anchor; + Distance = distance; + LocalTransform = localTransform; + WorldTransform = worldTransform; + WorldScale = worldScale; + } + + public ARHitTestResultType Type { get; private set; } + public float Distance { get; private set; } + public Matrix4x4 LocalTransform { get; private set; } + public Matrix4x4 WorldTransform { get; private set; } + public float WorldScale { get; private set; } + + internal _SerializableARAnchor Anchor { get; private set; } + + IARAnchor IARHitTestResult.Anchor + { + get { return Anchor; } + } + + void IDisposable.Dispose() + { + // Do nothing. This IARHitTestResult implementation is fully managed. + } + } +} diff --git a/Assets/ARDK/AR/HitTest/_SerializableARHitTestResult.cs.meta b/Assets/ARDK/AR/HitTest/_SerializableARHitTestResult.cs.meta new file mode 100644 index 0000000..35a8554 --- /dev/null +++ b/Assets/ARDK/AR/HitTest/_SerializableARHitTestResult.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: fe7c6fce4ecd45cbab7c07fe1ede5b6d +timeCreated: 1594776865 \ No newline at end of file diff --git a/Assets/ARDK/AR/HitTest/_SerializableARHitTestResultFactory.cs b/Assets/ARDK/AR/HitTest/_SerializableARHitTestResultFactory.cs new file mode 100644 index 0000000..33796b1 --- /dev/null +++ b/Assets/ARDK/AR/HitTest/_SerializableARHitTestResultFactory.cs @@ -0,0 +1,32 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.AR.Anchors; + +namespace Niantic.ARDK.AR.HitTest +{ + internal static class _SerializableARHitTestResultFactory + { + internal static _SerializableARHitTestResult _AsSerializable(this IARHitTestResult source) + { + if (source == null) + return null; + + var possibleResult = source as _SerializableARHitTestResult; + if (possibleResult != null) + return possibleResult; + + var result = + new _SerializableARHitTestResult + ( + source.Type, + source.Anchor._AsSerializable(), + source.Distance, + source.LocalTransform, + source.WorldTransform, + source.WorldScale + ); + + return result; + } + } +} diff --git a/Assets/ARDK/AR/HitTest/_SerializableARHitTestResultFactory.cs.meta b/Assets/ARDK/AR/HitTest/_SerializableARHitTestResultFactory.cs.meta new file mode 100644 index 0000000..f7f4ca4 --- /dev/null +++ b/Assets/ARDK/AR/HitTest/_SerializableARHitTestResultFactory.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 14814aaee42049d8a3c3f9fe2c945549 +timeCreated: 1594777723 \ No newline at end of file diff --git a/Assets/ARDK/AR/IARCamera.cs b/Assets/ARDK/AR/IARCamera.cs new file mode 100644 index 0000000..e2f7614 --- /dev/null +++ b/Assets/ARDK/AR/IARCamera.cs @@ -0,0 +1,125 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.AR.Camera; + +using UnityEngine; + +namespace Niantic.ARDK.AR +{ + /// + /// Interface for platform specific implementations of an ARCamera. Contains information about the + /// camera position and imaging characteristics for a captured video frame in an AR session. + /// + public interface IARCamera: + IDisposable + { + /// + /// The general quality of position tracking available when the camera captured a frame. + /// @remarks Use this property to keep your users informed as well as internally for peerState + /// and whether to process the enclosed data or not. + /// + TrackingState TrackingState { get; } + + /// + /// A possible diagnosis for limited position tracking quality as of when the camera + /// captured a frame. + /// @note This is an iOS-only value. + /// + TrackingStateReason TrackingStateReason { get; } + + /// + /// The width and height of the captured image, in pixels. + /// + Resolution ImageResolution { get; } + + /// + /// The resolution of the CPU captured image, in pixels. + /// + Resolution CPUImageResolution { get; } + + /// The focal length and principal point of this camera. + CameraIntrinsics Intrinsics { get; } + + /// The focal length and principal point of the camera used to generate the CPU image. + CameraIntrinsics CPUIntrinsics { get; } + + /// + /// The position and orientation of the camera in world coordinate space. + /// @remark This transform's coordinate space is always constant relative to the device + /// orientation. + /// + Matrix4x4 Transform { get; } + + /// + /// A transform matrix appropriate for rendering 3D content to match the image captured by + /// the camera. + /// @remark This property is equivalent to Camera.CalculateProjectionMatrix called with the + /// captured image's properties and default zNear and zFar of 0.001 and 1000.0, respectively. + /// + Matrix4x4 ProjectionMatrix { get; } + + /// + /// The scaling factor applied to this camera's Transform. + /// + float WorldScale { get; } + + /// + /// @brief Returns a transform matrix appropriate for rendering 3D content to match the + /// image captured by the camera, using the specified parameters. + /// @param orientation The current orientation of the interface. + /// @param viewportWidth Viewport width, in pixels. + /// @param viewportHeight Viewport height, in pixels. + /// @param nearClipPlane Near clip plane, in meters. + /// @param farClipPlane Far clip plane, in meters. + /// @note Returns a pre-calculated value in Remote Debugging. + /// + Matrix4x4 CalculateProjectionMatrix + ( + ScreenOrientation orientation, + int viewportWidth, + int viewportHeight, + float nearClipPlane, + float farClipPlane + ); + + /// + /// @brief Returns a transform matrix for converting from world space to camera space. + /// This matrix is in a left-handed coordinate system with the camera's forward direction + /// along the positive Z-axis. This is unlike Unity's + /// camera worldToCameraMatrix, + /// which uses a OpenGL-style, right-handed coordinate system with the camera's forward + /// direction along the negative Z-axis. + /// Convert from this coordinate system to the Unity/OpenGL system by negating the Z-axis, for example: + /// @code + /// var UnityViewMatrix = ARDKViewMatrix; + /// UnityViewMatrix.m20 *= -1.0f; + /// UnityViewMatrix.m21 *= -1.0f; + /// UnityViewMatrix.m22 *= -1.0f; + /// UnityViewMatrix.m23 *= -1.0f; + /// @endcode + /// @param orientation The current orientation of the interface. + /// @note Returns a pre-calculated value in Remote Debugging. + /// + Matrix4x4 GetViewMatrix(ScreenOrientation orientation); + + /// + /// @brief Returns the projection of a point from the 3D world space detected by the session into + /// the 2D space of a view rendering the scene. + /// @param point A point in 3D world space. + /// @param orientation The current orientation of the interface. + /// @param viewportWidth Viewport width, in pixels. + /// @param viewportHeight Viewport height, in pixels. + /// @note This is an iOS-only method. + /// @note Not currently supported in Remote Debugging. + /// + Vector2 ProjectPoint + ( + Vector3 point, + ScreenOrientation orientation, + int viewportWidth, + int viewportHeight + ); + } +} diff --git a/Assets/ARDK/AR/IARCamera.cs.meta b/Assets/ARDK/AR/IARCamera.cs.meta new file mode 100644 index 0000000..5f50889 --- /dev/null +++ b/Assets/ARDK/AR/IARCamera.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a339b8315b2374f119d7034826fa5dfe +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/IARFaceGeometry.cs b/Assets/ARDK/AR/IARFaceGeometry.cs new file mode 100644 index 0000000..6d6a5a0 --- /dev/null +++ b/Assets/ARDK/AR/IARFaceGeometry.cs @@ -0,0 +1,42 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.ObjectModel; + +using UnityEngine; + +namespace Niantic.ARDK.AR +{ + public interface IARFaceGeometry: + IDisposable + { + /// + /// An array of vertex positions (x, y, z) for each point in the face mesh. + /// @remark Each position is in a coordinate system defined by the owning face's anchor's + /// Transform matrix. E.g. "local" to that face. + /// + ReadOnlyCollection Vertices { get; } + + /// + /// A flat buffer of texture coordinate values (u, v) for each point in the face mesh. + /// @remark Each value at a particular index provides the u, v coordinates for the + /// corresponding vertex in the Vertices property. + /// + ReadOnlyCollection TextureCoordinates { get; } + + /// + /// A buffer of indices describing the triangle mesh formed by the face geometry's vertex data. + /// @remark Each value represents an index into the Vertices and TextureCoordinates arrays. + /// Each set of three represent the corners of a triangle in the mesh therefore, the number of + /// triangles is `TriangleIndices.Length / 3`. + /// + ReadOnlyCollection TriangleIndices { get; } + + /// + /// An array of normal positions (x, y, z) for each vertex in the face mesh. + /// @remark These normals are relative to the center pose of the face. + /// @note android-only value. Returns null on other platforms. + /// + ReadOnlyCollection Normals { get; } + } +} diff --git a/Assets/ARDK/AR/IARFaceGeometry.cs.meta b/Assets/ARDK/AR/IARFaceGeometry.cs.meta new file mode 100644 index 0000000..630f8c5 --- /dev/null +++ b/Assets/ARDK/AR/IARFaceGeometry.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e28fc9176a67a4af09b0c14abf30f5a2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/IARFrame.cs b/Assets/ARDK/AR/IARFrame.cs new file mode 100644 index 0000000..cccb3ab --- /dev/null +++ b/Assets/ARDK/AR/IARFrame.cs @@ -0,0 +1,139 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.ObjectModel; + +using Niantic.ARDK.AR.Anchors; +using Niantic.ARDK.AR.Awareness.Depth; +using Niantic.ARDK.AR.Awareness.Semantics; +using Niantic.ARDK.AR.HitTest; +using Niantic.ARDK.AR.SLAM; + +using UnityEngine; + +namespace Niantic.ARDK.AR +{ + /// + /// @brief A video image, with position-tracking information, captured as part of an AR session. + /// @remarks A running AR session continuously captures video frames from the device camera. + /// For each frame, the image is analyzed together with data from the device's motion + /// sensing hardware to estimate the device's real-world position. + /// + public interface IARFrame: + IDisposable + { + /// Gets or sets a value telling the retain policy of this frame. + /// If unset (that is, null) uses the value set at the session that created this frame. + ARFrameDisposalPolicy? DisposalPolicy { get; set; } + + /// + /// One or more native GPU textures. + /// @remark In iOS, this will be two textures, together they represent an image of format + /// [YCbCr](https://wiki.multimedia.cx/index.php/YCbCr_4:2:0). + /// @remark In Android, this will be a single texture of format BGRA. + /// @note Not supported in Remote Debugging. + /// + IntPtr[] CapturedImageTextures { get; } + + /// + /// The CPU-side image. + /// @remark In Android, initiates a copy from the native GPU texture into CPU-accessible memory. + /// @note **May be null**. + /// + IImageBuffer CapturedImageBuffer { get; } + + /// + /// The depth buffer. + /// @note **May be null**. + /// + IDepthBuffer Depth { get; } + + /// + /// The semantic buffer. + /// @note **May be null**. + /// + ISemanticBuffer Semantics { get; } + + /// + /// Information about the camera position, orientation, and imaging parameters used to + /// capture the frame. + /// + IARCamera Camera { get; } + + /// + /// An estimate of lighting conditions based on the camera image. + /// @note **May be null**, e.g. when not tracking. + /// + IARLightEstimate LightEstimate { get; } + + /// + /// The list of anchors representing positions tracked or objects at a point in time. + /// + ReadOnlyCollection Anchors { get; } + + /// + /// The list of maps from the Computer Vision system + /// + ReadOnlyCollection Maps { get; } + + /// + /// Raw 3D positions that are used in scene understanding. + /// @note **May be null**. + /// @note Not currently supported in Remote Debugging. + /// + IARPointCloud RawFeaturePoints { get; } + + /// + /// 3D positions generated based on the Depth Buffer. + /// @note **May be null** + /// + IDepthPointCloud DepthPointCloud { get; } + + /// + /// The scaling factor applied to this frame's data. + /// + float WorldScale { get; } + + /// Using a screen location, find points on real-world surfaces and objects in the camera view. + /// @param viewportWidth Width of the screen in pixels. + /// @param viewportHeight Height of the screen in pixels. + /// @param screenPoint A 2D point in screen (pixel) space. + /// @param types + /// The types of results to search for. Certain values are not supported on some platforms. + /// See ARHitTestResultType documentation for details. + /// @returns An array of hit test results in order of closest to furthest. May be zero-length. + ReadOnlyCollection HitTest + ( + int viewportWidth, + int viewportHeight, + Vector2 screenPoint, + ARHitTestResultType types + ); + + /// + /// Returns an affine transform for converting between normalized image coordinates + /// and a coordinate space appropriate for rendering the camera image onscreen. + /// @param orientation The current interface orientation. + /// @param viewportWidth Viewport width, in pixels. + /// @param viewportHeight Viewport height, in pixels. + /// @note Returns a pre-calculated value in Remote Debugging. + /// + Matrix4x4 CalculateDisplayTransform + ( + ScreenOrientation orientation, + int viewportWidth, + int viewportHeight + ); + + // TODO: Review if those should really be here: + /// + /// Releases the captured image and textures. + /// @remark Due to Unity's Garbage Collector (GC), we can't be sure when our memory will be + /// deallocated -- even if there are no more references to it. This method serves as a way to + /// release the largest memory suck in this class -- the images and textures. + /// @remark This might clear some dictionaries that cache accessed values, which is not thread + /// safe, so this should only be called from the Unity main thread + /// + void ReleaseImageAndTextures(); + } +} diff --git a/Assets/ARDK/AR/IARFrame.cs.meta b/Assets/ARDK/AR/IARFrame.cs.meta new file mode 100644 index 0000000..5b5986f --- /dev/null +++ b/Assets/ARDK/AR/IARFrame.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 68aad5ede59a483b9a1a64be07f26198 +timeCreated: 1594914714 \ No newline at end of file diff --git a/Assets/ARDK/AR/IARLightEstimate.cs b/Assets/ARDK/AR/IARLightEstimate.cs new file mode 100644 index 0000000..c43b55a --- /dev/null +++ b/Assets/ARDK/AR/IARLightEstimate.cs @@ -0,0 +1,33 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.ObjectModel; + +namespace Niantic.ARDK.AR +{ + public interface IARLightEstimate: + IDisposable + { + /// + /// The detected ambient light intensity. + /// @remark For iOS, this value is in lumens, 1000 representing "neutral" lighting. + /// @remark For Android, this value represents average pixel intensity of the range 0.0 - 1.0. + /// + float AmbientIntensity { get; } + + /// + /// The estimated color temperature, in degrees Kelvin, of ambient light throughout the scene. + /// @note This is an iOS-only value. + /// + float AmbientColorTemperature { get; } + + /// + /// A 4-element vector. Components 0-2 represent the scaling factor to be applied to the + /// r, g, and b values, respectively. The last component is the pixel intensity + /// (Identical to ARLightEstimate.AmbientIntensity). + /// @note This is an Android-only value. + /// @note The green channel [1] is always 1.0, to be used as the reference baseline. + /// + ReadOnlyCollection ColorCorrection { get; } + } +} diff --git a/Assets/ARDK/AR/IARLightEstimate.cs.meta b/Assets/ARDK/AR/IARLightEstimate.cs.meta new file mode 100644 index 0000000..141e11b --- /dev/null +++ b/Assets/ARDK/AR/IARLightEstimate.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f5b2660a735a48e8a67a0f301dd333c7 +timeCreated: 1592591435 \ No newline at end of file diff --git a/Assets/ARDK/AR/IARPlaneGeometry.cs b/Assets/ARDK/AR/IARPlaneGeometry.cs new file mode 100644 index 0000000..8c01e99 --- /dev/null +++ b/Assets/ARDK/AR/IARPlaneGeometry.cs @@ -0,0 +1,47 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.ObjectModel; + +using UnityEngine; + +namespace Niantic.ARDK.AR +{ + public interface IARPlaneGeometry: + IDisposable + { + /// + /// An array of vertex positions (x, y, z) for each point in the plane mesh. + /// @remark Each position is in a coordinate system defined by the owning plane anchor's + /// Transform matrix. E.g. "local" to that plane. + /// @note iOS-only value. + /// + ReadOnlyCollection Vertices { get; } + + /// + /// A flat buffer of texture coordinate values (u, v) for each point in the plane mesh. + /// @remark Each value at a particular index provides the u, v coordinates for the + /// corresponding vertex in the Vertices property. + /// @note iOS-only value. + /// + ReadOnlyCollection TextureCoordinates { get; } + + /// + /// A buffer of indices describing the triangle mesh formed by the plane geometry's vertex data. + /// @remark Each value represents an index into the Vertices and TextureCoordinates arrays. + /// Each set of three represent the corners of a triangle in the mesh therefore, the number of + /// triangles is `TriangleIndices.Length / 3`. + /// @note iOS-only value. + /// + ReadOnlyCollection TriangleIndices { get; } + + /// + /// An array of vertex positions (x, y, z) for each point along the plane's boundary. + /// @remark Each position is in a coordinate system defined by the owning plane anchor's + /// Transform matrix. E.g. "local" to that plane. + /// @remark The vertices only represent a boundary so this property is only useful if you're + /// interested in the general shape or outline of the plane. + /// + ReadOnlyCollection BoundaryVertices { get; } + } +} diff --git a/Assets/ARDK/AR/IARPlaneGeometry.cs.meta b/Assets/ARDK/AR/IARPlaneGeometry.cs.meta new file mode 100644 index 0000000..15f825e --- /dev/null +++ b/Assets/ARDK/AR/IARPlaneGeometry.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6420f2457ee94e4e8b2a252a4048028c +timeCreated: 1592873787 \ No newline at end of file diff --git a/Assets/ARDK/AR/IARPointCloud.cs b/Assets/ARDK/AR/IARPointCloud.cs new file mode 100644 index 0000000..8d7e07c --- /dev/null +++ b/Assets/ARDK/AR/IARPointCloud.cs @@ -0,0 +1,31 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.ObjectModel; + +using UnityEngine; + +namespace Niantic.ARDK.AR +{ + /// + /// Represents a point cloud. + /// + public interface IARPointCloud: + IDisposable + { + /// + /// The collection of detected points. + /// + ReadOnlyCollection Points { get; } + + /// + /// The collection of unique identifiers corresponding to detected feature points. + /// + ReadOnlyCollection Identifiers { get; } + + /// + /// The scaling factor applied to the point cloud's points. + /// + float WorldScale { get; } + } +} diff --git a/Assets/ARDK/AR/IARPointCloud.cs.meta b/Assets/ARDK/AR/IARPointCloud.cs.meta new file mode 100644 index 0000000..ec21273 --- /dev/null +++ b/Assets/ARDK/AR/IARPointCloud.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c58b82531d75246b998a6f860c1ca992 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/IARSession.cs b/Assets/ARDK/AR/IARSession.cs new file mode 100644 index 0000000..b325e81 --- /dev/null +++ b/Assets/ARDK/AR/IARSession.cs @@ -0,0 +1,183 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.AR.Anchors; +using Niantic.ARDK.AR.ARSessionEventArgs; +using Niantic.ARDK.AR.Awareness; +using Niantic.ARDK.AR.Configuration; +using Niantic.ARDK.AR.Mesh; +using Niantic.ARDK.LocationService; +using Niantic.ARDK.Utilities; + +using UnityEngine; + +namespace Niantic.ARDK.AR +{ + /// Values for AR Session running state + public enum ARSessionState + { + None = 0, + Running, + Paused, + Failed + } + + /// Main object for managing AR experiences. + /// @note + /// In order to release underlying native resources quickly, it is important to call Dispose + /// when you're done with an IARSession instance rather than leaving it for the garbage + /// collector. + public interface IARSession: + IDisposable + { + /// The runtime environment this ARSession is compatible with. + RuntimeEnvironment RuntimeEnvironment { get; } + + /// Object that defines what tracking, mapping, and depth processing behaviours are enabled + /// in the session. + IARConfiguration Configuration { get; } + + /// AR interpretation of the world most recently surfaced by the session. + /// @note May be null. + IARFrame CurrentFrame { get; } + + /// Gets or sets the "Disposal Policy" of the frames. By default, all frames are fully disposed + /// after a new frame is available. This can be changed to just release the image and textures + /// (so other traits like Anchors can still be accessed) or to be completely keep them in + /// memory. + /// Assuming you change this value, you should also correctly dispose of the frames on your own + /// after you finish reusing them. + ARFrameDisposalPolicy DefaultFrameDisposalPolicy { get; set; } + + /// World scale applied to all transforms. + /// @note This factor scales what we internally represent as a meter. Set to `2` means that + /// for every meter the device moves in the real world, the virtual camera will move 2 + /// meters -- effectively scaling "down" the virtual world. + float WorldScale { get; set; } + + /// An identifier used internally to relate different systems. This is the identifier for + /// the AR system. + Guid StageIdentifier { get; } + + /// Current state of the session + ARSessionState State { get; } + + /// The mesh generated by the currently running session. + /// @note Will never be null, but will only contain data when meshing is enabled. + IARMesh Mesh { get; } + + /// Starts AR processing with the specified configuration and options. + /// @param configuration + /// Object that defines what tracking, mapping, and depth processing behaviours are enabled + /// in the session. + /// @param options + /// Options defining how to transition the session if you are changing its configuration. + /// This parameter has no effect if running the session for the first time. + /// @note + /// Run can safely be called at any point during the application's run cycle, but if it + /// has been called before, passing in a configuration of a different type than the + /// current configuration may result in tracking being reset. + void Run + ( + IARConfiguration configuration, + ARSessionRunOptions options = ARSessionRunOptions.None + ); + + /// Pauses processing in the session. + /// @note + /// If the device moves while the session is paused and then the session restarts running, + /// world tracking will be incorrect until the session is able to re-localize. + void Pause(); + + /// Creates and adds an anchor to be tracked by the session. + /// @param transform + /// Position, rotation and scale of the anchor in the coordinate space of the AR session + /// it will be tracked in. + /// @returns The created anchor. + IARAnchor AddAnchor(Matrix4x4 transform); + + /// Removes the specified anchor from being tracked by the session. + /// @param anchor The anchor to remove. + void RemoveAnchor(IARAnchor anchor); + + /// Set up this session to listen to updates from the provided location service. + /// @param locationService The location service to listen to updates from. + void SetupLocationService(ILocationService locationService); + + /// Check the status of the initialization process required to run ContextAwareness features. + /// @param error + /// When this method returns, contains an enum value describing the error status of + /// initialization. + /// @param errorMessage + /// When this method returns, contains an error message if an error occured. + /// Otherwise, an empty string. + /// @returns + /// Enum value describing where in the ContextAwareness initialization process the + /// session is currently at. + /// @note + /// On devices where LiDAR is available, the Awareness algorithm will not be automatically + /// initialized when meshing is enabled. + AwarenessInitializationStatus GetAwarenessInitializationStatus + ( + out AwarenessInitializationError error, + out string errorMessage + ); + + /// Called when the session is deinitialized. + event ArdkEventHandler Deinitialized; + + /// Called when the session has just been run + event ArdkEventHandler Ran; + + /// Called when the session has just been paused + event ArdkEventHandler Paused; + + /// Called when the session receives an updated ARFrame. + event ArdkEventHandler FrameUpdated; + + /// Alerts subscribers that anchors have been merged and the duplicates have been removed. + event ArdkEventHandler AnchorsMerged; + + /// Alerts subscribers when one or more anchors have been added to the session. + event ArdkEventHandler AnchorsAdded; + + /// Alerts subscribers when one or more anchors have been updated. + event ArdkEventHandler AnchorsUpdated; + + /// Alerts subscribers when one or more anchors have been removed from the session. + /// After an Anchor is removed from the session, it is disposed of and can't be used anymore. + event ArdkEventHandler AnchorsRemoved; + + /// Alerts subscribers when one or more maps have been added to the session. + event ArdkEventHandler MapsAdded; + + /// Alerts subscribers when one or more maps have been updated. + event ArdkEventHandler MapsUpdated; + + /// Informs subscribers to changes in the quality of the position tracking. + event ArdkEventHandler CameraTrackingStateChanged; + + /// Informs subscribers when the session has temporarily stopped processing frames + /// and tracking position. + /// @note This event will only fire on iOS. + event ArdkEventHandler SessionInterrupted; + + /// Informs subscribers when the session has resumed processing from an interrupted peerState. + /// @note This event will only fire on iOS. + event ArdkEventHandler SessionInterruptionEnded; + + /// Asks the event subscribers whether to attempt recovery of world-tracking peerState after an + /// interruption. Defaults to return false. + /// To tell that a recovery attempt should be made, set the + /// args.ShouldSessionAttemptRelocalization to true. + /// @remark In the event of multiple subscribers, values are aggregated via OR. + /// @note This event will only fire on iOS. + /// @note Not supported in Remote Debugging. + event ArdkEventHandler + QueryingShouldSessionAttemptRelocalization; + + /// Informs subscribers when the session has stopped running due to an error. + event ArdkEventHandler SessionFailed; + } +} diff --git a/Assets/ARDK/AR/IARSession.cs.meta b/Assets/ARDK/AR/IARSession.cs.meta new file mode 100644 index 0000000..0d5d831 --- /dev/null +++ b/Assets/ARDK/AR/IARSession.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 48a0954255434f77aac3bde4abb8dc00 +timeCreated: 1544651780 \ No newline at end of file diff --git a/Assets/ARDK/AR/IARVideoFormat.cs b/Assets/ARDK/AR/IARVideoFormat.cs new file mode 100644 index 0000000..f9d45eb --- /dev/null +++ b/Assets/ARDK/AR/IARVideoFormat.cs @@ -0,0 +1,25 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using UnityEngine; + +namespace Niantic.ARDK.AR +{ + public interface IARVideoFormat + { + /// + /// How many frames of video will be processed per second on the native side. + /// + int FramesPerSecond { get; } + + /// + /// The resolution [width, height] of the video feed from an AR session. + /// + Vector2 ImageResolution { get; } + + /// + /// The resolution [width, height] of the gpu video feed from an AR session. + /// + Vector2 TextureResolution { get; } + } +} diff --git a/Assets/ARDK/AR/IARVideoFormat.cs.meta b/Assets/ARDK/AR/IARVideoFormat.cs.meta new file mode 100644 index 0000000..e2c1c1c --- /dev/null +++ b/Assets/ARDK/AR/IARVideoFormat.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 796e1b6ca39174e3eb5c65af216ee991 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/IImageBuffer.cs b/Assets/ARDK/AR/IImageBuffer.cs new file mode 100644 index 0000000..4546dfa --- /dev/null +++ b/Assets/ARDK/AR/IImageBuffer.cs @@ -0,0 +1,23 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +namespace Niantic.ARDK.AR +{ + /// + /// Interface for implementations of an Image Buffer + /// + public interface IImageBuffer: + IDisposable + { + /// + /// The format of the image. See ARDK.AR.ImageFormat. + /// + ImageFormat Format { get; } + + /// + /// Access the collection of planes that this IImageBuffer manages. + /// + IImagePlanes Planes { get; } + } +} diff --git a/Assets/ARDK/AR/IImageBuffer.cs.meta b/Assets/ARDK/AR/IImageBuffer.cs.meta new file mode 100644 index 0000000..00a303a --- /dev/null +++ b/Assets/ARDK/AR/IImageBuffer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 97ca8c7b2fec945dab4954d28ff1e5ca +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/IImagePlane.cs b/Assets/ARDK/AR/IImagePlane.cs new file mode 100644 index 0000000..85da9c9 --- /dev/null +++ b/Assets/ARDK/AR/IImagePlane.cs @@ -0,0 +1,36 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Unity.Collections; + +namespace Niantic.ARDK.AR +{ + /// + /// Represents a plane of an IImageBuffer. + /// + public interface IImagePlane + { + /// + /// Returns a native array of bytes of the current plane. + /// Users are not supposed to modify this Data, yet it is returned as a basic array of bytes + /// so Buffer.BlockCopy and similar operations can be used on it. + /// + NativeArray Data { get; } + + int PixelWidth { get; } + int PixelHeight { get; } + + /// + /// Returns the bytes per row of the current plane. + /// @remark Also referred to as row-stride. + /// + int BytesPerRow { get; } + + /// + /// Returns the bytes per pixel of the current plane. + /// @remark Also referred to as pixel-stride. + /// + int BytesPerPixel { get; } + } +} diff --git a/Assets/ARDK/AR/IImagePlane.cs.meta b/Assets/ARDK/AR/IImagePlane.cs.meta new file mode 100644 index 0000000..dcd5606 --- /dev/null +++ b/Assets/ARDK/AR/IImagePlane.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 4441b65a158749edb4c8e74ad13c4909 +timeCreated: 1593105718 \ No newline at end of file diff --git a/Assets/ARDK/AR/IImagePlanes.cs b/Assets/ARDK/AR/IImagePlanes.cs new file mode 100644 index 0000000..95059b3 --- /dev/null +++ b/Assets/ARDK/AR/IImagePlanes.cs @@ -0,0 +1,15 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.Collections.Generic; + +namespace Niantic.ARDK.AR +{ + // TODO: In newer versions of .NET we could just use IReadOnlyCollection + // instead of creating this entire interface. + public interface IImagePlanes: + IEnumerable + { + int Count { get; } + IImagePlane this[int planeIndex] { get; } + } +} diff --git a/Assets/ARDK/AR/IImagePlanes.cs.meta b/Assets/ARDK/AR/IImagePlanes.cs.meta new file mode 100644 index 0000000..7f42fc4 --- /dev/null +++ b/Assets/ARDK/AR/IImagePlanes.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: eaeeb60e8d25443799811ce6829411e5 +timeCreated: 1593105675 \ No newline at end of file diff --git a/Assets/ARDK/AR/Image.meta b/Assets/ARDK/AR/Image.meta new file mode 100644 index 0000000..a3fed5d --- /dev/null +++ b/Assets/ARDK/AR/Image.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0ca7e25842b804140af8cdd03ab77725 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Image/_ImageFactory.cs b/Assets/ARDK/AR/Image/_ImageFactory.cs new file mode 100644 index 0000000..33980aa --- /dev/null +++ b/Assets/ARDK/AR/Image/_ImageFactory.cs @@ -0,0 +1,66 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Unity.Collections; + +namespace Niantic.ARDK.AR.Image +{ + internal static class _ImageFactory + { + // compressionLevel 0 = raw. + internal static _SerializableImageBuffer _AsSerializable + ( + this IImageBuffer source, + int compressionLevel + ) + { + if (source == null) + return null; + + var possibleResult = source as _SerializableImageBuffer; + if (possibleResult != null) + return possibleResult; + + var planes = source.Planes._AsSerializable(); + return new _SerializableImageBuffer(source.Format, planes, compressionLevel); + } + + internal static _SerializableImagePlanes _AsSerializable(this IImagePlanes source) + { + if (source == null) + return null; + + var possibleResult = source as _SerializableImagePlanes; + if (possibleResult != null) + return null; + + int count = source.Count; + var result = new _SerializableImagePlane[count]; + for (int i = 0; i < count; i++) + result[i] = source[i]._AsSerializable(); + + return new _SerializableImagePlanes(result); + } + + internal static _SerializableImagePlane _AsSerializable(this IImagePlane source) + { + if (source == null) + return null; + + var possibleResult = source as _SerializableImagePlane; + if (possibleResult != null) + return possibleResult; + + var result = + new _SerializableImagePlane + ( + source.Data, + source.PixelWidth, + source.PixelHeight, + source.BytesPerRow, + source.BytesPerPixel + ); + + return result; + } + } +} diff --git a/Assets/ARDK/AR/Image/_ImageFactory.cs.meta b/Assets/ARDK/AR/Image/_ImageFactory.cs.meta new file mode 100644 index 0000000..955fd27 --- /dev/null +++ b/Assets/ARDK/AR/Image/_ImageFactory.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5b4195db9f934800b82f9b64f03ec9c0 +timeCreated: 1595010403 \ No newline at end of file diff --git a/Assets/ARDK/AR/Image/_NativeImageBuffer.cs b/Assets/ARDK/AR/Image/_NativeImageBuffer.cs new file mode 100644 index 0000000..264b33b --- /dev/null +++ b/Assets/ARDK/AR/Image/_NativeImageBuffer.cs @@ -0,0 +1,115 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Runtime.InteropServices; + +using Niantic.ARDK.Internals; + +namespace Niantic.ARDK.AR.Image +{ + internal sealed class _NativeImageBuffer: + IImageBuffer + { + static _NativeImageBuffer() + { + Platform.Init(); + } + + private readonly long _consumedUnmanagedMemory; + + public _NativeImageBuffer(IntPtr nativeHandle) + { + if (nativeHandle == IntPtr.Zero) + throw new ArgumentException("nativeHandle can't be Zero.", nameof(nativeHandle)); + + _nativeHandle = nativeHandle; + + Planes = _CreatePlanes(nativeHandle); + _consumedUnmanagedMemory = _CalculateConsumedMemory(); + GC.AddMemoryPressure(_consumedUnmanagedMemory); + } + + private static void _ReleaseImmediate(IntPtr nativeHandle) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARImage_Release(nativeHandle); + } + + ~_NativeImageBuffer() + { + _ReleaseImmediate(_nativeHandle); + GC.RemoveMemoryPressure(_consumedUnmanagedMemory); + } + + public void Dispose() + { + GC.SuppressFinalize(this); + + var nativeHandle = _nativeHandle; + if (nativeHandle != IntPtr.Zero) + { + _nativeHandle = IntPtr.Zero; + + _ReleaseImmediate(nativeHandle); + GC.RemoveMemoryPressure(_consumedUnmanagedMemory); + } + + Planes = null; + } + + private IntPtr _nativeHandle; + internal IntPtr _NativeHandle + { + get { return _nativeHandle; } + } + + public ImageFormat Format + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return (ImageFormat)_NARImage_GetFormat(_nativeHandle); + + #pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + } + } + + public _NativeImagePlanes Planes { get; private set; } + + private _NativeImagePlanes _CreatePlanes(IntPtr nativeHandle) + { + return new _NativeImagePlanes(nativeHandle); + } + + IImagePlanes IImageBuffer.Planes + { + get { return Planes; } + } + + private long _CalculateConsumedMemory() + { + var planeCount = Planes.Count; + if (planeCount == 0) + return 0; + + var plane = Planes[0]; + + if (planeCount == 1) + return plane.BytesPerRow * plane.PixelHeight; + + // This code currently tries to estimate the total memory consumed without querying all + // the planes. A possible optimization is to have C++ return the size of the unmanaged + // memory together with the count of planes. + // 1.5 was obtained because some planes use 1 byte per pixel while others use 2 per pixel. + return (int)(plane.PixelWidth * plane.PixelHeight * planeCount * 1.5); + } + + [DllImport(_ARDKLibrary.libraryName)] + private static extern Int32 _NARImage_GetFormat(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARImage_Release(IntPtr nativeHandle); + } +} diff --git a/Assets/ARDK/AR/Image/_NativeImageBuffer.cs.meta b/Assets/ARDK/AR/Image/_NativeImageBuffer.cs.meta new file mode 100644 index 0000000..3ea9ed7 --- /dev/null +++ b/Assets/ARDK/AR/Image/_NativeImageBuffer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6b29336c51d44df19dd40d5cbc1336b7 +timeCreated: 1593107928 \ No newline at end of file diff --git a/Assets/ARDK/AR/Image/_NativeImagePlane.cs b/Assets/ARDK/AR/Image/_NativeImagePlane.cs new file mode 100644 index 0000000..f41cb54 --- /dev/null +++ b/Assets/ARDK/AR/Image/_NativeImagePlane.cs @@ -0,0 +1,143 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Runtime.InteropServices; + +using Niantic.ARDK.Internals; + +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; + + +namespace Niantic.ARDK.AR.Image +{ + internal sealed class _NativeImagePlane: + IImagePlane + { + private readonly IntPtr _nativeHandle; + internal readonly UInt64 _planeIndex; + + private NativeArray _data; + + internal _NativeImagePlane(IntPtr nativeHandle, int planeIndex) + { + _nativeHandle = nativeHandle; + _planeIndex = (UInt64)planeIndex; + } + + public int PixelWidth + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _NARImage_GetWidthOfPlane(_nativeHandle, _planeIndex); + + #pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + } + } + + public int PixelHeight + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _NARImage_GetHeightOfPlane(_nativeHandle, _planeIndex); + + #pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + } + } + + public int BytesPerRow + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return checked((int)_NARImage_GetBytesPerRowOfPlane(_nativeHandle, _planeIndex)); + + #pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + } + } + + public int BytesPerPixel + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return checked((int)_NARImage_GetBytesPerPixelOfPlane(_nativeHandle, _planeIndex)); + + #pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + } + } + + + public NativeArray Data + { + get + { + unsafe + { + if (!_data.IsCreated) + { + var dataAddress = _GetBaseDataAddress().ToPointer(); + var length = BytesPerRow * PixelHeight; + + _data = + NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray + ( + dataAddress, + length, + Allocator.None + ); + } + + return _data; + } + } + } + + private IntPtr _GetBaseDataAddress() + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _NARImage_GetBaseAddressOfPlane(_nativeHandle, _planeIndex); + + #pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + } + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NARImage_GetBaseAddressOfPlane + ( + IntPtr nativeHandle, + UInt64 planeIndex + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern Int32 _NARImage_GetWidthOfPlane(IntPtr nativeHandle, UInt64 planeIndex); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern Int32 _NARImage_GetHeightOfPlane(IntPtr nativeHandle, UInt64 planeIndex); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern UInt64 _NARImage_GetBytesPerRowOfPlane + ( + IntPtr nativeHandle, + UInt64 planeIndex + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern UInt64 _NARImage_GetBytesPerPixelOfPlane + ( + IntPtr nativeHandle, + UInt64 planeIndex + ); + } +} diff --git a/Assets/ARDK/AR/Image/_NativeImagePlane.cs.meta b/Assets/ARDK/AR/Image/_NativeImagePlane.cs.meta new file mode 100644 index 0000000..9221b2e --- /dev/null +++ b/Assets/ARDK/AR/Image/_NativeImagePlane.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 4341b5b6ec014420af6030b842272b23 +timeCreated: 1593109019 \ No newline at end of file diff --git a/Assets/ARDK/AR/Image/_NativeImagePlanes.cs b/Assets/ARDK/AR/Image/_NativeImagePlanes.cs new file mode 100644 index 0000000..5810f92 --- /dev/null +++ b/Assets/ARDK/AR/Image/_NativeImagePlanes.cs @@ -0,0 +1,93 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +using Niantic.ARDK.Internals; + +namespace Niantic.ARDK.AR.Image +{ + internal sealed class _NativeImagePlanes: + IImagePlanes + { + private readonly _NativeImagePlane[] _planes; + + internal _NativeImagePlanes(IntPtr nativeHandle) + { + _nativeHandle = nativeHandle; + + ulong count = 0; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + count = _NARImage_GetPlaneCount(nativeHandle); + + _planes = new _NativeImagePlane[count]; + } + + private IntPtr _nativeHandle; + + internal IntPtr _NativeHandle + { + get { return _nativeHandle; } + } + + public int Count + { + get { return _planes.Length; } + } + + public _NativeImagePlane this[int planeIndex] + { + get + { + if (planeIndex < 0 || planeIndex >= Count) + throw new ArgumentOutOfRangeException(nameof(planeIndex)); + + var result = _planes[planeIndex]; + if (result == null) + { + result = _CreatePlane(planeIndex); + _planes[planeIndex] = result; + } + + return result; + } + } + + public IEnumerator<_NativeImagePlane> GetEnumerator() + { + int count = Count; + for (int i = 0; i < count; i++) + yield return this[i]; + } + + private _NativeImagePlane _CreatePlane(int planeIndex) + { + return new _NativeImagePlane(_nativeHandle, planeIndex); + } + + IImagePlane IImagePlanes.this[int planeIndex] + { + get { return this[planeIndex]; } + } + + IEnumerator IEnumerable.GetEnumerator() + { + // In newer versions of .NET we could just: + // return GetEnumerator(); + + int count = Count; + for (int i = 0; i < count; i++) + yield return this[i]; + } + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + [DllImport(_ARDKLibrary.libraryName)] + private static extern UInt64 _NARImage_GetPlaneCount(IntPtr nativeHandle); + } +} diff --git a/Assets/ARDK/AR/Image/_NativeImagePlanes.cs.meta b/Assets/ARDK/AR/Image/_NativeImagePlanes.cs.meta new file mode 100644 index 0000000..cbc81eb --- /dev/null +++ b/Assets/ARDK/AR/Image/_NativeImagePlanes.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c5cd90f5eab64e4db5bb923532653d02 +timeCreated: 1593108756 \ No newline at end of file diff --git a/Assets/ARDK/AR/Image/_SerializableImageBuffer.cs b/Assets/ARDK/AR/Image/_SerializableImageBuffer.cs new file mode 100644 index 0000000..1f42d22 --- /dev/null +++ b/Assets/ARDK/AR/Image/_SerializableImageBuffer.cs @@ -0,0 +1,46 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +namespace Niantic.ARDK.AR.Image +{ + // Can't use [Serializable]. Need to provide a serializer. + internal sealed class _SerializableImageBuffer: + IImageBuffer + { + internal _SerializableImageBuffer + ( + ImageFormat format, + _SerializableImagePlanes planes, + int compressionLevel + ) + { + if (planes == null) + throw new ArgumentNullException(nameof(planes)); + + Format = format; + Planes = planes; + CompressionLevel = compressionLevel; + } + + public void Dispose() + { + var planes = Planes; + if (planes != null) + { + Planes = null; + planes._Dispose(); + } + } + + public ImageFormat Format { get; private set; } + public _SerializableImagePlanes Planes { get; private set; } + + public int CompressionLevel { get; private set; } + + IImagePlanes IImageBuffer.Planes + { + get { return Planes; } + } + } +} diff --git a/Assets/ARDK/AR/Image/_SerializableImageBuffer.cs.meta b/Assets/ARDK/AR/Image/_SerializableImageBuffer.cs.meta new file mode 100644 index 0000000..6682cb5 --- /dev/null +++ b/Assets/ARDK/AR/Image/_SerializableImageBuffer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: abbf7cadf0e1481fbcd0b2484e39db7e +timeCreated: 1593102853 \ No newline at end of file diff --git a/Assets/ARDK/AR/Image/_SerializableImageBufferSerializer.cs b/Assets/ARDK/AR/Image/_SerializableImageBufferSerializer.cs new file mode 100644 index 0000000..9324256 --- /dev/null +++ b/Assets/ARDK/AR/Image/_SerializableImageBufferSerializer.cs @@ -0,0 +1,56 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Utilities.BinarySerialization; +using Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Image +{ + internal sealed class _SerializableImageBufferSerializer: + BaseItemSerializer<_SerializableImageBuffer> + { + internal static readonly _SerializableImageBufferSerializer _instance = + new _SerializableImageBufferSerializer(); + + private _SerializableImageBufferSerializer() + { + } + protected override void DoSerialize(BinarySerializer serializer, _SerializableImageBuffer item) + { + EnumSerializer.ForType().Serialize(serializer, item.Format); + + var compressionQuality = item.CompressionLevel; + CompressedInt32Serializer.Instance.Serialize(serializer, compressionQuality); + + if (compressionQuality == 100) + serializer.Serialize(item.Planes); + else + { + var compressedImage = + // TODO(kmori): will revisit if always scaling won't bring side effects + _VideoStreamHelper._CompressForVideoWithScale(item.Planes, item.Format, compressionQuality); + + serializer.Serialize(compressedImage); + } + } + + protected override _SerializableImageBuffer DoDeserialize(BinaryDeserializer deserializer) + { + var format = EnumSerializer.ForType().Deserialize(deserializer); + int compressionLevel = CompressedInt32Serializer.Instance.Deserialize(deserializer); + var planesOrCompressed = deserializer.Deserialize(); + + _SerializableImagePlanes planes; + if (compressionLevel == 0) + planes = (_SerializableImagePlanes)planesOrCompressed; + else + { + var compressedImage = (CompressedImage)planesOrCompressed; + planes = _VideoStreamHelper._DecompressForVideo(compressedImage); + } + + return new _SerializableImageBuffer(format, planes, compressionLevel); + } + } +} diff --git a/Assets/ARDK/AR/Image/_SerializableImageBufferSerializer.cs.meta b/Assets/ARDK/AR/Image/_SerializableImageBufferSerializer.cs.meta new file mode 100644 index 0000000..4889d42 --- /dev/null +++ b/Assets/ARDK/AR/Image/_SerializableImageBufferSerializer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: b9493594a8c24032b2f565dc5319b716 +timeCreated: 1593213799 \ No newline at end of file diff --git a/Assets/ARDK/AR/Image/_SerializableImagePlane.cs b/Assets/ARDK/AR/Image/_SerializableImagePlane.cs new file mode 100644 index 0000000..97d80d8 --- /dev/null +++ b/Assets/ARDK/AR/Image/_SerializableImagePlane.cs @@ -0,0 +1,96 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Runtime.InteropServices; + +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Image +{ + // This class is not marked [Serializable] on purpose. + // We need to register the proper Serializer into the global serializer, as this class has some + // fields that are actually not serializable. + internal sealed class _SerializableImagePlane: + IImagePlane + { +#if UNITY_EDITOR + internal _SerializableImagePlane + ( + NativeArray data, + AtomicSafetyHandle dataHandle, + int pixelWidth, + int pixelHeight, + int bytesPerRow, + int bytesPerPixel + ) + : this(data,pixelWidth, pixelHeight, bytesPerRow, bytesPerPixel) + { + _dataHandle = dataHandle; + } +#endif + + internal _SerializableImagePlane + ( + NativeArray data, + int pixelWidth, + int pixelHeight, + int bytesPerRow, + int bytesPerPixel + ) + { + if (data == null) + throw new ArgumentNullException(nameof(data)); + + if (pixelWidth < 0) + throw new ArgumentOutOfRangeException(nameof(pixelWidth)); + + if (pixelHeight < 0) + throw new ArgumentOutOfRangeException(nameof(pixelHeight)); + + if (bytesPerPixel < 1) + throw new ArgumentOutOfRangeException(nameof(bytesPerPixel)); + + if (bytesPerRow < pixelWidth * bytesPerPixel) + throw new ArgumentOutOfRangeException(nameof(bytesPerRow)); + + if (data.Length < bytesPerPixel * pixelHeight) + throw new ArgumentException("The provided data is too small for the dimensions given."); + + Data = data; + PixelWidth = pixelWidth; + PixelHeight = pixelHeight; + BytesPerRow = bytesPerRow; + BytesPerPixel = bytesPerPixel; + } + + public int PixelWidth { get; private set; } + public int PixelHeight { get; private set; } + public int BytesPerRow { get; private set; } + public int BytesPerPixel { get; private set; } + + public NativeArray Data { get; private set; } + +#if UNITY_EDITOR + // Value depends on whether compression was used when serializing the original device frame + // to send over RemoteConnection. + private readonly AtomicSafetyHandle? _dataHandle; +#endif + + // This method is internal because it is the _SerializableImageBuffer that's supposed to call + // it. Users do not need to Dispose() instances of this class. + internal void _Dispose() + { +#if UNITY_EDITOR + if (_dataHandle.HasValue) + AtomicSafetyHandle.Release(_dataHandle.Value); + else + Data.Dispose(); +#else + Data.Dispose(); +#endif + } + } +} diff --git a/Assets/ARDK/AR/Image/_SerializableImagePlane.cs.meta b/Assets/ARDK/AR/Image/_SerializableImagePlane.cs.meta new file mode 100644 index 0000000..dbfdee6 --- /dev/null +++ b/Assets/ARDK/AR/Image/_SerializableImagePlane.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c627ab6992f44573ad2072a2ad94e98e +timeCreated: 1593103609 \ No newline at end of file diff --git a/Assets/ARDK/AR/Image/_SerializableImagePlaneSerializer.cs b/Assets/ARDK/AR/Image/_SerializableImagePlaneSerializer.cs new file mode 100644 index 0000000..46690f8 --- /dev/null +++ b/Assets/ARDK/AR/Image/_SerializableImagePlaneSerializer.cs @@ -0,0 +1,49 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Utilities.BinarySerialization; +using Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers; + +using Unity.Collections; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Image +{ + internal sealed class _SerializableImagePlaneSerializer: + BaseItemSerializer<_SerializableImagePlane> + { + internal static readonly _SerializableImagePlaneSerializer _instance = + new _SerializableImagePlaneSerializer(); + + private _SerializableImagePlaneSerializer() + { + } + + protected override void DoSerialize(BinarySerializer serializer, _SerializableImagePlane item) + { + NativeArraySerializer.Instance.Serialize(serializer, item.Data); + + var int32Serializer = CompressedInt32Serializer.Instance; + int32Serializer.Serialize(serializer, item.PixelWidth); + int32Serializer.Serialize(serializer, item.PixelHeight); + int32Serializer.Serialize(serializer, item.BytesPerRow); + int32Serializer.Serialize(serializer, item.BytesPerPixel); + } + + protected override _SerializableImagePlane DoDeserialize(BinaryDeserializer deserializer) + { + var data = NativeArraySerializer.Instance.Deserialize(deserializer); + + var int32Deserializer = CompressedInt32Serializer.Instance; + int pixelWidth = int32Deserializer.Deserialize(deserializer); + int pixelHeight = int32Deserializer.Deserialize(deserializer); + int bytesPerRow = int32Deserializer.Deserialize(deserializer); + int bytesPerPixel = int32Deserializer.Deserialize(deserializer); + + var result = + new _SerializableImagePlane(data, pixelWidth, pixelHeight, bytesPerRow, bytesPerPixel); + + return result; + } + } +} diff --git a/Assets/ARDK/AR/Image/_SerializableImagePlaneSerializer.cs.meta b/Assets/ARDK/AR/Image/_SerializableImagePlaneSerializer.cs.meta new file mode 100644 index 0000000..ec55ce1 --- /dev/null +++ b/Assets/ARDK/AR/Image/_SerializableImagePlaneSerializer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 8fec112e8df84bc0b94608429c29022e +timeCreated: 1593106483 \ No newline at end of file diff --git a/Assets/ARDK/AR/Image/_SerializableImagePlanes.cs b/Assets/ARDK/AR/Image/_SerializableImagePlanes.cs new file mode 100644 index 0000000..cc7f8a6 --- /dev/null +++ b/Assets/ARDK/AR/Image/_SerializableImagePlanes.cs @@ -0,0 +1,57 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace Niantic.ARDK.AR.Image +{ + [Serializable] + internal sealed class _SerializableImagePlanes: + IImagePlanes + { + internal readonly _SerializableImagePlane[] _planes; + internal _SerializableImagePlanes(_SerializableImagePlane[] planeArray) + { + if (planeArray == null) + throw new ArgumentNullException(nameof(planeArray)); + + _planes = planeArray; + } + + internal void _Dispose() + { + foreach (var plane in _planes) + plane._Dispose(); + } + + public int Count + { + get { return _planes.Length; } + } + + public _SerializableImagePlane this[int planeIndex] + { + get { return _planes[planeIndex]; } + } + IImagePlane IImagePlanes.this[int planeIndex] + { + get { return this[planeIndex]; } + } + + public IEnumerator<_SerializableImagePlane> GetEnumerator() + { + foreach (var plane in _planes) + yield return plane; + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + } +} diff --git a/Assets/ARDK/AR/Image/_SerializableImagePlanes.cs.meta b/Assets/ARDK/AR/Image/_SerializableImagePlanes.cs.meta new file mode 100644 index 0000000..346f7ac --- /dev/null +++ b/Assets/ARDK/AR/Image/_SerializableImagePlanes.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 2976473c9d2d4b0591a8629d9a635169 +timeCreated: 1593103279 \ No newline at end of file diff --git a/Assets/ARDK/AR/ImageFormat.cs b/Assets/ARDK/AR/ImageFormat.cs new file mode 100644 index 0000000..3ee1803 --- /dev/null +++ b/Assets/ARDK/AR/ImageFormat.cs @@ -0,0 +1,30 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.AR +{ + /// Possible formats for an ImageBuffer. + public enum ImageFormat + { + /// Single plane, grayscale image. + Grayscale = 0, + + /// Single plane, BGRA image. + RGB = 1, + + /// Single plane, BGRA image. + RGBA = 2, + + /// Single plane, BGRA image. + BGRA = 3, + + /// Dual plane, YCbCr (4:2:0) image. + /// The YCbCr NV12 format, with Cb(U) coming before Cr(V) in each pair on the UV plane + YCbCr12 = 4, + + /// Dual plane, YCbCr (4:2:0) image. + /// The YCbCr NV21 format, with Cr(V) coming before Cb(U) in each pair on the UV plane + YCbCr21 = 5, + + Incomplete = 6, + } +} diff --git a/Assets/ARDK/AR/ImageFormat.cs.meta b/Assets/ARDK/AR/ImageFormat.cs.meta new file mode 100644 index 0000000..9034166 --- /dev/null +++ b/Assets/ARDK/AR/ImageFormat.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 043c18873580c4ed292d8fc0887c1716 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/IncorrectlyUsedNativeClassException.cs b/Assets/ARDK/AR/IncorrectlyUsedNativeClassException.cs new file mode 100644 index 0000000..7a7fc40 --- /dev/null +++ b/Assets/ARDK/AR/IncorrectlyUsedNativeClassException.cs @@ -0,0 +1,18 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +namespace Niantic.ARDK.AR +{ + public sealed class IncorrectlyUsedNativeClassException + : Exception + { + private const string IncorrectNativeClassMessage = + "Using a Native class with no testing/non-native fallback on a non-native platform"; + + public IncorrectlyUsedNativeClassException() + : base(IncorrectNativeClassMessage) + { + } + } +} diff --git a/Assets/ARDK/AR/IncorrectlyUsedNativeClassException.cs.meta b/Assets/ARDK/AR/IncorrectlyUsedNativeClassException.cs.meta new file mode 100644 index 0000000..58f053d --- /dev/null +++ b/Assets/ARDK/AR/IncorrectlyUsedNativeClassException.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 15150ff3fc16445bb9b13c50c796c9e8 +timeCreated: 1607473871 \ No newline at end of file diff --git a/Assets/ARDK/AR/InterpolationMode.cs b/Assets/ARDK/AR/InterpolationMode.cs new file mode 100644 index 0000000..3714dec --- /dev/null +++ b/Assets/ARDK/AR/InterpolationMode.cs @@ -0,0 +1,18 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +namespace Niantic.ARDK.AR +{ + /// The amount of synchronization with the camera pose to apply to each awareness buffer. Currently, + /// awareness frames are surfaced at ~20 fps, while poses are surfaced at ~30 fps (Android) or + /// ~60 fps (iOS). + public enum InterpolationMode + { + /// Don't sync with the camera pose. + None = 0, + + /// The awareness buffer is synced one time with the camera when it surfaces to the app. + Balanced = 1, + + /// The awareness buffer is synced with every pose until a new buffer replaces it. + Smooth = 2 + } +} diff --git a/Assets/ARDK/AR/InterpolationMode.cs.meta b/Assets/ARDK/AR/InterpolationMode.cs.meta new file mode 100644 index 0000000..ca3a44b --- /dev/null +++ b/Assets/ARDK/AR/InterpolationMode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9442ff8a9567474f9de3e4080537d581 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/LightEstimate.meta b/Assets/ARDK/AR/LightEstimate.meta new file mode 100644 index 0000000..de21908 --- /dev/null +++ b/Assets/ARDK/AR/LightEstimate.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cfb8ddc938d3b4a80990d1242d563ede +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/LightEstimate/_ARLightEstimateFactory.cs b/Assets/ARDK/AR/LightEstimate/_ARLightEstimateFactory.cs new file mode 100644 index 0000000..7866ef8 --- /dev/null +++ b/Assets/ARDK/AR/LightEstimate/_ARLightEstimateFactory.cs @@ -0,0 +1,24 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.AR.LightEstimate +{ + internal static class _ARLightEstimateFactory + { + internal static _SerializableARLightEstimate _AsSerializable(this IARLightEstimate source) + { + if (source == null) + return null; + + if (source is _SerializableARLightEstimate possibleResult) + return possibleResult; + + return + new _SerializableARLightEstimate + ( + source.AmbientIntensity, + source.AmbientColorTemperature, + source.ColorCorrection + ); + } + } +} diff --git a/Assets/ARDK/AR/LightEstimate/_ARLightEstimateFactory.cs.meta b/Assets/ARDK/AR/LightEstimate/_ARLightEstimateFactory.cs.meta new file mode 100644 index 0000000..d7f1f27 --- /dev/null +++ b/Assets/ARDK/AR/LightEstimate/_ARLightEstimateFactory.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6d4d736ddc8f4242b74ca735c831cb82 +timeCreated: 1595012286 \ No newline at end of file diff --git a/Assets/ARDK/AR/LightEstimate/_NativeARLightEstimate.cs b/Assets/ARDK/AR/LightEstimate/_NativeARLightEstimate.cs new file mode 100644 index 0000000..fe1dece --- /dev/null +++ b/Assets/ARDK/AR/LightEstimate/_NativeARLightEstimate.cs @@ -0,0 +1,119 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.ObjectModel; +using System.Runtime.InteropServices; + +using Niantic.ARDK.Internals; +using Niantic.ARDK.Utilities.Collections; + +namespace Niantic.ARDK.AR.LightEstimate +{ + internal sealed class _NativeARLightEstimate: + IARLightEstimate + { + // Estimated unmanaged memory usage: 2 floats + 4 float array + private const long _MemoryPressure = (2L * 4L) + (4L * 4L); + + static _NativeARLightEstimate() + { + Platform.Init(); + } + + private IntPtr _nativeHandle; + + internal _NativeARLightEstimate(IntPtr nativeHandle) + { + if (nativeHandle == IntPtr.Zero) + throw new ArgumentException("nativeHandle can't be Zero.", nameof(nativeHandle)); + + GC.AddMemoryPressure(_MemoryPressure); + _nativeHandle = nativeHandle; + } + + private static void _ReleaseImmediate(IntPtr nativeHandle) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARLightEstimate_Release(nativeHandle); + } + + ~_NativeARLightEstimate() + { + _ReleaseImmediate(_nativeHandle); + GC.RemoveMemoryPressure(_MemoryPressure); + } + + public void Dispose() + { + GC.SuppressFinalize(this); + + var nativeHandle = _nativeHandle; + if (nativeHandle != IntPtr.Zero) + { + _nativeHandle = IntPtr.Zero; + _ReleaseImmediate(nativeHandle); + GC.RemoveMemoryPressure(_MemoryPressure); + } + } + + public float AmbientIntensity + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _NARLightEstimate_GetAmbientIntensity(_nativeHandle); + + #pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + } + } + + public float AmbientColorTemperature + { + get + { +#if UNITY_IOS + return _NARLightEstimate_GetAmbientColorTemperature(_nativeHandle); +#else + return 0f; +#endif + } + } + + public ReadOnlyCollection ColorCorrection + { + get + { +#if UNITY_ANDROID + // Can we cache both the array and the read-only collection and just update it + // at every request instead of allocating new ones??? + + var correction = new float[4]; + _NARLightEstimate_GetColorCorrection(_nativeHandle, correction); + return new ReadOnlyCollection(correction); +#else + return EmptyReadOnlyCollection.Instance; +#endif + } + } + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARLightEstimate_Release(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern float _NARLightEstimate_GetAmbientIntensity(IntPtr nativeHandle); + +#if UNITY_IOS + [DllImport(_ARDKLibrary.libraryName)] + private static extern float _NARLightEstimate_GetAmbientColorTemperature(IntPtr nativeHandle); +#elif UNITY_ANDROID + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARLightEstimate_GetColorCorrection + ( + IntPtr nativeHandle, + float[] outCorrection + ); +#endif + } +} diff --git a/Assets/ARDK/AR/LightEstimate/_NativeARLightEstimate.cs.meta b/Assets/ARDK/AR/LightEstimate/_NativeARLightEstimate.cs.meta new file mode 100644 index 0000000..4d77ac9 --- /dev/null +++ b/Assets/ARDK/AR/LightEstimate/_NativeARLightEstimate.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ded14c1e4ed9404c8ea1471d68ed119b +timeCreated: 1592592566 \ No newline at end of file diff --git a/Assets/ARDK/AR/LightEstimate/_SerializableARLightEstimate.cs b/Assets/ARDK/AR/LightEstimate/_SerializableARLightEstimate.cs new file mode 100644 index 0000000..116f661 --- /dev/null +++ b/Assets/ARDK/AR/LightEstimate/_SerializableARLightEstimate.cs @@ -0,0 +1,39 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.ObjectModel; + +using Niantic.ARDK.Utilities.Collections; + +namespace Niantic.ARDK.AR.LightEstimate +{ + [Serializable] + internal sealed class _SerializableARLightEstimate: + IARLightEstimate + { + internal _SerializableARLightEstimate + ( + float ambientIntensity, + float ambientColorTemperature, + ReadOnlyCollection colorCorrection + ) + { + AmbientIntensity = ambientIntensity; + AmbientColorTemperature = ambientColorTemperature; + + if (colorCorrection != null && colorCorrection.Count > 0) + ColorCorrection = colorCorrection; + else + ColorCorrection = EmptyReadOnlyCollection.Instance; + } + + public float AmbientIntensity { get; private set; } + public float AmbientColorTemperature { get; private set; } + public ReadOnlyCollection ColorCorrection { get; private set; } + + void IDisposable.Dispose() + { + // Do nothing as this implementation is fully managed. + } + } +} diff --git a/Assets/ARDK/AR/LightEstimate/_SerializableARLightEstimate.cs.meta b/Assets/ARDK/AR/LightEstimate/_SerializableARLightEstimate.cs.meta new file mode 100644 index 0000000..1a33de7 --- /dev/null +++ b/Assets/ARDK/AR/LightEstimate/_SerializableARLightEstimate.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9084c894bee04ea19e2aad786faae315 +timeCreated: 1592591540 \ No newline at end of file diff --git a/Assets/ARDK/AR/MergedAnchorInfo.cs b/Assets/ARDK/AR/MergedAnchorInfo.cs new file mode 100644 index 0000000..57dd7cf --- /dev/null +++ b/Assets/ARDK/AR/MergedAnchorInfo.cs @@ -0,0 +1,104 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +using Niantic.ARDK.AR.Anchors; +using Niantic.ARDK.Utilities.Collections; + +namespace Niantic.ARDK.AR +{ + [StructLayout(LayoutKind.Sequential)] + internal unsafe struct ParentMergeInfo + { + public IntPtr parent; + public IntPtr* children; + public UInt32 childrenSize; + } + + [StructLayout(LayoutKind.Sequential)] + internal unsafe struct RawMergedAnchorInfo + { + public ParentMergeInfo* parents; + public UInt32 parentCount; + + public void Release() + { + for (int i = 0; i < parentCount; i++) + { + var childrenSize = parents[i].childrenSize; + for (int j = 0; j < childrenSize; j++) + _NativeARAnchor._ReleaseImmediate(parents[i].children[j]); + + _NativeARAnchor._ReleaseImmediate(parents[i].parent); + } + + parents = null; + parentCount = 0; + } + + // TODO: Use this on _NativeARSession. + public MergedAnchorInfo ConsumeToMakeMergedAnchorInfo() + { + #pragma warning disable 0162 + if (NativeAccess.Mode != NativeAccess.ModeType.Native) + _ARAnchorFactory._testOnly_DefaultAnchorType = AnchorType.Plane; + #pragma warning restore 0162 + + var mergedAnchors = new Dictionary(); + for (int i = 0; i < (int)parentCount; i++) + { + IntPtr parentNativeHandle = parents[i].parent; + var childrenSize = parents[i].childrenSize; + IARPlaneAnchor[] childrenAsPlanes = new IARPlaneAnchor[childrenSize]; + + for (int j = 0; j < childrenSize; j++) + { + IntPtr childNativeHandle = parents[i].children[j]; + var child = (IARPlaneAnchor)_ARAnchorFactory._FromNativeHandle(childNativeHandle); + childrenAsPlanes[j] = child; + } + + var parent = (IARPlaneAnchor)_ARAnchorFactory._FromNativeHandle(parentNativeHandle); + mergedAnchors.Add(parent, childrenAsPlanes); + } + + // The _NativeARPlaneAnchors have taken over ownership for the native handles and we're no + // longer responsible for disposing them, so 0 out all our references. + parents = null; + parentCount = 0; + + return new MergedAnchorInfo(mergedAnchors); + } + } + + internal struct MergedAnchorInfo: + IDisposable + { + private Dictionary _mergedAnchors; + + internal _ReadOnlyDictionary MergedAnchors { get; private set; } + + internal MergedAnchorInfo(Dictionary mergedAnchors) + : this() + { + _mergedAnchors = mergedAnchors; + MergedAnchors = new _ReadOnlyDictionary(mergedAnchors); + } + + public void Dispose() + { + foreach (var merge in _mergedAnchors) + { + foreach (var child in merge.Value) + child.Dispose(); + + merge.Key.Dispose(); + } + + _mergedAnchors = null; + MergedAnchors = null; + } + } +} diff --git a/Assets/ARDK/AR/MergedAnchorInfo.cs.meta b/Assets/ARDK/AR/MergedAnchorInfo.cs.meta new file mode 100644 index 0000000..b119e17 --- /dev/null +++ b/Assets/ARDK/AR/MergedAnchorInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ced17ea5006f74a77a45acc56803ef49 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Mesh.meta b/Assets/ARDK/AR/Mesh.meta new file mode 100644 index 0000000..170a59e --- /dev/null +++ b/Assets/ARDK/AR/Mesh.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f6b019c92dfb34e8c911c78467a21add +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Mesh/ARMeshConstants.cs b/Assets/ARDK/AR/Mesh/ARMeshConstants.cs new file mode 100644 index 0000000..ba2fcc0 --- /dev/null +++ b/Assets/ARDK/AR/Mesh/ARMeshConstants.cs @@ -0,0 +1,12 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.AR.Mesh +{ + public static class ARMeshConstants + { + public const int INTS_PER_BLOCK = 6; + public const int FLOATS_PER_VERTEX = 6; + public const int VECTORS_PER_VERTEX = 2; + public const int INTS_PER_FACE = 3; + } +} diff --git a/Assets/ARDK/AR/Mesh/ARMeshConstants.cs.meta b/Assets/ARDK/AR/Mesh/ARMeshConstants.cs.meta new file mode 100644 index 0000000..224d5b8 --- /dev/null +++ b/Assets/ARDK/AR/Mesh/ARMeshConstants.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f7b78d7bd4e44756893f5d4f7809c484 +timeCreated: 1614303277 \ No newline at end of file diff --git a/Assets/ARDK/AR/Mesh/FileARMesh.cs b/Assets/ARDK/AR/Mesh/FileARMesh.cs new file mode 100644 index 0000000..9865cce --- /dev/null +++ b/Assets/ARDK/AR/Mesh/FileARMesh.cs @@ -0,0 +1,67 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System.Collections.Generic; + +using Niantic.ARDK.Utilities; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Mesh +{ + public class FileARMesh: + IARMesh + { + public float MeshBlockSize + { + get { return _dataParser.MeshBlockSize; } + } + public int MeshVersion + { + get { return _dataParser.MeshVersion; } + } + + public int MeshBlockCount + { + get { return _dataParser.MeshBlockCount; } + } + + public int MeshVertexCount + { + get { return _dataParser.MeshVertexCount; } + } + + public int MeshFaceCount + { + get { return _dataParser.MeshFaceCount; } + } + + public event ArdkEventHandler MeshBlocksUpdated + { + add { _dataParser.MeshBlocksUpdated += value; } + remove { _dataParser.MeshBlocksUpdated -= value; } + } + + public event ArdkEventHandler MeshBlocksCleared + { + add { _dataParser.MeshBlocksCleared += value; } + remove { _dataParser.MeshBlocksCleared -= value; } + } + + public IReadOnlyDictionary Blocks + { + get { return _dataParser.Blocks; } + } + + private _MeshDataParser _dataParser; + + public FileARMesh(string path) + { + _dataParser = new _MeshDataParser(); + var data = new _FileARMeshData(path); + + if (data.Valid) + { + _dataParser.ParseMesh(data); + } + } + } +} diff --git a/Assets/ARDK/AR/Mesh/FileARMesh.cs.meta b/Assets/ARDK/AR/Mesh/FileARMesh.cs.meta new file mode 100644 index 0000000..d26d863 --- /dev/null +++ b/Assets/ARDK/AR/Mesh/FileARMesh.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5e29f9b7507b4cec817893d85d873de0 +timeCreated: 1631547426 \ No newline at end of file diff --git a/Assets/ARDK/AR/Mesh/IARMesh.cs b/Assets/ARDK/AR/Mesh/IARMesh.cs new file mode 100644 index 0000000..dfbb589 --- /dev/null +++ b/Assets/ARDK/AR/Mesh/IARMesh.cs @@ -0,0 +1,43 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System.Collections.Generic; + +using Niantic.ARDK.Utilities; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Mesh +{ + /// Represents an updating dense mesh of the environment, split into "blocks." Blocks are + /// updated as new areas are scanned and/or ARDK refines its understanding of already + /// scanned areas. + public interface IARMesh + { + /// Informs subscribers whenever mesh blocks have been added, removed, and/or their geometry has + /// been updated. + event ArdkEventHandler MeshBlocksUpdated; + + /// Informs subscribers whenever the mesh has been cleared, such as when the session is + /// re-run with the option to clear the mesh. + event ArdkEventHandler MeshBlocksCleared; + + /// The collection of blocks that make up the mesh. Each block is of equal size and has + /// self-contained arrays of vertices and faces (triangles). + IReadOnlyDictionary Blocks { get; } + + /// Size of a mesh block in meters in the last parsed mesh. + float MeshBlockSize { get; } + + /// Version of the last parsed mesh. + int MeshVersion { get; } + + /// Number of blocks in the last parsed mesh. Each block is represented + /// by a separate GameObject, which is an instance of _meshPrefab. + int MeshBlockCount { get; } + + /// Number of vertices in the most recently parsed mesh. + int MeshVertexCount { get; } + + /// Number of faces (polygons) in the last parsed mesh. + int MeshFaceCount { get; } + } +} diff --git a/Assets/ARDK/AR/Mesh/IARMesh.cs.meta b/Assets/ARDK/AR/Mesh/IARMesh.cs.meta new file mode 100644 index 0000000..8952fe1 --- /dev/null +++ b/Assets/ARDK/AR/Mesh/IARMesh.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 37a0bf66ef9c340659d436039920a614 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Mesh/MeshBlock.cs b/Assets/ARDK/AR/Mesh/MeshBlock.cs new file mode 100644 index 0000000..62c1987 --- /dev/null +++ b/Assets/ARDK/AR/Mesh/MeshBlock.cs @@ -0,0 +1,55 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using Unity.Collections; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Mesh +{ + /// A cube-shaped portion of the mesh of the environment. + public class MeshBlock + { + /// The version number of this specific block. + public int Version { get; internal set; } = -1; + + /// The version of the mesh that this block was last updated from. + public int MeshVersion { get; internal set; } = -1; + + /// The last block-specific Version that this block had its collider updated at. + /// Not set by the provider, besides to leave it at -1 initially. The consumer then uses this to + /// track their own work. + public int ColliderVersion { get; internal set; } = -1; + + /// The vertices associated with this mesh block. This array will only be valid until the next + /// frame when the _MeshDataParser updates, when this value will also be updated to once again + /// point to a valid array. If the mesh as a whole updated but this block didn't, then there + /// won't be an associated _MeshBlockParser.MeshBlockUpdated call but this value will still + /// update to point to a valid array with the same contents. It is strongly recommended never to + /// store these values, and always access them through the MeshBlock. If you do need access to + /// old values you need to create a managed copy of the array. + /// If the _MeshDataParser is not configured to provide block data, or if it has been Disposed, + /// this will be a default NativeArray whose IsCreated property will be false. + public NativeArray Vertices; + + /// The normals associated with this mesh block, sharing indices with the Vertices array. It is + /// valid when the Vertices array is valid, see that variable's comments for details. + public NativeArray Normals; + + /// The triangle indices associated with this mesh block. Each triple of values are 3 indices + /// into the Vertices/Normals arrays defining a triangle. It is valid when the Vertices array is + /// valid, see that variable's comments for details. + public NativeArray Triangles; + + /// The Unity mesh created from the Vertices, Normals, and Triangles data. This value will + /// be null until set by a consumer of the MeshBlocks provided by IARSession.Mesh, + /// such as the ARMeshManager component. + public UnityEngine.Mesh Mesh; + + internal void ClearArrays() + { + Vertices = new NativeArray(); + Normals = new NativeArray(); + Triangles = new NativeArray(); + } + } +} + diff --git a/Assets/ARDK/AR/Mesh/MeshBlock.cs.meta b/Assets/ARDK/AR/Mesh/MeshBlock.cs.meta new file mode 100644 index 0000000..956ad0b --- /dev/null +++ b/Assets/ARDK/AR/Mesh/MeshBlock.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a6238fd1d3524894a246f78be72f6ebe +timeCreated: 1629744102 \ No newline at end of file diff --git a/Assets/ARDK/AR/Mesh/MeshBlocksClearedArgs.cs b/Assets/ARDK/AR/Mesh/MeshBlocksClearedArgs.cs new file mode 100644 index 0000000..9f60e72 --- /dev/null +++ b/Assets/ARDK/AR/Mesh/MeshBlocksClearedArgs.cs @@ -0,0 +1,10 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.AR.Mesh +{ + public class MeshBlocksClearedArgs: + IArdkEventArgs + { + } +} diff --git a/Assets/ARDK/AR/Mesh/MeshBlocksClearedArgs.cs.meta b/Assets/ARDK/AR/Mesh/MeshBlocksClearedArgs.cs.meta new file mode 100644 index 0000000..e829c9b --- /dev/null +++ b/Assets/ARDK/AR/Mesh/MeshBlocksClearedArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2258869ffe31143ca991e68bd6ba593b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Mesh/MeshBlocksUpdatedArgs.cs b/Assets/ARDK/AR/Mesh/MeshBlocksUpdatedArgs.cs new file mode 100644 index 0000000..f923d79 --- /dev/null +++ b/Assets/ARDK/AR/Mesh/MeshBlocksUpdatedArgs.cs @@ -0,0 +1,30 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System.Collections.Generic; + +using Niantic.ARDK.Utilities; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Mesh +{ + public class MeshBlocksUpdatedArgs: + IArdkEventArgs + { + internal MeshBlocksUpdatedArgs + ( + IReadOnlyCollection blocksUpdated, + IReadOnlyCollection blocksObsoleted, + IARMesh mesh + ) + { + BlocksUpdated = blocksUpdated; + BlocksObsoleted = blocksObsoleted; + Mesh = mesh; + } + + public IReadOnlyCollection BlocksUpdated { get; private set; } + public IReadOnlyCollection BlocksObsoleted { get; private set; } + + public IARMesh Mesh { get; private set; } + } +} diff --git a/Assets/ARDK/AR/Mesh/MeshBlocksUpdatedArgs.cs.meta b/Assets/ARDK/AR/Mesh/MeshBlocksUpdatedArgs.cs.meta new file mode 100644 index 0000000..98b77db --- /dev/null +++ b/Assets/ARDK/AR/Mesh/MeshBlocksUpdatedArgs.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 92a267d5f97d4a3585304179ce1be2a9 +timeCreated: 1627688044 \ No newline at end of file diff --git a/Assets/ARDK/AR/Mesh/_FileARMeshData.cs b/Assets/ARDK/AR/Mesh/_FileARMeshData.cs new file mode 100644 index 0000000..f88b7e4 --- /dev/null +++ b/Assets/ARDK/AR/Mesh/_FileARMeshData.cs @@ -0,0 +1,190 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text.RegularExpressions; + +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Mesh +{ + internal sealed class _FileARMeshData: _IARMeshData + { + private static readonly byte[] _magicWord = new byte[] + { + // 6 D B L O C K M E S H _ _ _ _ _ + 0x36, 0x44, 0x42, 0x4C, 0x4F, 0x43, 0x4B, 0x4D, 0x45, 0x53, 0x48, 0x0, 0x0, 0x0, 0x0, 0x0 + }; + + public static byte[] MagicWord + { + get + { + return _magicWord; + } + } + + private readonly string _path; + private int _version; + private bool _read = false; + private bool _valid = false; + private int _blockBufferSize; + private int _vertexBufferSize; + private int _faceBufferSize; + private float _meshBlockSize; + + public _FileARMeshData(string path) + { + _path = path; + if (_path != null) + { + // Extract the version number from the file name + var filename = Path.GetFileName(path); + var versionMatch = Regex.Match(filename, @"\d+"); + if (versionMatch.Success) + { + _version = int.Parse(versionMatch.Value); + } + } + } + + public void Dispose() + { + } + + public bool Valid + { + get + { + ValidateFile(); + return _valid; + } + } + + public float MeshBlockSize + { + get + { + return _meshBlockSize; + } + } + + public int GetBlockMeshInfo + ( + out int blockBufferSizeOut, + out int vertexBufferSizeOut, + out int faceBufferSizeOut + ) + { + if (!Valid) + { + blockBufferSizeOut = 0; + vertexBufferSizeOut = 0; + faceBufferSizeOut = 0; + return 0; + } + + blockBufferSizeOut = _blockBufferSize; + vertexBufferSizeOut = _vertexBufferSize; + faceBufferSizeOut = _faceBufferSize; + return _version; + } + + public int GetBlockMesh + ( + IntPtr blockBuffer, + IntPtr vertexBuffer, + IntPtr faceBuffer, + int blockBufferSize, + int vertexBufferSize, + int faceBufferSize + ) + { + if (!Valid) + return -1; + + // sanity check + if (blockBufferSize < _blockBufferSize || + vertexBufferSize < _vertexBufferSize || + faceBufferSize < _faceBufferSize) + { + ARLog._Error("Buffer size too small to fit all mesh data."); + return -1; + } + + using (var file = File.Open(_path, FileMode.Open)) + { + using (var reader = new BinaryReader(file)) + { + // skip the file header + reader.ReadBytes(32); + var blockBufferLength = _blockBufferSize * sizeof(Int32); + var vertexBufferLength = _vertexBufferSize * sizeof(float); + var faceBufferLength = _faceBufferSize * sizeof(Int32); + + // read & copy block buffer + var blockBytes = reader.ReadBytes(blockBufferLength); + Marshal.Copy(blockBytes, 0, blockBuffer, blockBufferLength); + + // read & copy vertex buffer + var vertexBytes = reader.ReadBytes(vertexBufferLength); + Marshal.Copy(vertexBytes, 0, vertexBuffer, vertexBufferLength); + + // read & copy face buffer + var faceBytes = reader.ReadBytes(faceBufferLength); + Marshal.Copy(faceBytes, 0, faceBuffer, faceBufferLength); + } + } + + // return count of successfully read blocks + return _blockBufferSize / ARMeshConstants.INTS_PER_BLOCK; + } + + private void ValidateFile() + { + if (_read) + return; + + _read = true; + + using (var file = File.Open(_path, FileMode.Open)) + { + if (!file.CanRead) + { + _valid = false; + return; + } + + var reader = new BinaryReader(file); + try + { + var magicWord = reader.ReadBytes(MagicWord.Length); + if (!magicWord.SequenceEqual(MagicWord)) + { + _valid = false; + return; + } + + _blockBufferSize = reader.ReadInt32(); + _vertexBufferSize = reader.ReadInt32(); + _faceBufferSize = reader.ReadInt32(); + _meshBlockSize = reader.ReadSingle(); + } + catch + { + _valid = false; + reader.Close(); + return; + } + + var fileSize = 32 + (_blockBufferSize + _vertexBufferSize + _faceBufferSize) * sizeof(Int32); + _valid = file.Length >= fileSize; + reader.Close(); + } + } + } +} diff --git a/Assets/ARDK/AR/Mesh/_FileARMeshData.cs.meta b/Assets/ARDK/AR/Mesh/_FileARMeshData.cs.meta new file mode 100644 index 0000000..147f5fc --- /dev/null +++ b/Assets/ARDK/AR/Mesh/_FileARMeshData.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 4c6ccb842ade4c09bfa1882c563f92ff +timeCreated: 1601678069 \ No newline at end of file diff --git a/Assets/ARDK/AR/Mesh/_IARMeshData.cs b/Assets/ARDK/AR/Mesh/_IARMeshData.cs new file mode 100644 index 0000000..f7adce8 --- /dev/null +++ b/Assets/ARDK/AR/Mesh/_IARMeshData.cs @@ -0,0 +1,110 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +namespace Niantic.ARDK.AR.Mesh +{ + /// Represents a dense mesh. + /// This type of mesh is split into "blocks", which are cubes of equal size each containing the + /// vertices and faces (triangles) of the total world mesh between their boundaries. + /// The mesh is made of: + /// - a block size, which is the length of a side of the cube + /// - a version number, starting at zero + /// - a blocks buffer, indexing the mesh data by area. + /// - vertex and face (index) buffers. + /// + /// LAYOUT: + /// The block buffer is a flat array of 32bit integers in a sequence + /// Each block is defined by 6 back-to-back integers: + /// - (X, Y, Z) block coordinates + /// (0, 0, 0) is the coordinates of the block containing vertices and faces + /// between 0.0 and BLOCK_SIZE on every axis; + /// (-1, -1, -1) is the block containing vertices and faces + /// between -BLOCK_SIZE and 0.0 on every axis. + /// - a vertex count + /// - a face count + /// - a version number, which is equal to the mesh version for which the block was last updated. + /// The version number is to be used by applications to avoid updating unchanged mesh blocks. + /// + /// The vertex buffer is a flat array of single precision floats in a sequence. + /// The first half of the buffer, starting from 0, + /// contains all the vertex coordinates back to back: + /// X Y Z X Y Z X Y Z X Y Z etc. (3 floats per vertex) + /// The second half of the buffer, starting from vertexBufferSize/2, + /// contains all the vertex normal vectors back to back: + /// NX NY NZ NX NY NZ NX NY NZ etc. (3 floats per vertex) + /// The vertex buffer is organized in the same order as the block buffer. + /// + /// The face buffer is a flat array of 32bit integers in a sequence. + /// Each face is made of three indices, facing only one side (the one you'd see if the three + /// vertices are listed in counter-clockwise order). + /// The indices are global to the whole mesh and do not reset to zero for each block, making it + /// easy to consolidate multiple (or all) blocks into a single mesh object. + /// + /// EXAMPLE: + /// In this example, we'll have 2 blocks of 1 meter, containing 3 vertices and 1 face each. + /// The first block will be at (0, 0, 0) and the second block will be at (1, 0, 0), both + /// will start at version 0. + /// This mesh describes two triangles side by side on a flat plane: ΔΔ + /// + /// Block Buffer (12 int32s): + /// 0 0 0 3 1 0 // first block + /// 1 0 0 3 1 0 // second block + /// Vertex Buffer (36 floats): + /// 0.5 0.0 1.0 0.0 0.0 0.0 1.0 0.0 0.0 // first block vertex positions + /// 1.5 0.0 1.0 1.0 0.0 0.0 2.0 0.0 0.0 // second block vertex positions + /// 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 // first block vertex normals + /// 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 // second block vertex normals + /// Face buffer (6 int32s): + /// 0 1 2 // first block face + /// 3 4 5 // second block face + /// + /// In live data, blocks are expected to have thousands of vertices and faces each. + internal interface _IARMeshData: + IDisposable + { + /// The mesh block size, in meters. + /// It is used to easily find (through Euclidean division) the integer coordinates of a block + /// containing any vertex. + float MeshBlockSize { get; } + + /// Lightweight function to obtain mesh info without pulling all the data. + /// The function returns a version number, which is to be used by applications to avoid updating + /// unchanged meshes. + /// You have to provide 3 integers as parameters, which will be overwritten, returning the size + /// of buffers to be passed to GetBlockMesh(). + /// @param blockBufferSizeOut number of 32bit ints in the block buffer. + /// @param vertexBufferSizeOut number of single precision floats in the vertex buffer. + /// @param faceBufferSizeOut number of 32bit ints in the face (index) buffer. + /// @returns the version number of the mesh starting from 0; -1 if no mesh is available. + int GetBlockMeshInfo + ( + out int blockBufferSizeOut, + out int vertexBufferSizeOut, + out int faceBufferSizeOut + ); + + /// "Expensive" function to obtain mesh data. + /// Applications are expected to allocate buffers of the appropriate size (as dictated + /// by GetBlockMeshInfo()) and pass pointers to the buffers to this function to receive it. + /// The native implementation of this function is a memcpy of a few megabytes, + /// depending on the mesh size. + /// @param blockBuffer pointer to the block buffer. + /// @param vertexBuffer pointer to the vertex buffer. + /// @param faceBuffer pointer to the face buffer. + /// @param blockBufferSize size of the block buffer in 32bit integers. + /// @param vertexBufferSize size of the vertex buffer in single precision floats. + /// @param faceBufferSize size of the face buffer in 32bit integers. + /// @returns the number of blocks copied to the buffers (blockBufferSize/6) if the call is + /// successful; -1 if no mesh is available or if buffers are not large enough. + int GetBlockMesh + ( + IntPtr blockBuffer, + IntPtr vertexBuffer, + IntPtr faceBuffer, + int blockBufferSize, + int vertexBufferSize, + int faceBufferSize + ); + } +} diff --git a/Assets/ARDK/AR/Mesh/_IARMeshData.cs.meta b/Assets/ARDK/AR/Mesh/_IARMeshData.cs.meta new file mode 100644 index 0000000..04c0df6 --- /dev/null +++ b/Assets/ARDK/AR/Mesh/_IARMeshData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 34c98272cb6ee4f2ba2c2afbccc7d882 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Mesh/_MeshDataParser.cs b/Assets/ARDK/AR/Mesh/_MeshDataParser.cs new file mode 100644 index 0000000..ad36579 --- /dev/null +++ b/Assets/ARDK/AR/Mesh/_MeshDataParser.cs @@ -0,0 +1,413 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Runtime.InteropServices; + +using Niantic.ARDK.AR.ARSessionEventArgs; +using Niantic.ARDK.Extensions.Meshing; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Logging; + +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Mesh +{ + internal class _MeshDataParser: IARMesh, IDisposable + { + /// Size of a mesh block in meters in the last parsed mesh. + public float MeshBlockSize { get; private set; } + + /// Version of the last parsed mesh. + public int MeshVersion { get; private set; } + + /// Number of blocks in the last parsed mesh. Each block is represented + /// by a separate GameObject, which is an instance of _meshPrefab. + public int MeshBlockCount { get; private set; } + + /// Number of vertices in the most recently parsed mesh. + public int MeshVertexCount { get; private set; } + + /// Number of faces (polygons) in the last parsed mesh. + public int MeshFaceCount { get; private set; } + + // buffers + private NativeArray _blockArray; + private NativeArray _faceArray; + private NativeArray _unshiftedFaceArray; + private NativeArray _vertexArray; + + private Dictionary _blocks = new Dictionary(); + + public event ArdkEventHandler MeshBlocksUpdated; + public event ArdkEventHandler MeshBlocksCleared; + + public IReadOnlyDictionary Blocks { get; } + + public _MeshDataParser() + { + Blocks = new ReadOnlyDictionary(_blocks); + } + + /// Processes the raw data in the given mesh and updates mesh blocks if needed. + public void ParseMesh(_IARMeshData meshData) + { + var version = + meshData.GetBlockMeshInfo + ( + out int blockBufferSize, + out int vertexBufferSize, + out int faceBufferSize + ); + + var canUpdate = + blockBufferSize > 0 && + vertexBufferSize > 0 && + faceBufferSize > 0; + + if (canUpdate) + { + // Update mesh info + MeshBlockSize = meshData.MeshBlockSize; + MeshVersion = version; + MeshBlockCount = blockBufferSize / ARMeshConstants.INTS_PER_BLOCK; + MeshVertexCount = vertexBufferSize / ARMeshConstants.FLOATS_PER_VERTEX; + MeshFaceCount = faceBufferSize / ARMeshConstants.INTS_PER_FACE; + + ResizeArraysIfNeeded(blockBufferSize, vertexBufferSize, faceBufferSize); + UpdateMeshBlocks(meshData, blockBufferSize, vertexBufferSize, faceBufferSize); + } + else + { + ARLog._Warn("Invalid mesh data length."); + } + } + + // Recreate native buffers if the new mesh contains more blocks + private void ResizeArraysIfNeeded(int blockBufferSize, int vertexBufferSize, int faceBufferSize) + { + if (!_blockArray.IsCreated) + { + // If the block array isn't created, that means all arrays weren't created + + _blockArray = new NativeArray(blockBufferSize * 2, Allocator.Persistent); + _vertexArray = new NativeArray(vertexBufferSize * 2, Allocator.Persistent); + _faceArray = new NativeArray(faceBufferSize * 2, Allocator.Persistent); + _unshiftedFaceArray = new NativeArray(faceBufferSize * 2, Allocator.Persistent); + return; + } + + if (blockBufferSize > _blockArray.Length) + { + _blockArray.Dispose(); + _blockArray = new NativeArray(blockBufferSize * 2, Allocator.Persistent); + } + + if (vertexBufferSize > _vertexArray.Length) + { + _vertexArray.Dispose(); + _vertexArray = new NativeArray(vertexBufferSize * 2, Allocator.Persistent); + } + + if (faceBufferSize > _faceArray.Length) + { + _faceArray.Dispose(); + _faceArray = new NativeArray(faceBufferSize * 2, Allocator.Persistent); + + _unshiftedFaceArray.Dispose(); + _unshiftedFaceArray = new NativeArray(faceBufferSize * 2, Allocator.Persistent); + } + } + + // Scratch lists for both the updated and obsolete blocks used by UpdateMeshBlocks. + private readonly List _updatedBlocksScratch = new List(); + private readonly List _obsoleteBlocksScratch = new List(); + + // Obtains the mesh buffers and parses them, updating individual mesh blocks if their + // version number is newer than the current one. + // Raises the MeshBlocksUpdated event if mesh objects were successfully updated + private void UpdateMeshBlocks + ( + _IARMeshData meshData, + int blockBufferSize, + int vertexBufferSize, + int faceBufferSize + ) + { + // In the unlikely event that a race condition occured and the buffers are not the right size, + // just skip this update and wait for the next one. + if (!GetBlocksAndValidateSize(meshData, blockBufferSize, vertexBufferSize, faceBufferSize)) + return; + + _updatedBlocksScratch.Clear(); + + int verticesStart = 0; + int normalsStart = vertexBufferSize / 2; // normals start halfway through the buffer + int facesStart = 0; + + // Update all the full blocks returned by the API + const int floatsPerVertexVector = ARMeshConstants.FLOATS_PER_VERTEX / ARMeshConstants.VECTORS_PER_VERTEX; + for (int b = 0; b < blockBufferSize; b += ARMeshConstants.INTS_PER_BLOCK) + { + var currentBlock = + GetOrCreateBlockWithInfo + ( + b, + out Vector3Int blockCoords, + out int vertexCount, // number of vertices (each consisting of 3 floats) + out int faceCount, // number of faces (each consisting of 3 floats) + out int blockVersion + ); + + currentBlock.MeshVersion = MeshVersion; + + // If a block was obsoleted, all blocks' views into the block/face/vertex native arrays, + // have to be updated. It's only updating alias' into existing data, so it's not too + // terribly inefficient. + + // Turn number of vectors into number of floats + var numFloatsForAllVectors = vertexCount * floatsPerVertexVector; + var numFloatsForAllFaces = faceCount * ARMeshConstants.INTS_PER_FACE; + + // Have to update geometry for every block in case obsoleted blocks + // have affected the block offsets in the native arrays. + UpdateBlockGeometry + ( + currentBlock, + verticesStart, + numFloatsForAllVectors, + normalsStart, + numFloatsForAllVectors, + facesStart, + numFloatsForAllFaces + ); + + // Only surface block update in event if it actually updated + if (currentBlock.Version < blockVersion) + { + currentBlock.Version = blockVersion; + _updatedBlocksScratch.Add(blockCoords); + } + + verticesStart += numFloatsForAllVectors; + normalsStart += numFloatsForAllVectors; + facesStart += numFloatsForAllFaces; + } + + // Clean up obsolete blocks + RemoveObsoleteBlocks(_obsoleteBlocksScratch); + + MeshBlocksUpdated?.Invoke + ( + new MeshBlocksUpdatedArgs(_updatedBlocksScratch, _obsoleteBlocksScratch, this) + ); + } + + private bool GetBlocksAndValidateSize + ( + _IARMeshData meshData, + int blockBufferSize, + int vertexBufferSize, + int faceBufferSize + ) + { + // Get all the blocks and validate the counts are correct + int fullBlocksCount; + unsafe + { + var blockBufferPtr = _blockArray.GetUnsafePtr(); + var vertexBufferPtr = _vertexArray.GetUnsafePtr(); + var faceBufferPtr = _unshiftedFaceArray.GetUnsafePtr(); + + fullBlocksCount = + meshData.GetBlockMesh + ( + (IntPtr)blockBufferPtr, + (IntPtr)vertexBufferPtr, + (IntPtr)faceBufferPtr, + blockBufferSize, + vertexBufferSize, + faceBufferSize + ); + + _faceArray.CopyFrom(_unshiftedFaceArray); + } + + if (fullBlocksCount < 0) + { + ARLog._Error("Error getting mesh data, will not update the mesh."); + return false; + } + + if (fullBlocksCount == 0) + { + ARLog._Error("Mesh data provided an empty mesh, will not update."); + return false; + } + + var gotAllBlocks = fullBlocksCount == MeshBlockCount; + if (!gotAllBlocks) + { + ARLog._ErrorFormat + ( + "IARMesh.GetBlockMesh() returned {0} full blocks, expected {1}.", + fullBlocksCount, + MeshBlockCount + ); + + return false; + } + + return true; + } + + private MeshBlock GetOrCreateBlockWithInfo + ( + int startIndex, + out Vector3Int blockCoords, + out int vertexCount, + out int faceCount, + out int blockVersion + ) + { + blockCoords = + new Vector3Int + ( + _blockArray[startIndex], + _blockArray[startIndex + 1], + _blockArray[startIndex + 2] + ); + + vertexCount = _blockArray[startIndex + 3]; + faceCount = _blockArray[startIndex + 4]; + blockVersion = _blockArray[startIndex + 5]; + + if (!_blocks.TryGetValue(blockCoords, out MeshBlock block)) + { + block = new MeshBlock(); + _blocks[blockCoords] = block; + } + + return block; + } + + const int FloatSize = sizeof(float); + + // End indices are exclusive + private void UpdateBlockGeometry + ( + MeshBlock block, + int verticesStart, + int verticesCount, + int normalsStart, + int normalsCount, + int facesStart, + int facesCount + ) + { + var blockFaces = _faceArray.GetSubArray(facesStart, facesCount); + + // Update the vertex index for the triangles to be relative to the blockVertices array rather + // than the whole vertex array. + var firstVertexOffset = verticesStart / 3; + for (int i = 0; i < blockFaces.Length; i++) + { + blockFaces[i] -= firstVertexOffset; + } + + block.Triangles = blockFaces; + block.Vertices = _vertexArray.GetSubArray(verticesStart, verticesCount).Reinterpret(FloatSize); + block.Normals = _vertexArray.GetSubArray(normalsStart, normalsCount).Reinterpret(FloatSize); + } + + // Both remove obsolete blocks and fill a List with all the blocks that were removed. + private void RemoveObsoleteBlocks(List blocksThatWereObsoleted) + { + // Always clear out the scratch at the start so that no previous state could corrupt this + // call. Clearing won't change the Capacity of the List, so this will prevent us needing any + // allocations unless the List size needs to be increased. + blocksThatWereObsoleted.Clear(); + foreach (Vector3Int blockCoords in _blocks.Keys) + { + var block = _blocks[blockCoords]; + if (block.MeshVersion != MeshVersion) + blocksThatWereObsoleted.Add(blockCoords); + } + + foreach (Vector3Int blockCoords in blocksThatWereObsoleted) + _blocks.Remove(blockCoords); + } + + public void Clear() + { + MeshVersion = 0; + MeshBlockCount = 0; + MeshVertexCount = 0; + MeshFaceCount = 0; + + foreach (var kv in _blocks) + { + kv.Value.ClearArrays(); + } + + _blocks.Clear(); + + if (_blockArray.IsCreated) + _blockArray.Dispose(); + + if (_faceArray.IsCreated) + _faceArray.Dispose(); + + if (_unshiftedFaceArray.IsCreated) + _unshiftedFaceArray.Dispose(); + + if (_vertexArray.IsCreated) + _vertexArray.Dispose(); + + MeshBlocksCleared?.Invoke(new MeshBlocksClearedArgs()); + } + + public void Dispose() + { + Clear(); + } + + public byte[] GetSerializedBlockArray() + { + var validSlice = _blockArray.GetSubArray(0, MeshBlockCount * ARMeshConstants.INTS_PER_BLOCK); + return validSlice.Reinterpret(sizeof(Int32)).ToArray(); + } + + public byte[] GetSerializedFaceArray() + { + var validSlice = _unshiftedFaceArray.GetSubArray(0, MeshFaceCount * ARMeshConstants.INTS_PER_FACE); + return validSlice.Reinterpret(sizeof(Int32)).ToArray(); + } + + public byte[] GetSerializedVertexArray() + { + var validSlice = _vertexArray.GetSubArray(0, MeshVertexCount * ARMeshConstants.FLOATS_PER_VERTEX); + return validSlice.Reinterpret(sizeof(float)).ToArray(); + } + + public NativeArray GetNativeBlockArray() + { + var validSlice = _blockArray.GetSubArray(0, MeshBlockCount * ARMeshConstants.INTS_PER_BLOCK); + return validSlice; + } + public NativeArray GetNativeVertexArray() + { + var validSlice = _vertexArray.GetSubArray(0, MeshVertexCount * ARMeshConstants.FLOATS_PER_VERTEX); + return validSlice; + } + public NativeArray GetNativeFaceArray() + { + var validSlice = _unshiftedFaceArray.GetSubArray(0, MeshFaceCount * ARMeshConstants.INTS_PER_FACE); + return validSlice; + } + } +} diff --git a/Assets/ARDK/AR/Mesh/_MeshDataParser.cs.meta b/Assets/ARDK/AR/Mesh/_MeshDataParser.cs.meta new file mode 100644 index 0000000..f8f64d9 --- /dev/null +++ b/Assets/ARDK/AR/Mesh/_MeshDataParser.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 0a664a432edd422bbc2a6c9bc01f5914 +timeCreated: 1618240354 \ No newline at end of file diff --git a/Assets/ARDK/AR/Mesh/_NativeARMeshData.cs b/Assets/ARDK/AR/Mesh/_NativeARMeshData.cs new file mode 100644 index 0000000..588f5d9 --- /dev/null +++ b/Assets/ARDK/AR/Mesh/_NativeARMeshData.cs @@ -0,0 +1,138 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Runtime.InteropServices; + +using Niantic.ARDK.Internals; + +namespace Niantic.ARDK.AR.Mesh +{ + internal sealed class _NativeARMeshData: + _IARMeshData + { + static _NativeARMeshData() + { + Platform.Init(); + } + + private IntPtr _nativeHandle; + + // Used to inform the C# GC that there is managed memory held by this object + // points + identifiers (estimating 200 points) + private const long _MemoryPressure = (200L * (3L * 4L)) + (200L * 8L); + + public _NativeARMeshData(IntPtr nativeHandle) + { + if (nativeHandle == IntPtr.Zero) + throw new ArgumentException("nativeHandle can't be Zero.", nameof(nativeHandle)); + + _nativeHandle = nativeHandle; + + GC.AddMemoryPressure(_MemoryPressure); + } + + private static void _ReleaseImmediate(IntPtr nativeHandle) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARMesh_Release(nativeHandle); + } + + ~_NativeARMeshData() + { + _ReleaseImmediate(_nativeHandle); + GC.RemoveMemoryPressure(_MemoryPressure); + } + + public void Dispose() + { + GC.SuppressFinalize(this); + + var nativeHandle = _nativeHandle; + if (nativeHandle != IntPtr.Zero) + { + _nativeHandle = IntPtr.Zero; + + _ReleaseImmediate(nativeHandle); + GC.RemoveMemoryPressure(_MemoryPressure); + } + } + + public float MeshBlockSize + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _NARMesh_GetMeshBlockSize(_nativeHandle); +#pragma warning disable 0162 + else + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + } + + public int GetBlockMeshInfo + ( + out int blockBufferSizeOut, + out int vertexBufferSizeOut, + out int faceBufferSizeOut + ) + { + blockBufferSizeOut = 0; + vertexBufferSizeOut = 0; + faceBufferSizeOut = 0; + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _NARMesh_GetBlockMeshInfo(_nativeHandle, + out blockBufferSizeOut, out vertexBufferSizeOut, out faceBufferSizeOut); +#pragma warning disable 0162 + else + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + + public int GetBlockMesh + ( + IntPtr blockBuffer, + IntPtr vertexBuffer, + IntPtr faceBuffer, + int blockBufferSize, + int vertexBufferSize, + int faceBufferSize + ) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _NARMesh_GetBlockMesh(_nativeHandle, + blockBuffer, vertexBuffer, faceBuffer, + blockBufferSize, vertexBufferSize, faceBufferSize); +#pragma warning disable 0162 + else + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARMesh_Release(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern float _NARMesh_GetMeshBlockSize + ( + IntPtr nativeHandle + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern int _NARMesh_GetBlockMeshInfo( + IntPtr nativeHandle, + out int blockBufferSizeOut, + out int vertexBufferSizeOut, + out int faceBufferSizeOut); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern int _NARMesh_GetBlockMesh( + IntPtr nativeHandle, + IntPtr blockBuffer, + IntPtr vertexBuffer, + IntPtr faceBuffer, + int blockBufferSize, + int vertexBufferSize, + int faceBufferSize); + } +} diff --git a/Assets/ARDK/AR/Mesh/_NativeARMeshData.cs.meta b/Assets/ARDK/AR/Mesh/_NativeARMeshData.cs.meta new file mode 100644 index 0000000..1f15221 --- /dev/null +++ b/Assets/ARDK/AR/Mesh/_NativeARMeshData.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a03ba0e71863445cab0abf4df4c1acb1 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Mesh/_SerializableARMeshData.cs b/Assets/ARDK/AR/Mesh/_SerializableARMeshData.cs new file mode 100644 index 0000000..d03fd33 --- /dev/null +++ b/Assets/ARDK/AR/Mesh/_SerializableARMeshData.cs @@ -0,0 +1,61 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.ObjectModel; +using System.Runtime.InteropServices; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Mesh +{ + [Serializable] + internal sealed class _SerializableARMeshData:_IARMeshData + { + internal _SerializableARMeshData + ( + float meshBlockSize + ) + { + MeshBlockSize = meshBlockSize; + } + + public float MeshBlockSize { get; private set; } + + void IDisposable.Dispose() + { + // Do nothing as this object is fully managed. + } + + private static readonly _SerializableARMeshData _EmptyMesh = new _SerializableARMeshData(0); + public static _SerializableARMeshData EmptyMesh() + { + return _EmptyMesh; + } + + public int GetBlockMeshInfo + ( + out int blockBufferSizeOut, + out int vertexBufferSizeOut, + out int faceBufferSizeOut + ) + { + blockBufferSizeOut = 0; + vertexBufferSizeOut = 0; + faceBufferSizeOut = 0; + return 0; + } + + public int GetBlockMesh + ( + IntPtr blockBuffer, + IntPtr vertexBuffer, + IntPtr faceBuffer, + int blockBufferSize, + int vertexBufferSize, + int faceBufferSize + ) + { + return 0; + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/AR/Mesh/_SerializableARMeshData.cs.meta b/Assets/ARDK/AR/Mesh/_SerializableARMeshData.cs.meta new file mode 100644 index 0000000..2cc76d2 --- /dev/null +++ b/Assets/ARDK/AR/Mesh/_SerializableARMeshData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 19ac2e46bdb4e4308b71e6e17ea84ead +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/NativeAccess.cs b/Assets/ARDK/AR/NativeAccess.cs new file mode 100644 index 0000000..bfef5b9 --- /dev/null +++ b/Assets/ARDK/AR/NativeAccess.cs @@ -0,0 +1,65 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +#if (UNITY_IOS || UNITY_ANDROID) && !UNITY_EDITOR +#define AR_NATIVE_ONLY +#endif + +using UnityEngine; + +namespace Niantic.ARDK.AR +{ + internal static class NativeAccess + { + public enum ModeType + { + // This means that native code should be run. + Native, + + // This means that instead of native code running, shims meant for unit tests should be used instead. + Testing, + + // This means that instead of native code running, nothing should be done, and if necessary a default value will be returned. + Disabled, + } + + // On production devices (android/iOS phones) only native methods are supported. + // Because this is a const variable, if statements checking it can be optimized out, meaning + // there is no overhead for using it to control whether native methods are called on those + // platforms. On other platforms we default to not making any native calls, but can switch to + // other behaviors when necessary. Unit tests can switch to the testing shims, and playback code + // can switch to native calls once playback has been set up. +#if AR_NATIVE_ONLY + public const ModeType Mode = ModeType.Native; +#else + private static ModeType _mode = ModeType.Disabled; + public static ModeType Mode + { + get + { + return _mode; + } + } +#endif + + public static void SwitchToNativeImplementation() + { +#if !AR_NATIVE_ONLY + _mode = ModeType.Native; +#endif + } + + public static void SwitchToTestingImplementation() + { +#if !AR_NATIVE_ONLY + _mode = ModeType.Testing; +#endif + } + + public static void SwitchToDefaultImplementation() + { +#if !AR_NATIVE_ONLY + _mode = ModeType.Disabled; +#endif + } + } +} diff --git a/Assets/ARDK/AR/NativeAccess.cs.meta b/Assets/ARDK/AR/NativeAccess.cs.meta new file mode 100644 index 0000000..d36f9ef --- /dev/null +++ b/Assets/ARDK/AR/NativeAccess.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c5251b8f6c9246b3afbf5bcd697eb2f9 +timeCreated: 1605044812 \ No newline at end of file diff --git a/Assets/ARDK/AR/Networking.meta b/Assets/ARDK/AR/Networking.meta new file mode 100644 index 0000000..8976431 --- /dev/null +++ b/Assets/ARDK/AR/Networking.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1004b02f6508142b7bbf90e2a6cfebe0 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Networking/ARNetworkingEventArgs.meta b/Assets/ARDK/AR/Networking/ARNetworkingEventArgs.meta new file mode 100644 index 0000000..cdeb279 --- /dev/null +++ b/Assets/ARDK/AR/Networking/ARNetworkingEventArgs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 55dbb86c343854958b80a6404ff4973e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Networking/ARNetworkingEventArgs/ARNetworkingDeinitializedArgs.cs b/Assets/ARDK/AR/Networking/ARNetworkingEventArgs/ARNetworkingDeinitializedArgs.cs new file mode 100644 index 0000000..c09a650 --- /dev/null +++ b/Assets/ARDK/AR/Networking/ARNetworkingEventArgs/ARNetworkingDeinitializedArgs.cs @@ -0,0 +1,11 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.AR.Networking.ARNetworkingEventArgs +{ + public struct ARNetworkingDeinitializedArgs: + IArdkEventArgs + { + } +} diff --git a/Assets/ARDK/AR/Networking/ARNetworkingEventArgs/ARNetworkingDeinitializedArgs.cs.meta b/Assets/ARDK/AR/Networking/ARNetworkingEventArgs/ARNetworkingDeinitializedArgs.cs.meta new file mode 100644 index 0000000..3ada680 --- /dev/null +++ b/Assets/ARDK/AR/Networking/ARNetworkingEventArgs/ARNetworkingDeinitializedArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0da06b621437a4e0f9ac9637629a8a5c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Networking/ARNetworkingEventArgs/AnyARNetworkingInitializedArgs.cs b/Assets/ARDK/AR/Networking/ARNetworkingEventArgs/AnyARNetworkingInitializedArgs.cs new file mode 100644 index 0000000..ab5f9bd --- /dev/null +++ b/Assets/ARDK/AR/Networking/ARNetworkingEventArgs/AnyARNetworkingInitializedArgs.cs @@ -0,0 +1,18 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.AR.Networking.ARNetworkingEventArgs +{ + public struct AnyARNetworkingInitializedArgs: + IArdkEventArgs + { + public AnyARNetworkingInitializedArgs(IARNetworking arNetworking): + this() + { + ARNetworking = arNetworking; + } + + public IARNetworking ARNetworking { get; private set; } + } +} diff --git a/Assets/ARDK/AR/Networking/ARNetworkingEventArgs/AnyARNetworkingInitializedArgs.cs.meta b/Assets/ARDK/AR/Networking/ARNetworkingEventArgs/AnyARNetworkingInitializedArgs.cs.meta new file mode 100644 index 0000000..ded82c1 --- /dev/null +++ b/Assets/ARDK/AR/Networking/ARNetworkingEventArgs/AnyARNetworkingInitializedArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f48071b5ec72e408795215ad6878223c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Networking/ARNetworkingEventArgs/PeerPoseReceivedArgs.cs b/Assets/ARDK/AR/Networking/ARNetworkingEventArgs/PeerPoseReceivedArgs.cs new file mode 100644 index 0000000..0367e44 --- /dev/null +++ b/Assets/ARDK/AR/Networking/ARNetworkingEventArgs/PeerPoseReceivedArgs.cs @@ -0,0 +1,23 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Networking; +using Niantic.ARDK.Utilities; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Networking.ARNetworkingEventArgs +{ + public struct PeerPoseReceivedArgs: + IArdkEventArgs + { + public PeerPoseReceivedArgs(IPeer peer, Matrix4x4 pose): + this() + { + Peer = peer; + Pose = pose; + } + + public IPeer Peer { get; private set; } + public Matrix4x4 Pose { get; private set; } + } +} diff --git a/Assets/ARDK/AR/Networking/ARNetworkingEventArgs/PeerPoseReceivedArgs.cs.meta b/Assets/ARDK/AR/Networking/ARNetworkingEventArgs/PeerPoseReceivedArgs.cs.meta new file mode 100644 index 0000000..6f9be6b --- /dev/null +++ b/Assets/ARDK/AR/Networking/ARNetworkingEventArgs/PeerPoseReceivedArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c0074577f21d343aea0e1af79f56c4d3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Networking/ARNetworkingEventArgs/PeerStateReceivedArgs.cs b/Assets/ARDK/AR/Networking/ARNetworkingEventArgs/PeerStateReceivedArgs.cs new file mode 100644 index 0000000..53c5c74 --- /dev/null +++ b/Assets/ARDK/AR/Networking/ARNetworkingEventArgs/PeerStateReceivedArgs.cs @@ -0,0 +1,21 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Networking; +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.AR.Networking.ARNetworkingEventArgs +{ + public struct PeerStateReceivedArgs: + IArdkEventArgs + { + public PeerStateReceivedArgs(IPeer peer, PeerState state): + this() + { + Peer = peer; + State = state; + } + + public IPeer Peer { get; private set; } + public PeerState State { get; private set; } + } +} diff --git a/Assets/ARDK/AR/Networking/ARNetworkingEventArgs/PeerStateReceivedArgs.cs.meta b/Assets/ARDK/AR/Networking/ARNetworkingEventArgs/PeerStateReceivedArgs.cs.meta new file mode 100644 index 0000000..7b8de69 --- /dev/null +++ b/Assets/ARDK/AR/Networking/ARNetworkingEventArgs/PeerStateReceivedArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 060da590b1d8a452986f04ec74e11482 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Networking/ARNetworkingFactory.cs b/Assets/ARDK/AR/Networking/ARNetworkingFactory.cs new file mode 100644 index 0000000..3643f64 --- /dev/null +++ b/Assets/ARDK/AR/Networking/ARNetworkingFactory.cs @@ -0,0 +1,320 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.ComponentModel; + +using Niantic.ARDK.AR.Networking.ARNetworkingEventArgs; +using Niantic.ARDK.VirtualStudio; +using Niantic.ARDK.VirtualStudio.AR; +using Niantic.ARDK.VirtualStudio.AR.Networking.Mock; +using Niantic.ARDK.VirtualStudio.Remote; +using Niantic.ARDK.VirtualStudio.Networking; +using Niantic.ARDK.VirtualStudio.Networking.Mock; +using Niantic.ARDK.Networking; +using Niantic.ARDK.Networking.MultipeerNetworkingEventArgs; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Logging; + +/// @namespace Niantic.ARDK.AR.Networking +/// @brief Handles AR Networking sessions +namespace Niantic.ARDK.AR.Networking +{ + /// A static Factory class to create ARNetworking instances, as well as to be notified when + /// new ARNetworking instances are created. + public static class ARNetworkingFactory + { + private static readonly object _arNetworkingLock = new object(); + private static IARNetworking _arNetworking; + + /// Create an ARNetworking appropriate for the current device. + /// + /// On a mobile device, the attempted order will be LiveDevice, Remote, and finally Mock. + /// In the Unity Editor, the attempted order will be Remote, then Mock. + /// + /// This will also create an ARSession object. If an ARSession object has already been created, + /// use the ARNetworkingFactory.Create(IARSession session) API instead. + /// + /// @param stageIdentifier + /// The identifier used by the C++ library to connect all related components. + /// + /// @returns The created ARNetworking, or throws if it was not possible to create a session. + public static IARNetworking Create() + { + return _Create(null); + } + + /// Create an ARNetworking with the specified RuntimeEnvironment. + /// + /// This will also create an ARSession object. If an ARSession object has already been created, + /// use the ARNetworkingFactory.Create(IARSession session) API instead. + /// + /// @param env + /// The env used to create the ARNetworking for. + /// + /// @returns The created ARNetworking, or throws if it was not possible to create a session. + public static IARNetworking Create(RuntimeEnvironment env) + { + return _Create(new List(){env}); + } + + /// Creates a new ARNetworking for the given session. + /// + /// @param session - The session to create a new ARNetworking for. + /// @returns The newly created ARNetworking. + public static IARNetworking Create(IARSession session) + { + var arNetworking = Create(session, ServerConfiguration.ARBE); + if (arNetworking == null) + throw new NotSupportedException("Could not create an ARNetworking with the provided ARSession"); + + return arNetworking; + } + + /// Creates a new ARNetworking for the given session. + /// + /// @param session - The session to create a new ARNetworking for. + /// @param configuration - The configuration that tells how to connect to a server. + /// + /// @returns The newly created ARNetworking. + public static IARNetworking Create(IARSession session, ServerConfiguration configuration) + { + if (session == null) + throw new ArgumentNullException(nameof(session)); + + var env = session.RuntimeEnvironment; + + var networking = MultipeerNetworkingFactory.Create(env, configuration, session.StageIdentifier); + return Create(session, networking); + } + + /// Creates a new ARNetworking for the given session and multipeer networking. + /// + /// @param session - The session to create a new ARNetworking for. + /// @param networking - An existing multipeer networking. + /// + /// @returns The newly created ARNetworking. + public static IARNetworking Create(IARSession session, IMultipeerNetworking networking) + { + if (session == null) + throw new ArgumentNullException(nameof(session)); + + if (networking == null) + throw new ArgumentNullException(nameof(networking)); + + var env = session.RuntimeEnvironment; + if (env != networking.RuntimeEnvironment) + throw new ArgumentException("session and networking must have the same RuntimeEnvironment."); + + IARNetworking result; + switch (env) + { + case RuntimeEnvironment.LiveDevice: + result = new _NativeARNetworking(session, networking); + _InvokeNetworkingInitialized(result, isLocal: true); + break; + + case RuntimeEnvironment.Remote: + result = new _RemoteEditorARNetworking(session, networking); + _InvokeNetworkingInitialized(result, isLocal: true); + break; + + case RuntimeEnvironment.Mock: + result = + _CreateVirtualStudioManagedARNetworking + ( + session, + networking, + _VirtualStudioManager.Instance, + isLocal: true + ); + + break; + + default: + throw new InvalidEnumArgumentException("session.RuntimeEnvironment", (int)env, env.GetType()); + } + + return result; + } + + private static ArdkEventHandler _arNetworkingInitialized; + + /// Event called when a new AR Networking object is initialized. + public static event ArdkEventHandler ARNetworkingInitialized + { + add + { + _StaticMemberValidator._FieldIsNullWhenScopeEnds(() => _arNetworkingInitialized); + + _arNetworkingInitialized += value; + + // Safe to read with no lock. + var arNetworking = _arNetworking; + if (arNetworking != null) + { + ARLog._Debug("Calling new ARNetworkingInitialized callback to catch up"); + + var args = new AnyARNetworkingInitializedArgs(arNetworking); + value(args); + } + } + remove + { + _arNetworkingInitialized -= value; + } + } + + /// Tries to create an ARNetworking of any of the given envs. + /// + /// @param envs + /// A collection of envs used to create the networking for. As not all platforms support + /// all envs, the code will try to create the networking for the first env, then for the + /// second and so on. If envs is null or empty, then the order used is LiveDevice, + /// Remote and finally Mock. + /// + /// @returns The created networking, or null if it was not possible to create the object. + internal static IARNetworking _Create(IEnumerable envs = null) + { + IARSession session; + try + { + session = ARSessionFactory._Create(envs); + } + catch (InvalidOperationException) + { + var errorMessage = + "The ARNetworkingFactory is trying to create an ARSession when one already exists, " + + "pass the existing ARSession into ARNetworkingFactory.Create(IARSession session)"; + + throw new InvalidOperationException(errorMessage); + } + + if (session == null) + throw new NotSupportedException("None of the provided runtime environments are supported by this build."); + + return Create(session); + } + + internal static IARNetworking _CreateVirtualStudioManagedARNetworking + ( + IARSession arSession, + IMultipeerNetworking networking, + _IVirtualStudioManager virtualStudioManager, + bool isLocal + ) + { + var env = arSession.RuntimeEnvironment; + if (env != networking.RuntimeEnvironment) + throw new ArgumentException("arSession and networking must have the same RuntimeEnvironment."); + + IARNetworking result; + + ARLog._DebugFormat + ( + "Making {0} ARNetworking", + objs: env + ); + + switch (env) + { + case RuntimeEnvironment.Mock: + result = new _MockARNetworking(arSession, networking, virtualStudioManager); + break; + + case RuntimeEnvironment.Remote: + result = new _RemoteEditorARNetworking(arSession, networking); + break; + + default: + throw new InvalidOperationException("Invalid or unknown RuntimeEnvironment: " + env); + } + + _InvokeNetworkingInitialized(result, isLocal); + return result; + } + + // As there is no ConcurrentHashSet, we use a ConcurrentDictionary and ignore the value. + private static readonly ConcurrentDictionary _nonLocalARNetworkings = + new ConcurrentDictionary(_ReferenceComparer.Instance); + + private static ArdkEventHandler + _nonLocalARNetworkingInitialized; + + internal static event + ArdkEventHandler NonLocalARNetworkingInitialized + { + add + { + _StaticMemberValidator._FieldIsNullWhenScopeEnds(() => _nonLocalARNetworkingInitialized); + + _nonLocalARNetworkingInitialized += value; + + // It is safe to iterate a ConcurrentDictionary even if items are added or removed during + // the iteration. + foreach (var arNetworking in _nonLocalARNetworkings.Keys) + { + ARLog._Debug("Calling new NonLocalARNetworkingInitialized callback to catch up"); + + var args = new AnyARNetworkingInitializedArgs(arNetworking); + value(args); + } + } + remove + { + _nonLocalARNetworkingInitialized -= value; + } + } + + private static void _InvokeNetworkingInitialized(IARNetworking arNetworking, bool isLocal) + { + ArdkEventHandler handler; + if (isLocal) + { + ARLog._Debug("Initializing a local ARNetworking"); + + _StaticMemberValidator._FieldIsNullWhenScopeEnds(() => _arNetworking); + + lock (_arNetworkingLock) + { + if (_arNetworking != null) + throw new InvalidOperationException("There's another ARNetworking still active."); + + _arNetworking = arNetworking; + } + + handler = _arNetworkingInitialized; + + arNetworking.Deinitialized += + (_) => + { + lock (_arNetworkingLock) + if (_arNetworking == arNetworking) + _arNetworking = null; + }; + } + else + { + ARLog._Debug("Initializing a non-local ARNetworking"); + + _StaticMemberValidator._CollectionIsEmptyWhenScopeEnds(() => _nonLocalARNetworkings); + + if (!_nonLocalARNetworkings.TryAdd(arNetworking, true)) + throw new InvalidOperationException("Duplicated ARNetworking."); + + handler = _nonLocalARNetworkingInitialized; + + arNetworking.Deinitialized += + (ignored) => _nonLocalARNetworkings.TryRemove(arNetworking, out _); + + } + + if (handler != null) + { + var args = new AnyARNetworkingInitializedArgs(arNetworking); + handler(args); + } + } + } +} diff --git a/Assets/ARDK/AR/Networking/ARNetworkingFactory.cs.meta b/Assets/ARDK/AR/Networking/ARNetworkingFactory.cs.meta new file mode 100644 index 0000000..b3e2e79 --- /dev/null +++ b/Assets/ARDK/AR/Networking/ARNetworkingFactory.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f7a9e67413004f49927fd04906f6120a +timeCreated: 1579051169 \ No newline at end of file diff --git a/Assets/ARDK/AR/Networking/IARNetworking.cs b/Assets/ARDK/AR/Networking/IARNetworking.cs new file mode 100644 index 0000000..f029394 --- /dev/null +++ b/Assets/ARDK/AR/Networking/IARNetworking.cs @@ -0,0 +1,139 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; + +using Niantic.ARDK.AR.Networking.ARNetworkingEventArgs; +using Niantic.ARDK.Networking; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Marker; + +using UnityEngine; + +namespace Niantic.ARDK.AR.Networking +{ + /// Possible states of local or remote peers in an ARNetworking session. + public enum PeerState + { + /// Initial state. Peers will exit this state after connecting to the server. + Unknown, + + /// Currently unused. Peers will never reach this state. + Initializing, + + /// Mapper: Trying to create a map. + /// Non-Mapper: Waiting to receive localization data. + WaitingForLocalizationData, + + /// Mapper: Will not reach this state. + /// Non-Mapper: Has received map data from the server and is attempting to localize. + Localizing, + + /// State is only reached when using MarkerSync + /// (i.e. when `IARNetworking.InitializeForMarkerScanning` has been called). + /// Mapper: Enters this state after exiting Unknown. + /// Non-Mapper: Has successfully localized through MarkerSync. + Stabilizing, + + /// Mapper: Has successfully created at least one map. + /// Non-Mapper: Has successfully localized against a map. + Stable, + + /// Currently unused. Peers will never reach this state. + Limited, + + /// Mapper: Will not reach this state. + /// Non-Mapper: If the mapper has left the ARNetworking session before publishing any maps, + /// all non-mapper peers that join afterward will enter this state after exiting Unknown. + Failed + } + + /// @note This is part of an experimental feature that is not advised to be used in release builds. + [Flags] + public enum MarkerScanOption + { + ScanToJoin = 0x1, + ScanToSync = 0x2, + } + + public interface IARNetworking: + IDisposable + { + /// A reference to the underlying MultipeerNetworking instance used to communicate with other + /// peers. + IMultipeerNetworking Networking { get; } + + /// A reference to the underlying ARSession object generating data used to synchronize with + /// other peers. + IARSession ARSession { get; } + + /// Latest poses received from each peer (excluding the local peer). + /// Peers will be removed from the dictionary when they leave the session. + IReadOnlyDictionary LatestPeerPoses { get; } + + /// Latest PeerStates received from each peer (including the local peer). + /// Peers will be removed from the dictionary when they leave the session + IReadOnlyDictionary LatestPeerStates { get; } + + /// Current localization state of the local peer. + PeerState LocalPeerState { get; } + + /// Enable broadcasting of the local peer pose. + void EnablePoseBroadcasting(); + + /// Disable broadcasting of the local peer pose. + void DisablePoseBroadcasting(); + + /// Set target latency (milliseconds) for broadcasting the local peer pose. + void SetTargetPoseLatency(Int64 targetPoseLatency); + + /// Sets up this ARNetworking session to be a MarkerScanning host. The peer calling + /// this method must be the host in an existing networking session. Only needs to be called + /// when using a marker for map syncing. + /// @note This is part of an experimental feature that is not advised to be used in release builds. + /// + /// Positions of the marker points that should be detected by + /// scanners in real-world space (unit: meters), relative to the center of the device's screen. + /// + void InitializeForMarkerScanning(Vector3[] markerPointLocations = null); + + /// Initiates and runs the process to scan for a marker and join a networking session and/or + /// sync maps using that marker. + /// @note This is part of an experimental feature that is not advised to be used in release builds. + /// + /// Configure to scan for a marker in order to join a networking session, + /// to sync maps, or to do both (in last case will first join, then sync when able). + /// + /// + /// Callback raised when a marker is properly scanned and parsed. + /// If both joining and syncing MarkerScanOption flags are enabled, the callback will + /// only be raised after the syncing metadata has been parsed. At the time of the callback + /// it is not guaranteed this ARNetworking has either joined or synced, so still use the + /// MultipeerNetworking.DidConnect and ARNetworking.DidReceiveStateFromPeer to verify those + /// statuses. + /// + /// + /// If null, will default to using an ARFrameScanner scanning for a ZXing barcode. + /// + /// + /// If null, will default to using BasicMetadataSerializer and + /// EmbeddedStationaryMetadataSerializer (if MarkerScanOption.ScanToJoin is flagged). + /// + void ScanForMarker + ( + MarkerScanOption options, + Action gotResult = null, + IMarkerScanner scanner = null, + IMetadataSerializer deserializer = null + ); + + /// Alerts subscribers when any peer's (including the local peer's) localization state has changed. + event ArdkEventHandler PeerStateReceived; + + /// Alerts subscribers when any peer's (excluding the local peer's) pose has changed. + event ArdkEventHandler PeerPoseReceived; + + /// Alerts subscribers when this object is deinitialized. + event ArdkEventHandler Deinitialized; + } +} diff --git a/Assets/ARDK/AR/Networking/IARNetworking.cs.meta b/Assets/ARDK/AR/Networking/IARNetworking.cs.meta new file mode 100644 index 0000000..f471e97 --- /dev/null +++ b/Assets/ARDK/AR/Networking/IARNetworking.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 2dadd5242fa44128a7c474986e60fcce +timeCreated: 1544649419 \ No newline at end of file diff --git a/Assets/ARDK/AR/Networking/MarkerScanCoordinator.cs b/Assets/ARDK/AR/Networking/MarkerScanCoordinator.cs new file mode 100644 index 0000000..e16a63f --- /dev/null +++ b/Assets/ARDK/AR/Networking/MarkerScanCoordinator.cs @@ -0,0 +1,231 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Text; + +using Niantic.ARDK.AR.Networking.ARNetworkingEventArgs; +using Niantic.ARDK.AR.SLAM; +using Niantic.ARDK.Networking; +using Niantic.ARDK.Networking.Clock; +using Niantic.ARDK.Networking.MultipeerNetworkingEventArgs; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Logging; +using Niantic.ARDK.Utilities.Marker; +using UnityEngine; + +namespace Niantic.ARDK.AR.Networking +{ + internal sealed class MarkerScanCoordinator: + IDisposable + { + public event Action Finished; + + private readonly IARNetworking _arNetworking; + + private IMarkerSyncer _markerSyncer; + private IMarkerScanner _markerScanner; + + private IMetadataSerializer _metadataSerializer; + private MarkerMetadata _cachedMetadata; + + private MarkerScanOption _activeScanOptions; + private Action _finalResultCallback; + + public MarkerScanCoordinator(IARNetworking arNetworking, IMarkerSyncer syncer = null) + { + _arNetworking = arNetworking; + _markerSyncer = syncer ?? new NativeMarkerSyncer(arNetworking.Networking.StageIdentifier); + } + + ~MarkerScanCoordinator() + { + ARLog._Error("MarkerScanCoordinator should be destroyed by an explicit call to Dispose()."); + } + + public void Dispose() + { + GC.SuppressFinalize(this); + + var markerSyncer = _markerSyncer; + if (markerSyncer != null) + { + _markerSyncer = null; + markerSyncer.Dispose(); + } + + var markerScanner = _markerScanner; + if (markerScanner != null) + { + _markerScanner = null; + markerScanner.Dispose(); + } + } + + public void InitializeForMarkerScanning(Vector3[] markerPointLocations) + { + _markerSyncer.SendMarkerInformation(markerPointLocations); + } + + public void ScanForMarker + ( + MarkerScanOption options, + Action gotResult = null, + IMarkerScanner scanner = null, + IMetadataSerializer metadataSerializer = null + ) + { + _markerScanner = scanner ?? new ARFrameMarkerScanner(_arNetworking); + _metadataSerializer = metadataSerializer; + _activeScanOptions = options; + _finalResultCallback = gotResult; + + if ((options & MarkerScanOption.ScanToJoin) != 0) + { + ARLog._Debug("Scanning for a marker to join"); + _markerScanner.GotResult += GotJoiningScanResult; + } + else if ((options & MarkerScanOption.ScanToSync) != 0) + { + if (!_arNetworking.Networking.IsConnected) + { + ARLog._Error + ( + "Cannot scan for syncable markers without first being connected to a " + + "networking session." + ); + return; + } + + ARLog._Debug("Scanning for a marker to sync"); + _markerScanner.GotResult += GotSyncingScanResult; + } + else + { + ARLog._Error("No valid options were given for marker scanning."); + return; + } + + _markerScanner.Scan(); + } + + private void GotJoiningScanResult(ARFrameMarkerScannerGotResultArgs args) + { + _markerScanner.Stop(); + _markerScanner.GotResult -= GotJoiningScanResult; + + ValidateCachedMetadata(args.ParserResult.Data); + _arNetworking.Networking.Join(Encoding.UTF8.GetBytes(_cachedMetadata.SessionIdentifier)); + + if ((_activeScanOptions & MarkerScanOption.ScanToSync) != 0) + { + ARLog._Debug("Marker scanned, starting sync"); + _arNetworking.Networking.Connected += ConnectedToNetworking; + } + else + { + ARLog._Debug("Marker scanned and finalizing join"); + if (_finalResultCallback != null) + _finalResultCallback(_cachedMetadata); + + if (Finished != null) + Finished(); + } + } + + private void ConnectedToNetworking(ConnectedArgs args) + { + _arNetworking.Networking.Connected -= ConnectedToNetworking; + + // Don't need to wait for coordinated clocks to sync anymore, but this was noted as + // something that might be revisited in the future, so leaving the line here commented out. + // _UpdateLoop.Tick += CheckSynchronizedClockStatus; + + // For now, start scanning for sync immediately instead of waiting for clocks to sync + StartScanningForSync(); + } + + private void StartScanningForSync() + { + ARLog._Debug("Marker Sync starting scanning for pose sync"); + _arNetworking.PeerStateReceived += OnPeerStateReceived; + _markerScanner.GotResult += GotSyncingScanResult; + _markerScanner.Scan(); + } + + private void ValidateCachedMetadata(byte[] data) + { + if (_cachedMetadata != null) { return; } + + _cachedMetadata = + _metadataSerializer == null + ? BasicMetadataSerializer.StaticDeserialize(data) + : _metadataSerializer.Deserialize(data); + } + + private void GotSyncingScanResult(ARFrameMarkerScannerGotResultArgs args) + { + var parserResult = args.ParserResult; + + ValidateCachedMetadata(parserResult.Data); + + ARLog._DebugFormat + ( + "Marker sync got scan results from {0}", + false, + _cachedMetadata.Source + ); + + switch (_cachedMetadata.Source) + { + case MarkerMetadata.MarkerSource.Device: + { + _markerSyncer.ScanMarkerOnDevice + ( + parserResult.ARCamera, + parserResult.DetectedPoints, + parserResult.Timestamp + ); + break; + } + case MarkerMetadata.MarkerSource.Stationary: + { + _cachedMetadata = + _metadataSerializer == null + ? EmbeddedStationaryMetadataSerializer.StaticDeserialize(parserResult.Data) + : _metadataSerializer.Deserialize(parserResult.Data); + + var stationaryMetadata = (StationaryMarkerMetadata) _cachedMetadata; + + _markerSyncer.ScanStationaryMarker + ( + parserResult.ARCamera, + stationaryMetadata.RealWorldTransform, + stationaryMetadata.DetectionPointPositions, + parserResult.DetectedPoints, + parserResult.Timestamp + ); + break; + } + } + + if (_finalResultCallback != null) + _finalResultCallback(_cachedMetadata); + } + + private void OnPeerStateReceived(PeerStateReceivedArgs args) + { + var state = args.State; + var validFinishedState = state == PeerState.Stabilizing || state == PeerState.Stable; + + if (validFinishedState && args.Peer.Equals(_arNetworking.Networking.Self)) + { + ARLog._Debug("Marker Sync finished syncing position"); + + _markerScanner.Dispose(); + + if (Finished != null) + Finished(); + } + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/AR/Networking/MarkerScanCoordinator.cs.meta b/Assets/ARDK/AR/Networking/MarkerScanCoordinator.cs.meta new file mode 100644 index 0000000..c6cdcb4 --- /dev/null +++ b/Assets/ARDK/AR/Networking/MarkerScanCoordinator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 576131390fa6b47b5ad58430722c2d2a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/Networking/NativeARNetworkingMode_Experimental.cs b/Assets/ARDK/AR/Networking/NativeARNetworkingMode_Experimental.cs new file mode 100644 index 0000000..9eb4091 --- /dev/null +++ b/Assets/ARDK/AR/Networking/NativeARNetworkingMode_Experimental.cs @@ -0,0 +1,15 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +namespace Niantic.ARDK.AR.Networking +{ + /// @note This is currently in internal development, and not useable. + public enum NativeARNetworkingMode_Experimental: + UInt16 + { + Default = 0, + Experimental_1 = 1, + Experimental_2 = 2 + } +} \ No newline at end of file diff --git a/Assets/ARDK/AR/Networking/NativeARNetworkingMode_Experimental.cs.meta b/Assets/ARDK/AR/Networking/NativeARNetworkingMode_Experimental.cs.meta new file mode 100644 index 0000000..d32ac07 --- /dev/null +++ b/Assets/ARDK/AR/Networking/NativeARNetworkingMode_Experimental.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d91003c24a174378b72acc9291cec2dd +timeCreated: 1607451827 \ No newline at end of file diff --git a/Assets/ARDK/AR/Networking/_NativeARNetworking.cs b/Assets/ARDK/AR/Networking/_NativeARNetworking.cs new file mode 100644 index 0000000..4e87942 --- /dev/null +++ b/Assets/ARDK/AR/Networking/_NativeARNetworking.cs @@ -0,0 +1,800 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +using Niantic.ARDK.AR.ARSessionEventArgs; +using Niantic.ARDK.AR.Configuration; +using Niantic.ARDK.AR.Networking.ARNetworkingEventArgs; +using Niantic.ARDK.AR.SLAM; +using Niantic.ARDK.Configuration; +using Niantic.ARDK.Internals; +using Niantic.ARDK.Networking; +using Niantic.ARDK.Networking.MultipeerNetworkingEventArgs; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Collections; +using Niantic.ARDK.Utilities.Logging; +using Niantic.ARDK.Utilities.Marker; + +using UnityEngine; + +using AOT; + +namespace Niantic.ARDK.AR.Networking +{ + // Handles AR Networking sessions through native code. + // Contains an internal _NativeMultipeerNetworking instance to handle multipeer networking calls. + // + // Beyond the typical multipeer networking events, also contains events for receiving pose and + // state data from peers + internal sealed class _NativeARNetworking: + _ThreadCheckedObject, + IARNetworking + { + public IMultipeerNetworking Networking + { + get { return _networking; } + } + + public IARSession ARSession + { + get { return _arSession; } + } + + public IReadOnlyDictionary LatestPeerStates + { + get { return _readOnlyLatestPeerStates; } + } + + public IReadOnlyDictionary LatestPeerPoses + { + get { return _readOnlyLatestPeerPoses; } + } + + private readonly IMultipeerNetworking _networking; + private readonly IARSession _arSession; + + // All accesses of these dictionary must come from the main thread. + private readonly Dictionary _latestPeerStates = + new Dictionary(); + + private readonly Dictionary _latestPeerPoses = + new Dictionary(); + + private _ReadOnlyDictionary _readOnlyLatestPeerStates; + private _ReadOnlyDictionary _readOnlyLatestPeerPoses; + + public PeerState LocalPeerState { get; private set; } + + // Set to true if the _NativeARNetworking is destroyed, or if the underlying native code + // is explicitly destroyed with Destroy. Prevents any currently queued callbacks from + // processing + internal bool IsDestroyed { get; private set; } + + private MarkerScanCoordinator _scanCoordinator; + + // Creates an AR multipeer networking client with a custom server configuration. + internal _NativeARNetworking(IARSession arSession, ServerConfiguration configuration) + { + _FriendTypeAsserter.AssertCallerIs(typeof(ARNetworkingFactory)); + + ARLog._Debug("Creating _NativeARNetworking with a server configuration"); + // Create networking + // ServerConfiguration validation is done in the _NativeMultipeerNetworking constructor + var networking = + MultipeerNetworkingFactory.Create(configuration, arSession.StageIdentifier); + + if (!_ValidateComponents(arSession, networking)) + { + networking.Dispose(); + return; + } + + _arSession = arSession; + _networking = networking; + + FinishInitialization(); + } + + /// Creates an AR multipeer networking client with an existing multipeer networking instance. + internal _NativeARNetworking(IARSession arSession, IMultipeerNetworking networking) + { + _FriendTypeAsserter.AssertCallerIs(typeof(ARNetworkingFactory)); + + ARLog._Debug("Creating _NativeARNetworking with an existing multipeer networking"); + + if (!_ValidateComponents(arSession, networking)) + return; + + _arSession = arSession; + _networking = networking; + + FinishInitialization(); + } + + private bool _ValidateComponents(IARSession arSession, IMultipeerNetworking networking) + { + if (string.IsNullOrEmpty(ArdkGlobalConfig.GetDbowUrl())) + { + ARLog._Debug("DBOW URL was not set. The default URL will be used."); + ArdkGlobalConfig.SetDbowUrl(ArdkGlobalConfig._DBOW_URL); + } + + if (arSession.StageIdentifier != networking.StageIdentifier) + { + var msg = + "Failed to create _NativeARNetworking because the ARSession and MultipeerNetworking" + + " must have the same StageIdentifier."; + + ARLog._Error(msg); + return false; + } + + ARLog._Debug("_NativeARNetworking components validated"); + return true; + } + + private void FinishInitialization() + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + ARLog._DebugFormat("Creating _NativeARNetworking"); + + _nativeHandle = + _NARARMultipeerNetworking_InitWithNetworking + ( + ((_NativeMultipeerNetworking)_networking).GetNativeHandle(), + (UInt16)NativeARNetworkingMode_Experimental.Default, + default(Guid), + 0 + ); + + // Inform the GC that this class is holding a large native object, so it gets cleaned up fast + // TODO(awang): Make an IReleasable interface that handles this for all native-related classes + GC.AddMemoryPressure(GCPressure); + + ARLog._DebugFormat("Created _NativeARNetworking with handle: {0}", false, _nativeHandle); + SubscribeToInternalCallbacks(true); + } +#pragma warning disable 0162 + else + { + _nativeHandle = (IntPtr)1; + } +#pragma warning restore 0162 + + + _readOnlyLatestPeerStates = new _ReadOnlyDictionary(_latestPeerStates); + _readOnlyLatestPeerPoses = new _ReadOnlyDictionary(_latestPeerPoses); + + _networking.PeerAdded += OnPeerAdded; + _networking.PeerRemoved += OnPeerRemoved; + + ARLog._Debug("Finished creating _NativeARNetworking"); + } + + ~_NativeARNetworking() + { + ARLog._Error("_NativeARNetworking should be destroyed by an explicit call to Dispose()."); + Dispose(false); + } + + public void Dispose() + { + _CheckThread(); + + ARLog._Debug("Disposing _NativeARNetworking"); + GC.SuppressFinalize(this); + Dispose(true); + } + + private void Dispose(bool disposing) + { + if (IsDestroyed) + return; + + if (disposing) + { + var deinitializing = Deinitialized; + if (deinitializing != null) + { + var args = new ARNetworkingDeinitializedArgs(); + deinitializing(args); + } + + _networking.PeerAdded -= OnPeerAdded; + _networking.PeerRemoved -= OnPeerRemoved; + + if (_scanCoordinator != null) + { + _scanCoordinator.Dispose(); + _scanCoordinator = null; + } + } + + if (NativeAccess.Mode == NativeAccess.ModeType.Native && _nativeHandle != IntPtr.Zero) + { + _NARARMultipeerNetworking_Release(_nativeHandle); + _nativeHandle = IntPtr.Zero; + + GC.RemoveMemoryPressure(GCPressure); + ARLog._Debug("Released native ARNetworking object"); + } + + _cachedHandle.Free(); + _cachedHandleIntPtr = IntPtr.Zero; + + IsDestroyed = true; + } + + public void EnablePoseBroadcasting() + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARARMultipeerNetworking_EnablePoseBroadcasting(_nativeHandle); + } + + public void DisablePoseBroadcasting() + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARARMultipeerNetworking_DisablePoseBroadcasting(_nativeHandle); + } + + public void SetTargetPoseLatency(Int64 targetPoseLatency) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARARMultipeerNetworking_SetTargetPoseLatency(_nativeHandle, targetPoseLatency); + } + + public void InitializeForMarkerScanning(Vector3[] markerPointLocations) + { + _CheckThread(); + + if (_scanCoordinator != null) + { + var errorMessage = + "Either a marker mapper or scanner session was already started with this " + + "AR networking session."; + + ARLog._Error(errorMessage); + return; + } + + if (!Networking.IsConnected || !Networking.Host.Equals(Networking.Self)) + { + var errorMessage = + "The peer calling this method must be the host in an existing" + + "networking session."; + + ARLog._Error(errorMessage); + return; + } + + _scanCoordinator = new MarkerScanCoordinator(this); + _scanCoordinator.InitializeForMarkerScanning(markerPointLocations); + } + + public void ScanForMarker + ( + MarkerScanOption options, + Action gotResult = null, + IMarkerScanner scanner = null, + IMetadataSerializer deserializer = null + ) + { + _CheckThread(); + + if (_scanCoordinator != null) + { + var warningMessage = + "Either a marker mapper or scanner session was already started with this " + + "AR networking session."; + + ARLog._Warn(warningMessage); + return; + } + + if (Networking.IsConnected && (options & MarkerScanOption.ScanToJoin) != 0) + { + var errorMessage = + "This peer has already joined a networking session, and so cannot join " + + "a session using a marker."; + + ARLog._Error(errorMessage); + return; + } + + if (Networking.IsConnected && Networking.Host.Equals(Networking.Self)) + { + var errorMessage = + "The peer calling this method cannot be the host in an existing" + + "networking session."; + + ARLog._Error(errorMessage); + return; + } + + _scanCoordinator = new MarkerScanCoordinator(this); + _scanCoordinator.Finished += () => { _scanCoordinator = null; }; + + _scanCoordinator.ScanForMarker(options, gotResult, scanner, deserializer); + } + + + // These callbacks are subscribed to at initialization as they set the data that will be provided + // by accessors (LatestPeerPoses and LocalPeerState) + private void SubscribeToInternalCallbacks(bool force = false) + { + _CheckThread(); + + if (force) + { + _didReceivePoseFromPeerInitialized = false; + _didReceiveStateFromPeerInitialized = false; + } + + SubscribeToDidReceivePoseFromPeer(); + SubscribeToDidReceiveStateFromPeer(); + } + + // Add a peer to state tracking when they join the session + private void OnPeerAdded(PeerAddedArgs args) + { + _CheckThread(); + + var peer = args.Peer; + if (!_latestPeerStates.ContainsKey(peer)) + _latestPeerStates.Add(peer, PeerState.Unknown); + } + + // Remove a peer from the internal pose and state tracking when they leave the session + private void OnPeerRemoved(PeerRemovedArgs args) + { + _CheckThread(); + + var peer = args.Peer; + + if (peer.Equals(_networking.Self)) + { + LocalPeerState = PeerState.Unknown; + _latestPeerStates.Clear(); + _latestPeerPoses.Clear(); + } + else + { + _latestPeerStates.Remove(peer); + _latestPeerPoses.Remove(peer); + } + } + + // If the NativeARNetworking or its IMultipeerNetworking has been disposed before the callback + // is invoked, we should not surface the callback. + private static bool _ShouldEarlyReturnFromNativeCallback(_NativeARNetworking arNetworking) + { + if (arNetworking == null) + return true; + + if (arNetworking.IsDestroyed) + return true; + + if (arNetworking._networking == null) + return true; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + if (arNetworking._networking is _NativeMultipeerNetworking nativeNetworking) + { + if (nativeNetworking.IsDestroyed) + return true; + } + else + { + return true; + } + } + + return false; + } + + // Wrap both the native _Peer handling and testing _Peer generation from a native handle in a + // single method. + // Because the native callbacks are expecting IntPtrs, the TestingShim will register test _Peers + // to a list, then use the IntPtr to index into the list to find the correct peer. + // Because we are accessing testing _Peers through indexing into a List, tests that invoke + // PeerState or PeerPose updates cannot run concurrently. + private static IPeer _GetPeerFromHandle(IntPtr handle) + { +#pragma warning disable CS0162 + if (NativeAccess.Mode == NativeAccess.ModeType.Testing) + { + return _TestingShim._GetPeerFromTestingHandle(handle); + } +#pragma warning restore CS0162 + + + return _Peer.FromNativeHandle(handle); + } + +#region TestingShim + internal static class _TestingShim + { + private static List _peerLookup; + private static List _pinnedPoses; + + internal static IPeer _GetPeerFromTestingHandle(IntPtr handle) + { + if (NativeAccess.Mode != NativeAccess.ModeType.Testing) + return null; +#pragma warning disable CS0162 + var index = handle.ToInt32(); + return _peerLookup[index]; +#pragma warning restore CS0162 + } + + // Invoke the native peer state updated callback with the specified parameters. + internal static void _InvokePeerStateUpdate + ( + _NativeARNetworking arNetworking, + UInt32 rawPeerState, + IPeer peer + ) + { + if (NativeAccess.Mode != NativeAccess.ModeType.Testing) + return; +#pragma warning disable CS0162 + if (_peerLookup == null) + _peerLookup = new List(); + + if (!_peerLookup.Contains(peer)) + _peerLookup.Add(peer); + + var testingHandle = new IntPtr(_peerLookup.IndexOf(peer)); + + _onDidReceiveStateFromPeerNative + (arNetworking._applicationHandle, rawPeerState, testingHandle); +#pragma warning restore CS0162 + } + + // Invoke the native peer pose updated callback with the specified parameters + internal static void _InvokePeerPoseUpdate + ( + _NativeARNetworking arNetworking, + float[] nativePose, + IPeer peer + ) + { + if (NativeAccess.Mode != NativeAccess.ModeType.Testing) + return; +#pragma warning disable CS0162 + if (_peerLookup == null) + _peerLookup = new List(); + + if (!_peerLookup.Contains(peer)) + _peerLookup.Add(peer); + + var testingHandle = new IntPtr(_peerLookup.IndexOf(peer)); + + if (_pinnedPoses == null) + _pinnedPoses = new List(); + + var pinnedInternalArray = GCHandle.Alloc(nativePose, GCHandleType.Pinned); + + try + { + _pinnedPoses.Add(pinnedInternalArray); + + _onDidReceivePoseFromPeerNative + ( + arNetworking._applicationHandle, + pinnedInternalArray.AddrOfPinnedObject(), + testingHandle + ); + } + finally + { + pinnedInternalArray.Free(); + _pinnedPoses.Remove(pinnedInternalArray); + } +#pragma warning restore CS0162 + } + + internal static void Reset() + { + if (_peerLookup != null) + _peerLookup.Clear(); + + if (_pinnedPoses != null) + { + foreach (var pose in _pinnedPoses) + { + pose.Free(); + } + + _pinnedPoses.Clear(); + } + } + } +#endregion + +#region PoseFromPeer + private bool _didReceivePoseFromPeerInitialized = false; + + private void SubscribeToDidReceivePoseFromPeer() + { + _CheckThread(); + + if (_didReceivePoseFromPeerInitialized) + return; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + _NARARMultipeerNetworking_Set_didReceivePoseFromPeerCallback + ( + _applicationHandle, + _nativeHandle, + _onDidReceivePoseFromPeerNative + ); + } + + _didReceivePoseFromPeerInitialized = true; + } + + private ArdkEventHandler _peerPoseReceived; + + /// + public event ArdkEventHandler PeerPoseReceived + { + add + { + SubscribeToDidReceivePoseFromPeer(); + _peerPoseReceived += value; + } + remove + { + _peerPoseReceived -= value; + } + } + + [MonoPInvokeCallback(typeof(_NARARMultipeerNetworking_Did_Receive_Pose_From_Peer_CallbackDelegate))] + private static void _onDidReceivePoseFromPeerNative + ( + IntPtr context, + IntPtr pose, + IntPtr peerHandle + ) + { + var arNetworking = SafeGCHandle.TryGetInstance<_NativeARNetworking>(context); + + if (_ShouldEarlyReturnFromNativeCallback(arNetworking)) + { + _Peer._ReleasePeer(peerHandle); + return; + } + + var poseSchema = new float[16]; + Marshal.Copy(pose, poseSchema, 0, 16); + var poseMatrix = NARConversions.FromNARToUnity(_Convert.InternalToMatrix4x4(poseSchema)); + + _CallbackQueue.QueueCallback + ( + () => + { + if (_ShouldEarlyReturnFromNativeCallback(arNetworking)) + { + _Peer._ReleasePeer(peerHandle); + return; + } + + var peer = _GetPeerFromHandle(peerHandle); + + ARLog._DebugFormat + ( + "Handling pose from peer {0}", + true, + peer.Identifier + ); + + arNetworking._latestPeerPoses[peer] = poseMatrix; + + var peerPoseReceived = arNetworking._peerPoseReceived; + if (peerPoseReceived != null) + { + var args = new PeerPoseReceivedArgs(peer, poseMatrix); + peerPoseReceived(args); + } + } + ); + } +#endregion + +#region StateFromPeer + private bool _didReceiveStateFromPeerInitialized = false; + + private void SubscribeToDidReceiveStateFromPeer() + { + _CheckThread(); + + if (_didReceiveStateFromPeerInitialized) + return; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + _NARARMultipeerNetworking_Set_didReceiveStateFromPeerCallback + ( + _applicationHandle, + _nativeHandle, + _onDidReceiveStateFromPeerNative + ); + } + + _didReceiveStateFromPeerInitialized = true; + } + + private ArdkEventHandler _peerStateReceived; + + /// + public event ArdkEventHandler PeerStateReceived + { + add + { + SubscribeToDidReceiveStateFromPeer(); + _peerStateReceived += value; + } + remove + { + _peerStateReceived -= value; + } + } + + [MonoPInvokeCallback + (typeof(_NARARMultipeerNetworking_Did_Receive_State_From_Peer_CallbackDelegate))] + private static void _onDidReceiveStateFromPeerNative + ( + IntPtr context, + UInt32 rawPeerState, + IntPtr peerHandle + ) + { + var arNetworking = SafeGCHandle.TryGetInstance<_NativeARNetworking>(context); + if (_ShouldEarlyReturnFromNativeCallback(arNetworking)) + { + // arNetworking was deallocated + _Peer._ReleasePeer(peerHandle); + return; + } + + var peerState = (PeerState)rawPeerState; + + _CallbackQueue.QueueCallback + ( + () => + { + if (_ShouldEarlyReturnFromNativeCallback(arNetworking)) + { + _Peer._ReleasePeer(peerHandle); + return; + } + + var peer = _GetPeerFromHandle(peerHandle); + if (peer.Equals(arNetworking._networking.Self)) + arNetworking.LocalPeerState = peerState; + + arNetworking._latestPeerStates[peer] = peerState; + + ARLog._DebugFormat + ( + "Handling state from peer {0}", + true, + peer.Identifier + ); + + var peerStateReceived = arNetworking._peerStateReceived; + if (peerStateReceived != null) + { + var args = new PeerStateReceivedArgs(peer, peerState); + peerStateReceived(args); + } + } + ); + } +#endregion + + /// Event fired when instances of this class are deinitializing. + public event ArdkEventHandler Deinitialized; + + // Private handles and callbacks to handle native code and callbacks + + private IntPtr _nativeHandle = IntPtr.Zero; + + private IntPtr _cachedHandleIntPtr = IntPtr.Zero; + private SafeGCHandle<_NativeARNetworking> _cachedHandle; + + // Approx memory consumption of native objects + // Magic number representing 150MB, from profiling an iPhone 8 + private const long GCPressure = 150L * 1024L * 1024L; + + // Used to round-trip a pointer through c++, + // so that we can keep our this pointer even in c# functions + // marshaled and called by native code + private IntPtr _applicationHandle + { + get + { + _CheckThread(); + + if (_cachedHandleIntPtr != IntPtr.Zero) + return _cachedHandleIntPtr; + + _cachedHandle = SafeGCHandle.Alloc(this); + _cachedHandleIntPtr = _cachedHandle.ToIntPtr(); + return _cachedHandleIntPtr; + } + } + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NARARMultipeerNetworking_InitWithNetworking + ( + IntPtr nativeMultipeerNetworking, + UInt16 arNetworkingModeExperimental, + Guid mapLayerIdentifier, + UInt32 localizationOnly + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARARMultipeerNetworking_Release(IntPtr nativeHandle); + + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARARMultipeerNetworking_EnablePoseBroadcasting + ( + IntPtr nativeHandle + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARARMultipeerNetworking_DisablePoseBroadcasting + ( + IntPtr nativeHandle + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARARMultipeerNetworking_SetTargetPoseLatency + ( + IntPtr nativeHandle, + Int64 targetPoseLatency + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NARARMultipeerNetworking_GetNetworking(IntPtr nativeHandle); + + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARARMultipeerNetworking_Set_didReceivePoseFromPeerCallback + ( + IntPtr context, + IntPtr nativeHandle, + _NARARMultipeerNetworking_Did_Receive_Pose_From_Peer_CallbackDelegate cb + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARARMultipeerNetworking_Set_didReceiveStateFromPeerCallback + ( + IntPtr context, + IntPtr nativeHandle, + _NARARMultipeerNetworking_Did_Receive_State_From_Peer_CallbackDelegate cb + ); + + private delegate void _NARARMultipeerNetworking_Did_Receive_Pose_From_Peer_CallbackDelegate + ( + IntPtr context, + IntPtr pose, + IntPtr peer + ); + + private delegate void _NARARMultipeerNetworking_Did_Receive_State_From_Peer_CallbackDelegate + ( + IntPtr context, + UInt32 peerState, + IntPtr peer + ); + } +} diff --git a/Assets/ARDK/AR/Networking/_NativeARNetworking.cs.meta b/Assets/ARDK/AR/Networking/_NativeARNetworking.cs.meta new file mode 100644 index 0000000..4456c68 --- /dev/null +++ b/Assets/ARDK/AR/Networking/_NativeARNetworking.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a3eee8f14627942fba135bddc93cba0a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/PlaneGeometry.meta b/Assets/ARDK/AR/PlaneGeometry.meta new file mode 100644 index 0000000..e59892c --- /dev/null +++ b/Assets/ARDK/AR/PlaneGeometry.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a98e9fed2b81a457fbe9b26ea4cef9c8 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/PlaneGeometry/_NativeARPlaneGeometry.cs b/Assets/ARDK/AR/PlaneGeometry/_NativeARPlaneGeometry.cs new file mode 100644 index 0000000..e12d65d --- /dev/null +++ b/Assets/ARDK/AR/PlaneGeometry/_NativeARPlaneGeometry.cs @@ -0,0 +1,287 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.ObjectModel; +using System.Runtime.InteropServices; + +using Niantic.ARDK.Internals; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Collections; + +using UnityEngine; + +namespace Niantic.ARDK.AR.PlaneGeometry +{ + internal sealed class _NativeARPlaneGeometry: + IARPlaneGeometry + { + // Estimated unmanaged memory: assuming ~50 vertices (3 floats each) + private const long _MemoryPressure = (50L * 3L * 4L); + + private IntPtr _nativeHandle; + + internal _NativeARPlaneGeometry(IntPtr nativeHandle) + { + if (nativeHandle == IntPtr.Zero) + throw new ArgumentException("nativeHandle can't be Zero.", nameof(nativeHandle)); + + _nativeHandle = nativeHandle; + GC.AddMemoryPressure(_MemoryPressure); + } + + private static void _ReleaseImmediate(IntPtr nativeHandle) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARPlaneGeometry_Release(nativeHandle); + } + + ~_NativeARPlaneGeometry() + { + GC.RemoveMemoryPressure(_MemoryPressure); + _ReleaseImmediate(_nativeHandle); + } + + public void Dispose() + { + GC.SuppressFinalize(this); + + var nativeHandle = _nativeHandle; + if (nativeHandle != IntPtr.Zero) + { + _nativeHandle = IntPtr.Zero; + + GC.RemoveMemoryPressure(_MemoryPressure); + _ReleaseImmediate(nativeHandle); + } + } + +#if UNITY_IOS + private ReadOnlyCollection _vertices; +#endif + public ReadOnlyCollection Vertices + { + get + { +#if UNITY_IOS + if (_vertices != null) + return _vertices; + + var vertices = EmptyArray.Instance; + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + while (true) + { + var obtained = _NARPlaneGeometry_GetVertices(_nativeHandle, vertices.Length, vertices); + if (obtained == vertices.Length) + break; + + vertices = new Vector3[Math.Abs(obtained)]; + } + } + + var vertexCount = vertices.Length; + if (vertexCount == 0) + _vertices = EmptyReadOnlyCollection.Instance; + else + { + for (var i = 0; i < vertexCount; i++) + { + var vertex = vertices[i]; + vertices[i] = NARConversions.FromNARToUnity(vertex); + } + + _vertices = new ReadOnlyCollection(vertices); + } + + return _vertices; +#else + return EmptyReadOnlyCollection.Instance; +#endif + } + } + +#if UNITY_IOS + private ReadOnlyCollection _textureCoordinates; +#endif + public ReadOnlyCollection TextureCoordinates + { + get + { +#if UNITY_IOS + if (_textureCoordinates != null) + return _textureCoordinates; + + var textureCoordinates = EmptyArray.Instance; + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + while (true) + { + var obtained = + _NARPlaneGeometry_GetTextureCoordinates + ( + _nativeHandle, + textureCoordinates.Length, + textureCoordinates + ); + + if (obtained == textureCoordinates.Length) + break; + + textureCoordinates = new Vector2[Math.Abs(obtained)]; + } + } + + if (textureCoordinates.Length == 0) + _textureCoordinates = EmptyReadOnlyCollection.Instance; + else + _textureCoordinates = new ReadOnlyCollection(textureCoordinates); + + return _textureCoordinates; +#else + return EmptyReadOnlyCollection.Instance; +#endif + } + } + +#if UNITY_IOS + private ReadOnlyCollection _triangleIndices; +#endif + public ReadOnlyCollection TriangleIndices + { + get + { +#if UNITY_IOS + if (_triangleIndices != null) + return _triangleIndices; + + var triangleIndices = EmptyArray.Instance; + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + while (true) + { + var obtained = + _NARPlaneGeometry_GetTriangleIndices + ( + _nativeHandle, + triangleIndices.Length, + triangleIndices + ); + + if (obtained == triangleIndices.Length) + break; + + triangleIndices = new Int16[Math.Abs(obtained)]; + } + } + + if (triangleIndices.Length == 0) + _triangleIndices = EmptyReadOnlyCollection.Instance; + else + _triangleIndices = new ReadOnlyCollection(triangleIndices); + + return _triangleIndices; +#else + return EmptyReadOnlyCollection.Instance; +#endif + } + } + + private ReadOnlyCollection _boundaryVertices; + public ReadOnlyCollection BoundaryVertices + { + get + { + if (_boundaryVertices != null) + return _boundaryVertices; + + var boundaryVertices = EmptyArray.Instance; + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + while (true) + { + int obtained = 0; + + _NARPlaneGeometry_GetBoundaryVertices + ( + _nativeHandle, + boundaryVertices.Length, + boundaryVertices + ); + + // If at the first time we have the wrong size, we resize or vector and try again. + // This loop should execute at most 2 times. + if (obtained == boundaryVertices.Length) + break; + + boundaryVertices = new Vector3[Math.Abs(obtained)]; + } + } + + // Initialize cache + var boundaryVertexCount = boundaryVertices.Length; + if (boundaryVertexCount == 0) + _boundaryVertices = EmptyReadOnlyCollection.Instance; + else + { + for (var i = 0; i < boundaryVertexCount; i++) + { + var boundaryVertex = boundaryVertices[i]; + boundaryVertices[i] = NARConversions.FromNARToUnity(boundaryVertex); + } + + _boundaryVertices = new ReadOnlyCollection(boundaryVertices); + } + + return _boundaryVertices; + } + } + + /// Gets a fully managed representation of this object. This means that a copy will be made. + internal _SerializableARPlaneGeometry _AsSerializable() + { + return + new _SerializableARPlaneGeometry + ( + Vertices, + TextureCoordinates, + TriangleIndices, + BoundaryVertices + ); + } + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARPlaneGeometry_Release(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern int _NARPlaneGeometry_GetVertices + ( + IntPtr nativeHandle, + int verticesLength, + Vector3[] vertices + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern int _NARPlaneGeometry_GetTextureCoordinates + ( + IntPtr nativeHandle, + int textureCoordinatesLength, + Vector2[] textureCoordinates + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern int _NARPlaneGeometry_GetTriangleIndices + ( + IntPtr nativeHandle, + int triangleIndicesLength, + Int16[] triangleIndices + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern int _NARPlaneGeometry_GetBoundaryVertices + ( + IntPtr nativeHandle, + int boundaryVerticesLength, + Vector3[] boundaryVertices + ); + } +} diff --git a/Assets/ARDK/AR/PlaneGeometry/_NativeARPlaneGeometry.cs.meta b/Assets/ARDK/AR/PlaneGeometry/_NativeARPlaneGeometry.cs.meta new file mode 100644 index 0000000..683c344 --- /dev/null +++ b/Assets/ARDK/AR/PlaneGeometry/_NativeARPlaneGeometry.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 646a094430b24f5797ceb38a94c143e4 +timeCreated: 1592874243 \ No newline at end of file diff --git a/Assets/ARDK/AR/PlaneGeometry/_SerializableARPlaneGeometry.cs b/Assets/ARDK/AR/PlaneGeometry/_SerializableARPlaneGeometry.cs new file mode 100644 index 0000000..c581c99 --- /dev/null +++ b/Assets/ARDK/AR/PlaneGeometry/_SerializableARPlaneGeometry.cs @@ -0,0 +1,38 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.ObjectModel; + +using UnityEngine; + +namespace Niantic.ARDK.AR.PlaneGeometry +{ + [Serializable] + internal sealed class _SerializableARPlaneGeometry: + IARPlaneGeometry + { + internal _SerializableARPlaneGeometry + ( + ReadOnlyCollection vertices, + ReadOnlyCollection textureCoordinates, + ReadOnlyCollection triangleIndices, + ReadOnlyCollection boundaryVertices + ) + { + Vertices = vertices; + TextureCoordinates = textureCoordinates; + TriangleIndices = triangleIndices; + BoundaryVertices = boundaryVertices; + } + + public ReadOnlyCollection Vertices { get; private set; } + public ReadOnlyCollection TextureCoordinates { get; private set; } + public ReadOnlyCollection TriangleIndices { get; private set; } + public ReadOnlyCollection BoundaryVertices { get; private set; } + + void IDisposable.Dispose() + { + // Do nothing as this object is fully managed. + } + } +} diff --git a/Assets/ARDK/AR/PlaneGeometry/_SerializableARPlaneGeometry.cs.meta b/Assets/ARDK/AR/PlaneGeometry/_SerializableARPlaneGeometry.cs.meta new file mode 100644 index 0000000..2d8af68 --- /dev/null +++ b/Assets/ARDK/AR/PlaneGeometry/_SerializableARPlaneGeometry.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: baa5518c6816440d9f328741475a75bb +timeCreated: 1592874015 \ No newline at end of file diff --git a/Assets/ARDK/AR/PointCloud.meta b/Assets/ARDK/AR/PointCloud.meta new file mode 100644 index 0000000..08c5974 --- /dev/null +++ b/Assets/ARDK/AR/PointCloud.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 293b1147ec19847c7ae16258b1863d34 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/PointCloud/_ARPointCloudFactory.cs b/Assets/ARDK/AR/PointCloud/_ARPointCloudFactory.cs new file mode 100644 index 0000000..86874b4 --- /dev/null +++ b/Assets/ARDK/AR/PointCloud/_ARPointCloudFactory.cs @@ -0,0 +1,24 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.AR.PointCloud +{ + internal static class _ARPointCloudFactory + { + internal static _SerializableARPointCloud _AsSerializable(this IARPointCloud pointCloud) + { + var existsAndIsSerializable = + pointCloud == null || + pointCloud is _SerializableARPointCloud; + + if (existsAndIsSerializable) + return (_SerializableARPointCloud)pointCloud; + + return new _SerializableARPointCloud + ( + pointCloud.Points, + pointCloud.Identifiers, + pointCloud.WorldScale + ); + } + } +} diff --git a/Assets/ARDK/AR/PointCloud/_ARPointCloudFactory.cs.meta b/Assets/ARDK/AR/PointCloud/_ARPointCloudFactory.cs.meta new file mode 100644 index 0000000..3176555 --- /dev/null +++ b/Assets/ARDK/AR/PointCloud/_ARPointCloudFactory.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 11f6a8d60eb447b9bf4ebc86ef2f34e5 +timeCreated: 1643307140 \ No newline at end of file diff --git a/Assets/ARDK/AR/PointCloud/_NativeARPointCloud.cs b/Assets/ARDK/AR/PointCloud/_NativeARPointCloud.cs new file mode 100644 index 0000000..53ab297 --- /dev/null +++ b/Assets/ARDK/AR/PointCloud/_NativeARPointCloud.cs @@ -0,0 +1,158 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.ObjectModel; +using System.Runtime.InteropServices; + +using Niantic.ARDK.Internals; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Collections; + +using UnityEngine; + +namespace Niantic.ARDK.AR.PointCloud +{ + internal sealed class _NativeARPointCloud: + IARPointCloud + { + static _NativeARPointCloud() + { + Platform.Init(); + } + + private IntPtr _nativeHandle; + + // Used to inform the C# GC that there is managed memory held by this object + // points + identifiers (estimating 200 points) + private const long _MemoryPressure = (200L * (3L * 4L)) + (200L * 8L); + + public _NativeARPointCloud(IntPtr nativeHandle, float worldScale) + { + if (nativeHandle == IntPtr.Zero) + throw new ArgumentException("nativeHandle can't be Zero.", nameof(nativeHandle)); + + _nativeHandle = nativeHandle; + WorldScale = worldScale; + + GC.AddMemoryPressure(_MemoryPressure); + } + + private static void _ReleaseImmediate(IntPtr nativeHandle) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARPointCloud_Release(nativeHandle); + } + + ~_NativeARPointCloud() + { + _ReleaseImmediate(_nativeHandle); + GC.RemoveMemoryPressure(_MemoryPressure); + } + + public void Dispose() + { + GC.SuppressFinalize(this); + + var nativeHandle = _nativeHandle; + if (nativeHandle != IntPtr.Zero) + { + _nativeHandle = IntPtr.Zero; + + _ReleaseImmediate(nativeHandle); + GC.RemoveMemoryPressure(_MemoryPressure); + } + } + + public float WorldScale { get; private set; } + + private ReadOnlyCollection _points; + public ReadOnlyCollection Points + { + get + { + if (_points != null) + return _points; + + var points = EmptyArray.Instance; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + while (true) + { + var obtained = _NARPointCloud_GetPoints(_nativeHandle, points.Length, points); + + if (obtained == points.Length) + break; + + points = new Vector3[Math.Abs(obtained)]; + } + } + + var pointCount = points.Length; + if (pointCount > 0) + { + for (var i = 0; i < pointCount; i++) + { + var rawPoint = points[i]; + var point = + new Vector3(rawPoint.x * WorldScale, rawPoint.y * WorldScale, rawPoint.z * WorldScale); + + points[i] = NARConversions.FromNARToUnity(point); + } + } + + _points = new ReadOnlyCollection(points); + return _points; + } + } + + private ReadOnlyCollection _identifiers; + public ReadOnlyCollection Identifiers + { + get + { + if (_identifiers != null) + return _identifiers; + + var identifiers = EmptyArray.Instance; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + while (true) + { + var obtained = + _NARPointCloud_GetIdentifiers(_nativeHandle, identifiers.Length, identifiers); + + if (obtained == identifiers.Length) + break; + + identifiers = new ulong[Math.Abs(obtained)]; + } + } + + _identifiers = new ReadOnlyCollection(identifiers); + return _identifiers; + } + } + + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARPointCloud_Release(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern Int32 _NARPointCloud_GetPoints + ( + IntPtr nativeHandle, + Int32 lengthOfOutPoints, + Vector3[] outPoints + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern Int32 _NARPointCloud_GetIdentifiers + ( + IntPtr nativeHandle, + Int32 lengthOfOutIdentifiers, + UInt64[] outIdentifiers + ); + } +} diff --git a/Assets/ARDK/AR/PointCloud/_NativeARPointCloud.cs.meta b/Assets/ARDK/AR/PointCloud/_NativeARPointCloud.cs.meta new file mode 100644 index 0000000..d05af7f --- /dev/null +++ b/Assets/ARDK/AR/PointCloud/_NativeARPointCloud.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 543a7e557ad14263bfa16d93274a19a7 +timeCreated: 1593189275 \ No newline at end of file diff --git a/Assets/ARDK/AR/PointCloud/_SerializableARPointCloud.cs b/Assets/ARDK/AR/PointCloud/_SerializableARPointCloud.cs new file mode 100644 index 0000000..0eec9ca --- /dev/null +++ b/Assets/ARDK/AR/PointCloud/_SerializableARPointCloud.cs @@ -0,0 +1,35 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.ObjectModel; + +using UnityEngine; + +namespace Niantic.ARDK.AR.PointCloud +{ + [Serializable] + internal sealed class _SerializableARPointCloud: + IARPointCloud + { + internal _SerializableARPointCloud + ( + ReadOnlyCollection points, + ReadOnlyCollection identifiers, + float worldScale + ) + { + Points = points; + Identifiers = identifiers; + WorldScale = worldScale; + } + + public ReadOnlyCollection Points { get; private set; } + public ReadOnlyCollection Identifiers { get; private set; } + public float WorldScale { get; private set; } + + void IDisposable.Dispose() + { + // Do nothing as this object is fully managed. + } + } +} diff --git a/Assets/ARDK/AR/PointCloud/_SerializableARPointCloud.cs.meta b/Assets/ARDK/AR/PointCloud/_SerializableARPointCloud.cs.meta new file mode 100644 index 0000000..677422b --- /dev/null +++ b/Assets/ARDK/AR/PointCloud/_SerializableARPointCloud.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c0bb850aa13649d0826e428e1957bcb8 +timeCreated: 1593189033 \ No newline at end of file diff --git a/Assets/ARDK/AR/ReferenceImage.meta b/Assets/ARDK/AR/ReferenceImage.meta new file mode 100644 index 0000000..3573458 --- /dev/null +++ b/Assets/ARDK/AR/ReferenceImage.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6364509d4437743bb9cb2469656136bb +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/ReferenceImage/ARReferenceImageFactory.cs b/Assets/ARDK/AR/ReferenceImage/ARReferenceImageFactory.cs new file mode 100644 index 0000000..b6fa013 --- /dev/null +++ b/Assets/ARDK/AR/ReferenceImage/ARReferenceImageFactory.cs @@ -0,0 +1,477 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Runtime.InteropServices; + +using AOT; + +using Niantic.ARDK.Internals; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; + +namespace Niantic.ARDK.AR.ReferenceImage +{ + /// + /// This class contains methods to create IARReferenceImage instances. + /// + public static class ARReferenceImageFactory + { + /// Creates a new reference image from raw image buffer (RGBA, BGRA, etc), physical size, + /// and orientation. + /// @param name The name of the image (for identifying unique images upon detection) + /// @param rawBytes The base image from which to create the reference image + /// @param width The width of the image in pixels + /// @param height The height of the image in pixels + /// @param byteOrderInfo The endianness of each pixel (See ByteOrderInfo) + /// @param alphaInfo The location of the alpha channel in each pixel (See AlphaInfo) + /// @param physicalWidth + /// The physical width of the image in meters. Be as accurate as possible, entering an + /// incorrect physical size will result in detecting an anchor that’s the wrong distance + /// from the camera. + /// @param orientation + /// The orientation of the provided image. (See Orientation for more information) + /// @note Not supported in Editor. + /// @note The ARReferenceImage will contain the full image buffer until it is destroyed. + /// Unless reuse of the constructed ARReferenceImage is required in the near future, it is + /// recommended to destroy images after adding them to a configuration. + /// @note Currently, only Orientation.Up is supported + /// @note May return null if creating the reference image fails (not enough features, not supported) + public static IARReferenceImage Create + ( + string name, + byte[] rawBytes, + int width, + int height, + ByteOrderInfo byteOrderInfo, + AlphaInfo alphaInfo, + int componentsPerPixel, + float physicalWidth, + Orientation orientation = Orientation.Up + ) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + var result = + _NARReferenceImage_Init + ( + name, + rawBytes, + (UInt64)width, + (UInt64)height, + (UInt64)8 /* hard coded 8 bits per component */, + (UInt64)(8 * componentsPerPixel), + (UInt64)(width * componentsPerPixel), + (UInt32)byteOrderInfo, + (UInt32)alphaInfo, + (UInt32)orientation, + physicalWidth + ); + + if (result == IntPtr.Zero) + { + ARLog._Error("Failed to create reference image, returning null"); + return null; + } + + return _NativeARReferenceImage._FromNativeHandle(result); + } + #pragma warning disable 0162 + else + { + return new _SerializableARReferenceImage(name, Vector2.zero); + } + #pragma warning restore 0162 + } + + /// Creates a new reference image from the contents of a JPG image (in byte[] form), + /// physical size, and orientation. + /// @param name The name of the image (for identifying unique images upon detection) + /// @param rawBytes The JPG image from which to create the reference image + /// @param physicalWidth + /// The physical width of the image in meters. Be as accurate as possible, entering an + /// incorrect physical size will result in detecting an anchor that’s the wrong distance + /// from the camera. + /// @param orientation The orientation of the image (Currently only Up is supported) + /// @note Not supported in Editor. + /// @note The ARReferenceImage will contain the full image buffer until it is destroyed. + /// Unless reuse of the constructed ARReferenceImage is required in the near future, it is + /// recommended to destroy images after adding them to a configuration. + /// @note WARNING: JPG decompression contains a security vulnerability, only use this constructor + /// on a byte buffer that can be verified to be a JPG image (manually uploaded data, server + /// verification, etc). + /// @note May return null if creating the reference image fails (not enough features, not supported) + public static IARReferenceImage Create + ( + string name, + byte[] rawBytesOfJpg, + int bufferSize, + float physicalWidth, + Orientation orientation = Orientation.Up + ) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + var result = + _NARReferenceImage_InitWithJPG + ( + name, + rawBytesOfJpg, + (UInt64)bufferSize, + (UInt32)orientation, + physicalWidth + ); + + if (result == IntPtr.Zero) + { + ARLog._Error("Failed to create reference image, returning null"); + return null; + } + + return _NativeARReferenceImage._FromNativeHandle(result); + } + #pragma warning disable 0162 + else + { + return new _SerializableARReferenceImage(name, Vector2.zero); + } + #pragma warning restore 0162 + } + + /// Creates a new reference image from a JPG file and the physical width + /// @param name The name of the image (for identifying unique images upon detection) + /// @param filePath The JPG image from which to create the reference image + /// @param physicalWidth The physical width of the image in meters. + /// @param orientation The orientation of the image (Currently only Up is supported) + /// @note Not supported in Editor. + /// @note The ARReferenceImage will contain the full image buffer until it is destroyed. + /// Unless reuse of the constructed ARReferenceImage is required in the near future, it is + /// recommended to destroy images after adding them to a configuration. + /// @note WARNING: JPG decompression contains a security vulnerability, only use this constructor + /// on a file that can be verified to be a JPG image (manually uploaded data, server + /// verification, etc). + /// @note May return null if creating the reference image fails (not enough features, not supported) + public static IARReferenceImage Create + ( + string name, + string filePath, + float physicalWidth, + Orientation orientation = Orientation.Up + ) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + var rawBytes = _ReadBytesFromFile(filePath); + var result = + _NARReferenceImage_InitWithJPG + ( + name, + rawBytes, + (UInt64)rawBytes.Length, + (UInt32)orientation, + physicalWidth + ); + + if (result == IntPtr.Zero) + { + ARLog._Error("Failed to create reference image, returning null"); + return null; + } + + return _NativeARReferenceImage._FromNativeHandle(result); + } + #pragma warning disable 0162 + else + { + return new _SerializableARReferenceImage(name, Vector2.zero); + } + #pragma warning restore 0162 + } + + /// Creates a new reference image from raw image buffer (RGBA, BGRA, etc), physical size, + /// and orientation in an async manner. + /// @param name The name of the image (for identifying unique images upon detection) + /// @param rawBytes The base image from which to create the reference image + /// @param width The width of the image in pixels + /// @param height The height of the image in pixels + /// @param byteOrderInfo The endianness of each pixel (See ByteOrderInfo) + /// @param alphaInfo The location of the alpha channel in each pixel (See AlphaInfo) + /// @param physicalWidth The physical width of the image in meters. + /// @param completionHandler The action to run upon creating the image + /// @param orientation The orientation of the provided image. (See Orientation for more + /// information) + /// @note Not supported in Editor. + /// @note The ARReferenceImage will contain the full image buffer until it is destroyed. + /// Unless reuse of the constructed ARReferenceImage is required in the near future, it is + /// recommended to destroy images after adding them to a configuration. + /// @note Currently, only Orientation.Up is supported + /// @note May execute the handler with a null object if creation fails + public static void CreateAsync + ( + string name, + byte[] rawBytes, + int width, + int height, + ByteOrderInfo byteOrderInfo, + AlphaInfo alphaInfo, + int componentsPerPixel, + float physicalWidth, + Action completionHandler, + Orientation orientation = Orientation.Up + ) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + if (orientation != Orientation.Up) + throw new Exception("ARReferenceImage only supports Orientation.Up at the moment"); + + _NARReferenceImage_CreateAsync + ( + name, + rawBytes, + (UInt64)width, + (UInt64)height, + (UInt64)8 /* hard coded 8 bits per component */, + (UInt64)(8 * componentsPerPixel), + (UInt64)(width * componentsPerPixel), + (UInt32)byteOrderInfo, + (UInt32)alphaInfo, + (UInt32)orientation, + physicalWidth, + SafeGCHandle.AllocAsIntPtr(completionHandler), + ARReferenceImageCreateAsyncCallback + ); + } + #pragma warning disable 0162 + else + { + var image = new _SerializableARReferenceImage(name, Vector2.zero); + completionHandler(image); + } + #pragma warning restore 0162 + } + + + /// Creates a new reference image from the contents of a JPG image (in byte[] form), + /// physical size, and orientation in an async manner. + /// @param name The name of the image (for identifying unique images upon detection) + /// @param rawBytes The JPG image from which to create the reference image + /// @param physicalWidth The physical width of the image in meters. + /// @param completionHandler The action to run upon creating the image + /// @param orientation The orientation of the image (Currently only Up is supported) + /// @note Not supported in Editor. + /// @note The ARReferenceImage will contain the full image buffer until it is destroyed. + /// Unless reuse of the constructed ARReferenceImage is required in the near future, it is + /// recommended to destroy images after adding them to a configuration. + /// @note WARNING: JPG decompression contains a security vulnerability, only use this constructor + /// on a byte buffer that can be verified to be a JPG image (manually uploaded data, server + /// verification, etc). + /// @note May execute the handler with a null object if creation fails + public static void CreateAsync + ( + string name, + byte[] rawBytesOfJpg, + int bufferSize, + float physicalWidth, + Action completionHandler, + Orientation orientation = Orientation.Up + ) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + _NARReferenceImage_CreateAsyncWithJPG + ( + name, + rawBytesOfJpg, + (UInt64)bufferSize, + (UInt32)orientation, + physicalWidth, + SafeGCHandle.AllocAsIntPtr(completionHandler), + ARReferenceImageCreateAsyncCallback + ); + } + #pragma warning disable 0162 + else + { + var image = new _SerializableARReferenceImage(name, Vector2.zero); + completionHandler.Invoke(image); + } + #pragma warning restore 0162 + } + + /// Creates a new reference image from a JPG file and the physical width in an async manner + /// @param name The name of the image (for identifying unique images upon detection) + /// @param filePath The JPG image from which to create the reference image + /// @param physicalWidth The physical width of the image in meters. + /// @param completionHandler The action to run upon creating the image + /// @param orientation The orientation of the image (Currently only Up is supported) + /// @note Not supported in Editor. + /// @note The ARReferenceImage will contain the full image buffer until it is destroyed. + /// Unless reuse of the constructed ARReferenceImage is required in the near future, it is + /// recommended to destroy images after adding them to a configuration. + /// @note WARNING: JPG decompression contains a security vulnerability, only use this constructor + /// on a file that can be verified to be a JPG image (manually uploaded data, server + /// verification, etc). + /// @note May execute the handler with a null object if creation fails + public static void CreateAsync + ( + string name, + string filePath, + float physicalWidth, + Action completionHandler, + Orientation orientation = Orientation.Up + ) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + var rawBytes = _ReadBytesFromFile(filePath); + _NARReferenceImage_CreateAsyncWithJPG + ( + name, + rawBytes, + (UInt64)rawBytes.Length, + (UInt32)orientation, + physicalWidth, + SafeGCHandle.AllocAsIntPtr(completionHandler), + ARReferenceImageCreateAsyncCallback + ); + } + #pragma warning disable 0162 + else + { + var image = new _SerializableARReferenceImage(name, Vector2.zero); + completionHandler.Invoke(image); + } + #pragma warning restore 0162 + } + + internal static _SerializableARReferenceImage _AsSerializable(this IARReferenceImage source) + { + var possibleResult = source as _SerializableARReferenceImage; + if (possibleResult != null) + return possibleResult; + + var result = new _SerializableARReferenceImage(source.Name, source.PhysicalSize); + return result; + } + + private static byte[] _ReadBytesFromFile(string filePath) + { +#if UNITY_ANDROID + byte[] rawBytes; + + // This case happens with files built into the apk (ie StreamingAssets), where the file path + // takes the format 'jar:file:///data/xxx'. A UnityWebRequest is required to properly handle + // the 'jar' prefix. In other cases (ie temporaryCachePath), System.IO.File can be used. + if (filePath.Contains("://")) + { + var www = UnityEngine.Networking.UnityWebRequest.Get(filePath); + var request = www.SendWebRequest(); + + while (!request.isDone) + { + // TODO: Shouldn't we add a sleep or something here??? + } + + rawBytes = www.downloadHandler.data; + } + else + { + rawBytes = System.IO.File.ReadAllBytes(filePath); + } + + return rawBytes; +#elif UNITY_IOS + return System.IO.File.ReadAllBytes(filePath); +#else + throw new NotSupportedException("The current platform is not supported."); +#endif + } + + [MonoPInvokeCallback(typeof(_NARReferenceImage_CreateAsync_Callback))] + private static void ARReferenceImageCreateAsyncCallback + ( + IntPtr context, + IntPtr referenceImageHandle + ) + { + var callbackHandle = SafeGCHandle>.FromIntPtr(context); + var callback = callbackHandle.TryGetInstance(); + callbackHandle.Free(); + + // Happens when callback was deallocated + if (callback == null) + return; + + IARReferenceImage referenceImage = null; + + if (referenceImageHandle != IntPtr.Zero) + referenceImage = _NativeARReferenceImage._FromNativeHandle(referenceImageHandle); + + _CallbackQueue.QueueCallback(() => { callback(referenceImage); }); + } + + private delegate void _NARReferenceImage_CreateAsync_Callback + ( + IntPtr context, + IntPtr referenceImageHandle + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NARReferenceImage_Init + ( + string name, + byte[] imageBytes, + UInt64 imageWidth, + UInt64 imageHeight, + UInt64 bitsPerComponent, + UInt64 bitsPerPixel, + UInt64 bytesPerRow, + UInt32 byteOrderInfo, + UInt32 alphaInfo, + UInt32 orientation, + float physicalWidth + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NARReferenceImage_InitWithJPG + ( + string name, + byte[] jpgBytes, + UInt64 jpgBufferSize, + UInt32 orientation, + float physicalWidth + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NARReferenceImage_CreateAsync + ( + string name, + byte[] imageBytes, + UInt64 imageWidth, + UInt64 imageHeight, + UInt64 bitsPerComponent, + UInt64 bitsPerPixel, + UInt64 bytesPerRow, + UInt32 byteOrderInfo, + UInt32 alphaInfo, + UInt32 orientation, + float physicalWidth, + IntPtr applicationContext, + _NARReferenceImage_CreateAsync_Callback callback + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NARReferenceImage_CreateAsyncWithJPG + ( + string name, + byte[] jpgBytes, + UInt64 jpgBufferSize, + UInt32 orientation, + float physicalWidth, + IntPtr applicationContext, + _NARReferenceImage_CreateAsync_Callback callback + ); + } +} diff --git a/Assets/ARDK/AR/ReferenceImage/ARReferenceImageFactory.cs.meta b/Assets/ARDK/AR/ReferenceImage/ARReferenceImageFactory.cs.meta new file mode 100644 index 0000000..6f4f8fc --- /dev/null +++ b/Assets/ARDK/AR/ReferenceImage/ARReferenceImageFactory.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 759dc9890a5b477b97ef530997f306d3 +timeCreated: 1594080952 \ No newline at end of file diff --git a/Assets/ARDK/AR/ReferenceImage/AlphaInfo.cs b/Assets/ARDK/AR/ReferenceImage/AlphaInfo.cs new file mode 100644 index 0000000..6995838 --- /dev/null +++ b/Assets/ARDK/AR/ReferenceImage/AlphaInfo.cs @@ -0,0 +1,19 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.AR.ReferenceImage +{ + /// + /// Defines the position of the alpha data in each pixel of the image + /// + public enum AlphaInfo: uint + { + /// The encoded image data does not contain any alpha data. + None = 1, + + /// The alpha data is stored in the most significant bits. + First = 2, + + /// The alpha data is stored in the least significant bits. + Last = 3, + } +} diff --git a/Assets/ARDK/AR/ReferenceImage/AlphaInfo.cs.meta b/Assets/ARDK/AR/ReferenceImage/AlphaInfo.cs.meta new file mode 100644 index 0000000..0edd424 --- /dev/null +++ b/Assets/ARDK/AR/ReferenceImage/AlphaInfo.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 56a3246241a2492aa67610057f2c80c8 +timeCreated: 1594079459 \ No newline at end of file diff --git a/Assets/ARDK/AR/ReferenceImage/ByteOrderInfo.cs b/Assets/ARDK/AR/ReferenceImage/ByteOrderInfo.cs new file mode 100644 index 0000000..afb687e --- /dev/null +++ b/Assets/ARDK/AR/ReferenceImage/ByteOrderInfo.cs @@ -0,0 +1,22 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.AR.ReferenceImage +{ + /// + /// Defines the order of data per pixel of an image. + /// + /// @note: Although this sounds like it handles all four bytes, the position of that alpha data + /// is defined by the AlphaInfo, so this actually only handles the order of the RGB data. + /// + public enum ByteOrderInfo: + uint + { + /// The bytes in an image are stored in 32-bit little-endian format. e.g. for an ARGB image, + /// the data will look like BGRA. + little32 = 1, + + /// The bytes in an image are stored in 32-bit big-endian format. e.g. for an ARGB image, + /// the data will look like ARGB. + big32 = 2 + } +} diff --git a/Assets/ARDK/AR/ReferenceImage/ByteOrderInfo.cs.meta b/Assets/ARDK/AR/ReferenceImage/ByteOrderInfo.cs.meta new file mode 100644 index 0000000..5ecd384 --- /dev/null +++ b/Assets/ARDK/AR/ReferenceImage/ByteOrderInfo.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e673ee2acf9f49d9bd4763fb4d42878f +timeCreated: 1594079497 \ No newline at end of file diff --git a/Assets/ARDK/AR/ReferenceImage/IARReferenceImage.cs b/Assets/ARDK/AR/ReferenceImage/IARReferenceImage.cs new file mode 100644 index 0000000..b3a1ec9 --- /dev/null +++ b/Assets/ARDK/AR/ReferenceImage/IARReferenceImage.cs @@ -0,0 +1,28 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using UnityEngine; + +namespace Niantic.ARDK.AR.ReferenceImage +{ + /// @brief An image to be recognized in the real-world environment during a world-tracking AR + /// session. + /// @note The ARReferenceImage will contain the full image buffer until it is destroyed. + /// Unless reuse of the constructed ARReferenceImage is required in the near future, it is + /// recommended to destroy images after adding them to a configuration. + public interface IARReferenceImage: + IDisposable + { + /// + /// A name for the image. + /// @note Limited to 25 characters on native + /// + string Name { get; set; } + + /// The real-world dimensions [width, height], in meters, of the image. + /// @note On Android, this may initially be 0,0 when multiple images are being detected, as + /// ARCore attempts to estimate the physical size of the image. This will happen even if a + /// physical size is used to construct the ARReferenceImage. + Vector2 PhysicalSize { get; } + } +} diff --git a/Assets/ARDK/AR/ReferenceImage/IARReferenceImage.cs.meta b/Assets/ARDK/AR/ReferenceImage/IARReferenceImage.cs.meta new file mode 100644 index 0000000..52fc486 --- /dev/null +++ b/Assets/ARDK/AR/ReferenceImage/IARReferenceImage.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d906a8c5825e4a3787d98dc447cd985b +timeCreated: 1594079335 \ No newline at end of file diff --git a/Assets/ARDK/AR/ReferenceImage/Orientation.cs b/Assets/ARDK/AR/ReferenceImage/Orientation.cs new file mode 100644 index 0000000..a894c63 --- /dev/null +++ b/Assets/ARDK/AR/ReferenceImage/Orientation.cs @@ -0,0 +1,38 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.AR.ReferenceImage +{ + /// Value describing the intended display orientation for an image. + public enum Orientation + { + /// The encoded image data matches the image's intended display orientation. + Up = 1, + + /// The encoded image data is horizontally flipped from the image's intended + /// display orientation. + UpMirrored = 2, + + /// The encoded image data is rotated 180º from the image's intended display orientation. + Down = 3, + + /// The encoded image data is vertically flipped rotated from the image's intended + /// display orientation. + DownMirrored = 4, + + /// The encoded image data is horizontally flipped and rotated 90º counter-clockwise from + /// the image's intended display orientation. + LeftMirrored = 5, + + /// The encoded image data is rotated 90º clockwise from the image's intended display + /// orientation. + Right = 6, + + /// The encoded image data is horizontally flipped and rotated 90º clockwise from the + /// image's intended display orientation. + RightMirrored = 7, + + /// The encoded image data is rotated 90º clockwise from the image's intended display + /// orientation. + Left = 8, + } +} diff --git a/Assets/ARDK/AR/ReferenceImage/Orientation.cs.meta b/Assets/ARDK/AR/ReferenceImage/Orientation.cs.meta new file mode 100644 index 0000000..79e94e5 --- /dev/null +++ b/Assets/ARDK/AR/ReferenceImage/Orientation.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 41e8e430ab9843068246e4fd965ef33c +timeCreated: 1594079418 \ No newline at end of file diff --git a/Assets/ARDK/AR/ReferenceImage/_NativeARReferenceImage.cs b/Assets/ARDK/AR/ReferenceImage/_NativeARReferenceImage.cs new file mode 100644 index 0000000..6e3c8f2 --- /dev/null +++ b/Assets/ARDK/AR/ReferenceImage/_NativeARReferenceImage.cs @@ -0,0 +1,157 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Runtime.InteropServices; +using System.Text; + +using Niantic.ARDK.Internals; +using Niantic.ARDK.Utilities; + +using UnityEngine; + +namespace Niantic.ARDK.AR.ReferenceImage +{ + internal sealed class _NativeARReferenceImage: + IARReferenceImage + { + static _NativeARReferenceImage() + { + Platform.Init(); + } + + private static readonly _WeakValueDictionary _allImages = + new _WeakValueDictionary(); + + internal static _NativeARReferenceImage _FromNativeHandle(IntPtr nativeHandle) + { + _StaticMemberValidator._CollectionIsEmptyWhenScopeEnds(() => _allImages); + + var cppAddress = _NARReferenceImage_GetCppAddress(nativeHandle); + + var possibleResult = _allImages.TryGetValue(cppAddress); + if (possibleResult != null) + { + // An existing C# wrapper already exists for the same C++ address. + // So, we release the new handle but return the wrapper to the previous handle, as it will + // still safely point to the right C++ object. + + _ReleaseImmediate(nativeHandle); + return possibleResult; + } + + var result = + _allImages.GetOrAdd(cppAddress, (_) => new _NativeARReferenceImage(nativeHandle)); + + if (result._nativeHandle != nativeHandle) + { + // We got in a very rare situation. After our TryGetValue, another thread actually did add + // a wrapper for the same cppAddress we are using. This means there are 2 handles for the + // same C++ object, and ours is not going to be used. So we should release it immediately. + _ReleaseImmediate(nativeHandle); + } + + return result; + } + + // Estimated memory usage of a reference image: 25 char string + 2 floats + 0.5MB (image) + private const long _MemoryPressure = (25L * 8L) + (2L * 4L) + (512L * 1024L); + + private _NativeARReferenceImage(IntPtr nativeHandle) + { + if (nativeHandle == IntPtr.Zero) + throw new ArgumentNullException("nativeHandle can't be Zero.", "nativeHandle"); + + _nativeHandle = nativeHandle; + GC.AddMemoryPressure(_MemoryPressure); + } + + ~_NativeARReferenceImage() + { + _ReleaseImmediate(_nativeHandle); + + GC.RemoveMemoryPressure(_MemoryPressure); + } + + private static void _ReleaseImmediate(IntPtr nativeHandle) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARReferenceImage_Release(nativeHandle); + } + + public void Dispose() + { + GC.SuppressFinalize(this); + + var nativeHandle = _nativeHandle; + if (nativeHandle != IntPtr.Zero) + { + _nativeHandle = IntPtr.Zero; + + _ReleaseImmediate(nativeHandle); + + GC.RemoveMemoryPressure(_MemoryPressure); + } + } + + private IntPtr _nativeHandle; + internal IntPtr _NativeHandle + { + get { return _nativeHandle;} + } + + public string Name + { + get + { + var stringBuilder = new StringBuilder(25); + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARReferenceImage_GetName(_nativeHandle, stringBuilder, stringBuilder.Capacity); + + return stringBuilder.ToString(); + } + set + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARReferenceImage_SetName(_nativeHandle, value); + } + } + + public Vector2 PhysicalSize + { + get + { + var rawPhysicalSize = new float[2]; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARReferenceImage_GetPhysicalSize(_nativeHandle, rawPhysicalSize); + + return new Vector2(rawPhysicalSize[0], rawPhysicalSize[1]); + } + } + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARReferenceImage_Release(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NARReferenceImage_GetCppAddress(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARReferenceImage_GetName + ( + IntPtr nativeHandle, + StringBuilder outName, + int maxNameSize + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARReferenceImage_SetName(IntPtr nativeHandle, string name); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARReferenceImage_GetPhysicalSize + ( + IntPtr nativeHandle, + float[] outPhysicalSize + ); + } +} diff --git a/Assets/ARDK/AR/ReferenceImage/_NativeARReferenceImage.cs.meta b/Assets/ARDK/AR/ReferenceImage/_NativeARReferenceImage.cs.meta new file mode 100644 index 0000000..fff2364 --- /dev/null +++ b/Assets/ARDK/AR/ReferenceImage/_NativeARReferenceImage.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e789cddb0a2042528e36a9e1d6898a07 +timeCreated: 1594080077 \ No newline at end of file diff --git a/Assets/ARDK/AR/ReferenceImage/_SerializableARReferenceImage.cs b/Assets/ARDK/AR/ReferenceImage/_SerializableARReferenceImage.cs new file mode 100644 index 0000000..62c76b8 --- /dev/null +++ b/Assets/ARDK/AR/ReferenceImage/_SerializableARReferenceImage.cs @@ -0,0 +1,26 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using UnityEngine; + +namespace Niantic.ARDK.AR.ReferenceImage +{ + [Serializable] + internal sealed class _SerializableARReferenceImage: + IARReferenceImage + { + internal _SerializableARReferenceImage(string name, Vector2 physicalSize) + { + Name = name; + PhysicalSize = physicalSize; + } + + public string Name { get; set; } + public Vector2 PhysicalSize { get; set; } + + void IDisposable.Dispose() + { + // Do nothing. This implementation of IARReferenceImage is fully managed. + } + } +} diff --git a/Assets/ARDK/AR/ReferenceImage/_SerializableARReferenceImage.cs.meta b/Assets/ARDK/AR/ReferenceImage/_SerializableARReferenceImage.cs.meta new file mode 100644 index 0000000..fb80658 --- /dev/null +++ b/Assets/ARDK/AR/ReferenceImage/_SerializableARReferenceImage.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: fa2b02179b764383a3fc9bfd4c7a9605 +timeCreated: 1594079906 \ No newline at end of file diff --git a/Assets/ARDK/AR/RuntimeEnvironment.cs b/Assets/ARDK/AR/RuntimeEnvironment.cs new file mode 100644 index 0000000..f7bf541 --- /dev/null +++ b/Assets/ARDK/AR/RuntimeEnvironment.cs @@ -0,0 +1,24 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK +{ + /// Options for which implementation of the core ARDK interfaces (IARSession, + /// IMultipeerNetworking, and IARNetworking) to use at runtime. + public enum RuntimeEnvironment + { + /// On a mobile device, this is equivalent to the LiveDevice value. + /// In the Unity Editor, if Remoting is enabled in the Virtual Studio window then it is + /// equivalent to the Remote value, else it is equivalent to the Mock value. + Default, + + /// AR data is sourced "live" (that is, an actual camera or similar is being used), and + /// networking connects to a live server. + LiveDevice, + + /// AR data and networking responses are coming from a remote source. + Remote, + + /// AR data and networking responses are completely code based and contained in the Unity Editor. + Mock + } +} diff --git a/Assets/ARDK/AR/RuntimeEnvironment.cs.meta b/Assets/ARDK/AR/RuntimeEnvironment.cs.meta new file mode 100644 index 0000000..86a0909 --- /dev/null +++ b/Assets/ARDK/AR/RuntimeEnvironment.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 248e463017894a97a653c0de0a27fb81 +timeCreated: 1610040166 \ No newline at end of file diff --git a/Assets/ARDK/AR/SLAM.meta b/Assets/ARDK/AR/SLAM.meta new file mode 100644 index 0000000..4b59ef3 --- /dev/null +++ b/Assets/ARDK/AR/SLAM.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c3b36bc41a6594f4d86c574b47d03dbc +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/SLAM/ARMap.meta b/Assets/ARDK/AR/SLAM/ARMap.meta new file mode 100644 index 0000000..06823dc --- /dev/null +++ b/Assets/ARDK/AR/SLAM/ARMap.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: bee8151e4f2654497926fbdda2b704f9 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/SLAM/ARMap/IARMap.cs b/Assets/ARDK/AR/SLAM/ARMap/IARMap.cs new file mode 100644 index 0000000..776c4f2 --- /dev/null +++ b/Assets/ARDK/AR/SLAM/ARMap/IARMap.cs @@ -0,0 +1,39 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using UnityEngine; + +namespace Niantic.ARDK.AR.SLAM +{ + /// @brief A map that is generated by the Computer Vision system on a host device + /// based on the world around the device. All other devices receive maps from the host + /// and try to sync against the maps to figure out where they are in the world + /// with respect to the host. + /// @remarks When a map is published by the host device and reaches the other client + /// devices in the session, the client devices need to look towards the position where + /// the host has published the map in order to sync. + public interface IARMap: + IDisposable + { + /// + /// A unique identifier representing this map. + /// + Guid Identifier { get; } + + /// + /// The Unity-specific scaling factor applied to this map's Transform. + /// + float WorldScale { get; } + + /// + /// Transform of the approximate center of the map. The orientation is always identity. + /// + Matrix4x4 Transform { get; } + + // This is odd to be here, but we have some other classes not in the ARDK that use the native + // handle. We can either make the entire _NativeARMap public, or we expose these properties + // to tell if NativeHandle can be accessed and to actually access it. + bool CanGetNativeHandle { get; } + IntPtr NativeHandle { get; } + } +} diff --git a/Assets/ARDK/AR/SLAM/ARMap/IARMap.cs.meta b/Assets/ARDK/AR/SLAM/ARMap/IARMap.cs.meta new file mode 100644 index 0000000..c81dd0d --- /dev/null +++ b/Assets/ARDK/AR/SLAM/ARMap/IARMap.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: df0f423454ec49e7811120f230dc0389 +timeCreated: 1593709489 \ No newline at end of file diff --git a/Assets/ARDK/AR/SLAM/ARMap/_ARMapFactory.cs b/Assets/ARDK/AR/SLAM/ARMap/_ARMapFactory.cs new file mode 100644 index 0000000..5224a2c --- /dev/null +++ b/Assets/ARDK/AR/SLAM/ARMap/_ARMapFactory.cs @@ -0,0 +1,40 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.Collections.Generic; +using System.Collections.ObjectModel; + +using Niantic.ARDK.Utilities.Collections; + +namespace Niantic.ARDK.AR.SLAM +{ + internal static class _ARMapFactory + { + internal static _SerializableARMap _AsSerializable(this IARMap source) + { + if (source == null) + return null; + + var possibleResult = source as _SerializableARMap; + if (possibleResult != null) + return possibleResult; + + return new _SerializableARMap(source.Identifier, source.WorldScale, source.Transform); + } + + internal static _SerializableARMap[] _AsSerializableArray(this IList source) + { + if (source == null) + return null; + + int count = source.Count; + if (count == 0) + return EmptyArray<_SerializableARMap>.Instance; + + var result = new _SerializableARMap[count]; + for(int i=0; i _allMaps = + new _WeakValueDictionary<_CppAddressAndScale, _NativeARMap>(); + + internal static _NativeARMap _FromNativeHandle(IntPtr nativeHandle, float worldScale) + { + _StaticMemberValidator._CollectionIsEmptyWhenScopeEnds(() => _allMaps); + + var cppAddress = _NARMapViz_GetCppAddress(nativeHandle); + var handleAndScale = new _CppAddressAndScale(cppAddress, worldScale); + + var result = _allMaps.TryGetValue(handleAndScale); + if (result != null) + { + // We found an existing C# wrapper for the actual C++ object. Let's release the new + // nativeHandle and return the existing wrapper. + + _ReleaseImmediate(nativeHandle); + return result; + } + + Func<_CppAddressAndScale, _NativeARMap> creator = + (_) => new _NativeARMap(nativeHandle, worldScale); + + result = _allMaps.GetOrAdd(handleAndScale, creator); + + if (result._nativeHandle != nativeHandle) + { + // We got on the very odd situation where just after a TryGetValue another value was added. + // We should release our handle immediately. Then, we can return the result as it is valid. + _ReleaseImmediate(nativeHandle); + } + + return result; + } + + private _NativeARMap(IntPtr nativeHandle, float worldScale = 1.0f) + { + if (nativeHandle == IntPtr.Zero) + throw new ArgumentException("nativeHandle can't be Zero.", nameof(nativeHandle)); + + _nativeHandle = nativeHandle; + WorldScale = worldScale; + + GC.AddMemoryPressure(_MemoryPressure); + } + + internal static void _ReleaseImmediate(IntPtr nativeHandle) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARMapViz_Release(nativeHandle); + } + + ~_NativeARMap() + { + _ReleaseImmediate(_nativeHandle); + GC.RemoveMemoryPressure(_MemoryPressure); + } + + public void Dispose() + { + GC.SuppressFinalize(this); + + var nativeHandle = _nativeHandle; + if (nativeHandle != IntPtr.Zero) + { + _nativeHandle = IntPtr.Zero; + + _ReleaseImmediate(nativeHandle); + GC.RemoveMemoryPressure(_MemoryPressure); + } + } + + public float WorldScale { get; private set; } + + public bool CanGetNativeHandle + { + get { return true; } + } + + private IntPtr _nativeHandle; + public IntPtr NativeHandle + { + get { return _nativeHandle; } + } + + public Guid Identifier + { + get + { + Guid result; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARMapViz_GetIdentifier(_nativeHandle, out result); + #pragma warning disable 0162 + else + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + + return result; + } + } + + public Matrix4x4 Transform + { + get + { + var nativeTransform = new float[16]; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARMapViz_GetTransform(_nativeHandle, nativeTransform); + #pragma warning disable 0162 + else + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + + var transform = + NARConversions.FromNARToUnity(_Convert.InternalToMatrix4x4(nativeTransform)); + + _Convert.ApplyScale(ref transform, WorldScale); + + return transform; + } + } + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARMapViz_Release(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NARMapViz_GetCppAddress(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARMapViz_GetIdentifier(IntPtr nativeHandle, out Guid identifier); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARMapViz_GetTransform(IntPtr nativeHandle, float[] outTransform); + } +} diff --git a/Assets/ARDK/AR/SLAM/ARMap/_NativeARMap.cs.meta b/Assets/ARDK/AR/SLAM/ARMap/_NativeARMap.cs.meta new file mode 100644 index 0000000..956b273 --- /dev/null +++ b/Assets/ARDK/AR/SLAM/ARMap/_NativeARMap.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f8d63b22c0e34c65978d0c1d6e081779 +timeCreated: 1593709906 \ No newline at end of file diff --git a/Assets/ARDK/AR/SLAM/ARMap/_SerializableARMap.cs b/Assets/ARDK/AR/SLAM/ARMap/_SerializableARMap.cs new file mode 100644 index 0000000..cab6de1 --- /dev/null +++ b/Assets/ARDK/AR/SLAM/ARMap/_SerializableARMap.cs @@ -0,0 +1,38 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using UnityEngine; + +namespace Niantic.ARDK.AR.SLAM +{ + [Serializable] + internal sealed class _SerializableARMap: + IARMap + { + internal _SerializableARMap(Guid identifier, float worldScale, Matrix4x4 transform) + { + Identifier = identifier; + WorldScale = worldScale; + Transform = transform; + } + + public Guid Identifier { get; private set; } + public float WorldScale { get; private set; } + public Matrix4x4 Transform { get; private set; } + + public bool CanGetNativeHandle + { + get { return false; } + } + + IntPtr IARMap.NativeHandle + { + get { throw new NotSupportedException("This object doesn't have a NativeHandle."); } + } + + void IDisposable.Dispose() + { + // Do nothing. This object is fully managed. + } + } +} diff --git a/Assets/ARDK/AR/SLAM/ARMap/_SerializableARMap.cs.meta b/Assets/ARDK/AR/SLAM/ARMap/_SerializableARMap.cs.meta new file mode 100644 index 0000000..b573e65 --- /dev/null +++ b/Assets/ARDK/AR/SLAM/ARMap/_SerializableARMap.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 028f5ae3c1c1462799eff8de5db7f2ca +timeCreated: 1593709672 \ No newline at end of file diff --git a/Assets/ARDK/AR/SLAM/MarkerSyncer.meta b/Assets/ARDK/AR/SLAM/MarkerSyncer.meta new file mode 100644 index 0000000..870f541 --- /dev/null +++ b/Assets/ARDK/AR/SLAM/MarkerSyncer.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 357979fde0297430aab365e3962c8857 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/SLAM/MarkerSyncer/IMarkerSyncer.cs b/Assets/ARDK/AR/SLAM/MarkerSyncer/IMarkerSyncer.cs new file mode 100644 index 0000000..f032220 --- /dev/null +++ b/Assets/ARDK/AR/SLAM/MarkerSyncer/IMarkerSyncer.cs @@ -0,0 +1,79 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.AR.Camera; + +using UnityEngine; + +namespace Niantic.ARDK.AR.SLAM +{ + /// + /// System to sync Unity-space coordinates of multiple peers using a marker (ex. QRCode, image). + /// + internal interface IMarkerSyncer: + IDisposable + { + /// An identifier used internally to relate different systems. This is the identifier for + /// the LocationService system. + Guid StageIdentifier { get; } + + /// + /// Use to publish information about the marker displayed on a host peer's device. + /// + /// Real-world space locations of the marker points (unit: meters). + /// Points must be in the same order as in the scannedPointLocations argument of + /// the ScanMarkerOnDevice method. + void SendMarkerInformation(Vector3[] pointLocations); + + /// + /// Use to sync using a scan of a marker displayed on the host peer's device screen + /// + /// + /// ARCamera instance from the ARFrame that the marker was scanned on. + /// + /// + /// Screen-space locations of scanned marker points (unit: pixels). + /// Points must be in the same order as in the corners argument in the SendMarkerInformation + /// method. + /// + /// + void ScanMarkerOnDevice + ( + IARCamera arCamera, + Vector2[] scannedPointLocations, + double timestamp + ); + + /// + /// Use to sync using a scan of a marker that is placed in the real world. In this use case, + /// make sure the real world coordinate space has gravity aligned on the y-axis (ie y-axis is + /// up/down). + /// + /// + /// ARCamera instance from the ARFrame that the marker was scanned on. + /// + /// + /// Real world-space position (unit: meters) and orientation of the marker relative to the + /// origin of the shared AR space. + /// + /// + /// Real world-space positions (unit: meters) of the marker points relative to the + /// markerWorldTransform . Points must be in the same order as in the scannedPointLocations + /// argument. + /// + /// + /// Screen-space locations (unit: pixels) of the scanned marker points. Points must be in the + /// same order as in markerPointLocations. + /// + /// + void ScanStationaryMarker + ( + IARCamera arCamera, + Matrix4x4 markerWorldTransform, + Vector3[] markerPointPositions, + Vector2[] scannedPointPositions, + double timestamp + ); + } +} diff --git a/Assets/ARDK/AR/SLAM/MarkerSyncer/IMarkerSyncer.cs.meta b/Assets/ARDK/AR/SLAM/MarkerSyncer/IMarkerSyncer.cs.meta new file mode 100644 index 0000000..53c6df3 --- /dev/null +++ b/Assets/ARDK/AR/SLAM/MarkerSyncer/IMarkerSyncer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ce631b1245e4549ea83321f13ca2edb7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/SLAM/MarkerSyncer/NativeMarkerSyncer.cs b/Assets/ARDK/AR/SLAM/MarkerSyncer/NativeMarkerSyncer.cs new file mode 100644 index 0000000..93600b0 --- /dev/null +++ b/Assets/ARDK/AR/SLAM/MarkerSyncer/NativeMarkerSyncer.cs @@ -0,0 +1,234 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Runtime.InteropServices; + +using Niantic.ARDK.AR.Camera; +using Niantic.ARDK.Internals; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; + +namespace Niantic.ARDK.AR.SLAM +{ + /// + /// An implementation of IMarkerSyncer that sends data about markers found by the device + /// to be processed by NAR native + /// + internal sealed class NativeMarkerSyncer: + IMarkerSyncer + { + public Guid StageIdentifier { get; private set; } + + // Private handles and code to deal with native callbacks and initialization + private IntPtr _nativeHandle = IntPtr.Zero; + + public NativeMarkerSyncer(Guid stageIdentifier) + { + StageIdentifier = stageIdentifier; + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _nativeHandle = _NARMarkerManager_Init(StageIdentifier.ToByteArray()); + } + + ~NativeMarkerSyncer() + { + _ReleaseUnmanagedResources(); + + ARLog._Error("NativeMarkerSyncer should be destroyed by an explicit call to Dispose()."); + } + + public void Dispose() + { + GC.SuppressFinalize(this); + + _ReleaseUnmanagedResources(); + } + + private void _ReleaseUnmanagedResources() + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + if (_nativeHandle != IntPtr.Zero) + { + _NARMarkerManager_Release(_nativeHandle); + _nativeHandle = IntPtr.Zero; + } + } + } + + public void SendMarkerInformation(Vector3[] markerPointLocations) + { + if (_nativeHandle == IntPtr.Zero) + { + ARLog._Warn("Tried to access invalid NativeMarkerSyncer"); + return; + } + + var markerPointsFlattened = FlattenVectorArray(markerPointLocations); + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + ARLog._Debug("Sending marker information to native marker manager"); + _NARMarkerManager_SendMarkerInformation + ( + _nativeHandle, + markerPointsFlattened, + markerPointLocations.Length + ); + } + } + + public void ScanStationaryMarker + ( + IARCamera arCamera, + Matrix4x4 markerWorldTransform, + Vector3[] markerPointPositions, + Vector2[] scannedPointPositions, + double timestamp + ) + { + if (_nativeHandle == IntPtr.Zero) + { + ARLog._Warn("Tried to access invalid NativeMarkerSyncer"); + return; + } + + ARLog._Debug("Called ScanStationaryMarker"); + + // Object point calculations + var objectPointsFlattened = FlattenVectorArray(markerPointPositions); + + var mwt = markerWorldTransform; + var objectExtrinsicsArray = + new float[] + { + mwt.m00, mwt.m01, mwt.m02, mwt.m03, + mwt.m10, mwt.m11, mwt.m12, mwt.m13, + mwt.m20, mwt.m21, mwt.m22, mwt.m23, + mwt.m30, mwt.m31, mwt.m32, mwt.m33, + }; + + // Input point calculations + var imagePointsFlattened = FlattenVectorArray(scannedPointPositions); + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + ARLog._Debug("Sending stationary marker to be evaluated by native marker manager"); + var nativeCamera = (_NativeARCamera)arCamera; + _NARMarkerManager_ScanPrintedMarker + ( + _nativeHandle, + nativeCamera._NativeHandle, + objectPointsFlattened, + markerPointPositions.Length, + objectExtrinsicsArray, + imagePointsFlattened, + scannedPointPositions.Length, + timestamp + ); + } + } + + public void ScanMarkerOnDevice + ( + IARCamera arCamera, + Vector2[] scannedPointLocations, + double timestamp + ) + { + if (_nativeHandle == IntPtr.Zero) + { + ARLog._Warn("Tried to access invalid NativeMarkerSyncer"); + return; + } + + var imagePointsFlattened = FlattenVectorArray(scannedPointLocations); + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + ARLog._Debug("Sending device marker to be evaluated by native marker manager"); + var nativeCamera = (_NativeARCamera)arCamera; + _NARMarkerManager_ScanMarkerOnDevice + ( + _nativeHandle, + nativeCamera._NativeHandle, + imagePointsFlattened, + scannedPointLocations.Length, + timestamp + ); + } + } + + private static float[] FlattenVectorArray(Vector3[] inputArray) + { + var numInputs = inputArray.Length; + var flattenedArray = new float[numInputs * 3]; + + var flattenedIndex = 0; + for (var inputIndex = 0; inputIndex < numInputs; ++inputIndex) + { + var vector = inputArray[inputIndex]; + flattenedArray[flattenedIndex++] = vector.x; + flattenedArray[flattenedIndex++] = vector.y; + flattenedArray[flattenedIndex++] = vector.z; + } + + return flattenedArray; + } + + private static float[] FlattenVectorArray(Vector2[] inputArray) + { + var numInputs = inputArray.Length; + var flattenedArray = new float[numInputs * 2]; + + var flattenedIndex = 0; + for (var inputIndex = 0; inputIndex < numInputs; ++inputIndex) + { + var vector = inputArray[inputIndex]; + flattenedArray[flattenedIndex++] = vector.x; + flattenedArray[flattenedIndex++] = vector.y; + } + + return flattenedArray; + } + +#region Externals + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NARMarkerManager_Init(byte[] stageIdentifier); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARMarkerManager_SendMarkerInformation + ( + IntPtr nativeHandle, + float[] objectPoints, + int numObjectPoints + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARMarkerManager_ScanMarkerOnDevice + ( + IntPtr nativeHandle, + IntPtr arCameraHandle, + float[] imagePoints, + int numImagePoints, + double timestamp + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARMarkerManager_ScanPrintedMarker + ( + IntPtr nativeHandle, + IntPtr arCameraHandle, + float[] objectPoints, + int numObjectPoints, + float[] objectExtrinsics, + float[] imagePoints, + int numImagePoints, + double timestamp + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARMarkerManager_Release(IntPtr nativeHandle); +#endregion + } +} diff --git a/Assets/ARDK/AR/SLAM/MarkerSyncer/NativeMarkerSyncer.cs.meta b/Assets/ARDK/AR/SLAM/MarkerSyncer/NativeMarkerSyncer.cs.meta new file mode 100644 index 0000000..cc1aa03 --- /dev/null +++ b/Assets/ARDK/AR/SLAM/MarkerSyncer/NativeMarkerSyncer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8362cb6ac932c4720a2a7fcccce21be2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/TrackingState.cs b/Assets/ARDK/AR/TrackingState.cs new file mode 100644 index 0000000..99f5075 --- /dev/null +++ b/Assets/ARDK/AR/TrackingState.cs @@ -0,0 +1,18 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.AR +{ + /// @brief Possible values for position tracking quality. + public enum TrackingState: + byte + { + /// Position tracking is not available. + NotAvailable = 0, + + /// Tracking is available, but the quality is limited. + Limited = 1, + + /// Position tracking is providing optimal results. + Normal = 2, + } +} diff --git a/Assets/ARDK/AR/TrackingState.cs.meta b/Assets/ARDK/AR/TrackingState.cs.meta new file mode 100644 index 0000000..9bf53dd --- /dev/null +++ b/Assets/ARDK/AR/TrackingState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 26e1c6f4ae1e240c2a08a8a51250306d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/TrackingStateReason.cs b/Assets/ARDK/AR/TrackingStateReason.cs new file mode 100644 index 0000000..7600c8b --- /dev/null +++ b/Assets/ARDK/AR/TrackingStateReason.cs @@ -0,0 +1,27 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.AR +{ + /// @brief Possible causes for limited position tracking quality. + /// @note iOS-only value. + public enum TrackingStateReason: + byte + { + /// Current tracking peerState is not limited. + /// @note This is the only Android-supported value of TrackingStateReason. + None = 0, + + /// The AR session has not gathered enough camera or motion data to provide + /// tracking information. + Initializing = 1, + + /// Tracking is limited due to excessive motion of the device. + ExcessiveMotion = 2, + + /// Tracking is limited due to insufficient features viewable by the camera. + InsufficientFeatures = 3, + + /// Tracking is limited due to a relocalization in progress. + Relocalizing = 4 + } +} diff --git a/Assets/ARDK/AR/TrackingStateReason.cs.meta b/Assets/ARDK/AR/TrackingStateReason.cs.meta new file mode 100644 index 0000000..b94544c --- /dev/null +++ b/Assets/ARDK/AR/TrackingStateReason.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d0e739663944147f2ab65940203a64e2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/VideoFormat.meta b/Assets/ARDK/AR/VideoFormat.meta new file mode 100644 index 0000000..a6cca07 --- /dev/null +++ b/Assets/ARDK/AR/VideoFormat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c339151a270de49c4938f07dce0570b0 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/VideoFormat/_NativeARVideoFormat.cs b/Assets/ARDK/AR/VideoFormat/_NativeARVideoFormat.cs new file mode 100644 index 0000000..aaf304a --- /dev/null +++ b/Assets/ARDK/AR/VideoFormat/_NativeARVideoFormat.cs @@ -0,0 +1,156 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Runtime.InteropServices; + +using Niantic.ARDK.Internals; +using Niantic.ARDK.Utilities; + +using UnityEngine; + +namespace Niantic.ARDK.AR.VideoFormat +{ + internal sealed class _NativeARVideoFormat: + IARVideoFormat + { + // Estimated unmanaged memory usage: 1 int64 + 2 Vector2 + private const long _MemoryPressure = (1L * 8L) + (2L * 4L) + (2L * 4L); + + static _NativeARVideoFormat() + { + Platform.Init(); + } + + private static readonly _WeakValueDictionary _allVideoFormats = + new _WeakValueDictionary(); + + internal static _NativeARVideoFormat _FromNativeHandle(IntPtr nativeHandle) + { + _StaticMemberValidator._CollectionIsEmptyWhenScopeEnds(() => _allVideoFormats); + + #pragma warning disable CS0162 + if (NativeAccess.Mode != NativeAccess.ModeType.Native) + return new _NativeARVideoFormat(nativeHandle); + #pragma warning restore CS0162 + + var uniqueId = _NARVideoFormat_GetPlatformHandle(nativeHandle); + + var result = _allVideoFormats.TryGetValue(uniqueId); + if (result != null) + { + // There is an already existing format for the given uniqueId. So we release the new handle + // immediately and return the existing object. + _ReleaseImmediate(nativeHandle); + return result; + } + + result = _allVideoFormats.GetOrAdd(uniqueId, (_) => new _NativeARVideoFormat(nativeHandle)); + if (result._NativeHandle != nativeHandle) + { + // Just after our TryGetValue an instance was registered for the given uniqueId. + // So, same as before, we need to release our handle immediately. + _ReleaseImmediate(nativeHandle); + } + + // We either created a new object or we are using an existing one. In any case, return what + // we got. + return result; + } + + private IntPtr _nativeHandle; + + private _NativeARVideoFormat(IntPtr nativeHandle) + { + if (nativeHandle == IntPtr.Zero) + throw new ArgumentException("nativeHandle can't be Zero.", nameof(nativeHandle)); + + _nativeHandle = nativeHandle; + GC.AddMemoryPressure(_MemoryPressure); + } + + public static void _ReleaseImmediate(IntPtr nativeHandle) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARVideoFormat_Release(nativeHandle); + } + + ~_NativeARVideoFormat() + { + _ReleaseImmediate(_nativeHandle); + GC.RemoveMemoryPressure(_MemoryPressure); + } + + internal IntPtr _NativeHandle + { + get { return _nativeHandle; } + } + + public int FramesPerSecond + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return (int)_NARVideoFormat_GetFramesPerSecond(_nativeHandle); + + #pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); + #pragma warning restore 0162 + } + } + + public Vector2 ImageResolution + { + get + { + var rawImageResolution = new Int32[2]; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARVideoFormat_GetImageResolution(_nativeHandle, rawImageResolution); + + return new Vector2(rawImageResolution[0], rawImageResolution[1]); + } + } + + public Vector2 TextureResolution + { + get + { + var rawTextureResolution = new Int32[2]; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARVideoFormat_GetTextureResolution(_nativeHandle, rawTextureResolution); + + return new Vector2(rawTextureResolution[0], rawTextureResolution[1]); + } + } + + internal _SerializableARVideoFormat _AsSerializable() + { + return new _SerializableARVideoFormat(FramesPerSecond, ImageResolution, TextureResolution); + } + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARVideoFormat_Release(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NARVideoFormat_GetPlatformHandle(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern Int64 _NARVideoFormat_GetFramesPerSecond(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARVideoFormat_GetImageResolution + ( + IntPtr nativeHandle, + Int32[] outImageResolution + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARVideoFormat_GetTextureResolution + ( + IntPtr nativeHandle, + Int32[] outTextureResolution + ); + } +} + diff --git a/Assets/ARDK/AR/VideoFormat/_NativeARVideoFormat.cs.meta b/Assets/ARDK/AR/VideoFormat/_NativeARVideoFormat.cs.meta new file mode 100644 index 0000000..06fa0fb --- /dev/null +++ b/Assets/ARDK/AR/VideoFormat/_NativeARVideoFormat.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: b0284c1a0f864c39b6b23b5e35d62ebf +timeCreated: 1592706265 \ No newline at end of file diff --git a/Assets/ARDK/AR/VideoFormat/_SerializableARVideoFormat.cs b/Assets/ARDK/AR/VideoFormat/_SerializableARVideoFormat.cs new file mode 100644 index 0000000..50422d8 --- /dev/null +++ b/Assets/ARDK/AR/VideoFormat/_SerializableARVideoFormat.cs @@ -0,0 +1,28 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using UnityEngine; + +namespace Niantic.ARDK.AR.VideoFormat +{ + [Serializable] + internal sealed class _SerializableARVideoFormat: + IARVideoFormat + { + internal _SerializableARVideoFormat + ( + int framesPerSecond, + Vector2 imageResolution, + Vector2 textureResolution + ) + { + FramesPerSecond = framesPerSecond; + ImageResolution = imageResolution; + TextureResolution = textureResolution; + } + + public int FramesPerSecond { get; private set; } + public Vector2 ImageResolution { get; private set; } + public Vector2 TextureResolution { get; private set; } + } +} diff --git a/Assets/ARDK/AR/VideoFormat/_SerializableARVideoFormat.cs.meta b/Assets/ARDK/AR/VideoFormat/_SerializableARVideoFormat.cs.meta new file mode 100644 index 0000000..0062118 --- /dev/null +++ b/Assets/ARDK/AR/VideoFormat/_SerializableARVideoFormat.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 026d61b109db464caea7b018170d17ea +timeCreated: 1592705263 \ No newline at end of file diff --git a/Assets/ARDK/AR/WayspotAnchors.meta b/Assets/ARDK/AR/WayspotAnchors.meta new file mode 100644 index 0000000..e3c69ee --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 40503ef987bbd4f68875d47dd2f862f6 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/WayspotAnchors/IWayspotAnchor.cs b/Assets/ARDK/AR/WayspotAnchors/IWayspotAnchor.cs new file mode 100644 index 0000000..a7484ec --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/IWayspotAnchor.cs @@ -0,0 +1,25 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; + +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.AR.WayspotAnchors +{ + public interface IWayspotAnchor: + IDisposable + { + /// Called when the position/rotation of the wayspot anchor has been updated + /// @note This is only surfaced automatically when using the WayspotAnchorService. + /// It needs to be invoked in your application code when using the WayspotAnchorController. + ArdkEventHandler TrackingStateUpdated { get; set; } + + /// Gets the ID of the wayspot anchor + Guid ID { get; } + + /// Gets the payload for the wayspot anchor + WayspotAnchorPayload Payload { get; } + + /// Whether or not the wayspot anchor is currently being tracked + bool Tracking { get; } + } +} diff --git a/Assets/ARDK/AR/WayspotAnchors/IWayspotAnchor.cs.meta b/Assets/ARDK/AR/WayspotAnchors/IWayspotAnchor.cs.meta new file mode 100644 index 0000000..4258f4e --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/IWayspotAnchor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8bb78f7d8cd9a43babb72be3518b3c4d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/WayspotAnchors/IWayspotAnchorsConfiguration.cs b/Assets/ARDK/AR/WayspotAnchors/IWayspotAnchorsConfiguration.cs new file mode 100644 index 0000000..b5ccb70 --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/IWayspotAnchorsConfiguration.cs @@ -0,0 +1,71 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; + +namespace Niantic.ARDK.AR.WayspotAnchors +{ + /// Configuration information for a VPS localization attempt. + public interface IWayspotAnchorsConfiguration: + IDisposable + { + /// The timeout in seconds for the entire localization attempt. An attempt will send + /// localization requests until the localization succeeds, times out, or is canceled. + /// A value of -1 indicates no timeout. + /// The default is 30 seconds. + float LocalizationTimeout { get; set; } + + /// The timeout in seconds for an individual request made during the overall localization attempt. + /// A timeout of -1 indicates no timeout + /// The default is 10 seconds. + float RequestTimeLimit { get; set; } + + /// The max number of network requests per second + /// The default and maximum value is 1.0 + float RequestsPerSecond { get; set; } + + /// The max number of wayspot anchor resolutions per second + /// A value of -1 indicates no maximun (Resolve as frequent as possible). + /// The default is 1. + float MaxResolutionsPerSecond { get; set; } + + /// The number of seconds that the system is required to wait after entering a good tracking state before running + /// The default value is 3.0 + float GoodTrackingWait { get; set; } + + /// The max number of wayspot anchor resolutions per second + /// The default value is false + bool ContinuousLocalizationEnabled { get; set; } + + // The following configurations are for internal testing and debugging. + // Do not change the default values. + + /// Override option internal testing. You probably shouldn't touch this + bool CloudProcessingForced { get; set; } + + /// Override option internal testing. You probably shouldn't touch this + bool ClientProcessingForced { get; set; } + + /// The endpoint for VPS config API requests. You probably shouldn't touch this + string ConfigURL { get; set; } + + /// The endpoint for VPS health API requests. You probably shouldn't touch this + string HealthURL { get; set; } + + /// The endpoint for VPS localization API requests. You probably shouldn't touch this + string LocalizationURL { get; set; } + + /// The endpoint for VPS graph sync API requests. You probably shouldn't touch this + string GraphSyncURL { get; set; } + + /// The endpoint for VPS anchor creation API requests. You probably shouldn't touch this + string WayspotAnchorCreateURL { get; set; } + + /// The endpoint for VPS anchor resolution API requests. You probably shouldn't touch this + string WayspotAnchorResolveURL { get; set; } + + /// The endpoint for VPS node registration API requests. You probably shouldn't touch this + string RegisterNodeURL { get; set; } + + /// The endpoint for VPS node lookup API requests. You probably shouldn't touch this + string LookUpNodeURL { get; set; } + } +} diff --git a/Assets/ARDK/AR/WayspotAnchors/IWayspotAnchorsConfiguration.cs.meta b/Assets/ARDK/AR/WayspotAnchors/IWayspotAnchorsConfiguration.cs.meta new file mode 100644 index 0000000..66eb690 --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/IWayspotAnchorsConfiguration.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 903156c215a3d4698968e4c9fb053308 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/WayspotAnchors/LocalizationFailureReason.cs b/Assets/ARDK/AR/WayspotAnchors/LocalizationFailureReason.cs new file mode 100644 index 0000000..4d1b775 --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/LocalizationFailureReason.cs @@ -0,0 +1,54 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +namespace Niantic.ARDK.AR.WayspotAnchors +{ + /// Failure reasons for a failed localization + /// @see [Working with the Visual Positioning System (VPS)](@ref working_with_vps) + public enum LocalizationFailureReason + { + /// No failure, no reason. + None = 0, + + /// Failure, unknown reasons. + Unknown = 1, + + /// Failure, couldn't localize within the specified timeout period, likely + /// because the user's world tracking was unstable or the user was not + /// looking at a localize-able target. + Timeout = 2, + + /// Canceled, because StopLocalization was called. + Canceled = 3, + + // Failure, localization service is configured with an invalid URL. + InvalidEndpoint = 4, + + /// Failure to connect to localization service. + CannotConnectToServer = 5, + + /// Failure, localization service rejected the client request. + BadRequest = 6, + + /// Failure, client rejected the localization service response. + BadResponse = 7, + + /// Failure, Identifier is invalid + BadIdentifier = 8, + + /// Failure, Location permissions were not granted by the user, or no location + /// service was started by the app. + LocationDataNotAvailable = 9, + + /// Failure, based on GPS information, system determined localization was not + /// possible. + NotSupportedAtLocation = 10, + + // Serious Server Failure + InternalServerFailure = 11, + + // Failure, invalid API key + InvalidAPIKey = 12, + + // Dev is not authenticated to use VPS + Unauthenticated = 13 + } +} diff --git a/Assets/ARDK/AR/WayspotAnchors/LocalizationFailureReason.cs.meta b/Assets/ARDK/AR/WayspotAnchors/LocalizationFailureReason.cs.meta new file mode 100644 index 0000000..901614a --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/LocalizationFailureReason.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d7a66bbe35c5467c85fd1286520a8ff9 +timeCreated: 1619643136 \ No newline at end of file diff --git a/Assets/ARDK/AR/WayspotAnchors/LocalizationState.cs b/Assets/ARDK/AR/WayspotAnchors/LocalizationState.cs new file mode 100644 index 0000000..0d90deb --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/LocalizationState.cs @@ -0,0 +1,20 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +namespace Niantic.ARDK.AR.WayspotAnchors +{ + /// Possible states for a localization + /// @see [Working with the Visual Positioning System (VPS)](@ref working_with_vps) + public enum LocalizationState + { + /// System is using device and GPS information to determine if localization is possible. + Initializing = 0, + + /// Localization in process + Localizing = 1, + + /// Localization succeeded. + Localized = 2, + + /// Localization failed, a failure reason will be provided. + Failed = 3 + } +} diff --git a/Assets/ARDK/AR/WayspotAnchors/LocalizationState.cs.meta b/Assets/ARDK/AR/WayspotAnchors/LocalizationState.cs.meta new file mode 100644 index 0000000..9f2449f --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/LocalizationState.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 4293fd7207584706903a2977b10bd43e +timeCreated: 1619643103 \ No newline at end of file diff --git a/Assets/ARDK/AR/WayspotAnchors/LocalizationStateUpdatedArgs.cs b/Assets/ARDK/AR/WayspotAnchors/LocalizationStateUpdatedArgs.cs new file mode 100644 index 0000000..883119f --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/LocalizationStateUpdatedArgs.cs @@ -0,0 +1,21 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.AR.WayspotAnchors +{ + public class LocalizationStateUpdatedArgs: IArdkEventArgs + { + public LocalizationState State { get; } + public LocalizationFailureReason FailureReason { get; } + + internal LocalizationStateUpdatedArgs + ( + LocalizationState state, + LocalizationFailureReason failureReason + ) + { + State = state; + FailureReason = failureReason; + } + } +} diff --git a/Assets/ARDK/AR/WayspotAnchors/LocalizationStateUpdatedArgs.cs.meta b/Assets/ARDK/AR/WayspotAnchors/LocalizationStateUpdatedArgs.cs.meta new file mode 100644 index 0000000..b11d81b --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/LocalizationStateUpdatedArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 74c3996653f2b420784cede8d148abbf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/WayspotAnchors/MockWayspotAnchorImplementation.cs b/Assets/ARDK/AR/WayspotAnchors/MockWayspotAnchorImplementation.cs new file mode 100644 index 0000000..0d350b8 --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/MockWayspotAnchorImplementation.cs @@ -0,0 +1,230 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +using Niantic.ARDK.AR.ARSessionEventArgs; +using Niantic.ARDK.Utilities; + +using UnityEngine; + +namespace Niantic.ARDK.AR.WayspotAnchors +{ + internal sealed class MockWayspotAnchorImplementation: _IWayspotAnchorImplementation + { + /// Called when the localization state has changed + public event ArdkEventHandler LocalizationStateUpdated; + + /// Called when the status of managed poses has changed + public event ArdkEventHandler WayspotAnchorStatusUpdated; + + /// Called when new wayspot anchors have been created + public event ArdkEventHandler WayspotAnchorsCreated; + + /// Called when wayspot anchors have updated their position/rotation + public event ArdkEventHandler WayspotAnchorsResolved; + + private Dictionary _wayspotAnchors = + new Dictionary(); + + private List resolvedWayspotAnchors = new List(); + + private bool _isDisposed; + private IARSession _arSession; + private LocalizationState _localizationState; + + /// Creates a Mock Wayspot Anchor Controller + /// @param arSession The AR Session to create the mock wayspot anchor controller with + internal MockWayspotAnchorImplementation(IARSession arSession) + { + _arSession = arSession; + _arSession.Paused += HandleARSessionPaused; + _arSession.Ran += HandleARSessionRan; + _isDisposed = false; + ResolveWayspotAnchors(); + } + + /// Disposes the Mock Wayspot Anchor Controller + public void Dispose() + { + _isDisposed = true; + } + + /// Starts VPS + /// @param localizationConfiguration The configuration to start VPS with + public async void StartVPS(IWayspotAnchorsConfiguration wayspotAnchorsConfiguration) + { + await SimulateServerWork(); + _localizationState = LocalizationState.Initializing; + var initializingLocalizationStateUpdatedArgs = new LocalizationStateUpdatedArgs + (LocalizationState.Initializing, LocalizationFailureReason.None); + + LocalizationStateUpdated?.Invoke(initializingLocalizationStateUpdatedArgs); + + await SimulateServerWork(); + _localizationState = LocalizationState.Localizing; + var localizingLocalizationStateUpdatedArgs = new LocalizationStateUpdatedArgs + (LocalizationState.Localizing, LocalizationFailureReason.None); + + LocalizationStateUpdated?.Invoke(localizingLocalizationStateUpdatedArgs); + + await SimulateServerWork(); + _localizationState = LocalizationState.Localized; + var localizedLocalizationStateUpdatedArgs = new LocalizationStateUpdatedArgs + (LocalizationState.Localized, LocalizationFailureReason.None); + + LocalizationStateUpdated?.Invoke(localizedLocalizationStateUpdatedArgs); + } + + /// Stops VPS + public async void StopVPS() + { + await SimulateServerWork(); + var localizedLocalizationStateUpdatedArgs = new LocalizationStateUpdatedArgs + (LocalizationState.Failed, LocalizationFailureReason.Canceled); + + LocalizationStateUpdated?.Invoke(localizedLocalizationStateUpdatedArgs); + } + + /// Creates new wayspot anchors with position and rotation + /// @param localPoses The position and rotation of the new wayspot anchors to create + /// @return The IDs of the newly created wayspot anchors + public Guid[] CreateWayspotAnchors(params Matrix4x4[] localPoses) + { + var createdWayspotAnchors = new Dictionary(); + var ids = new List(); + var statuses = new List(); + foreach (var localPose in localPoses) + { + var id = Guid.NewGuid(); + ids.Add(id); + createdWayspotAnchors.Add(id, localPose); + var status = new WayspotAnchorStatusUpdate(id, WayspotAnchorStatusCode.Pending); + statuses.Add(status); + } + + var wayspotAnchorStatusUpdatedArgs = new WayspotAnchorStatusUpdatedArgs(statuses.ToArray()); + WayspotAnchorStatusUpdated?.Invoke(wayspotAnchorStatusUpdatedArgs); + CreateWayspotAnchors(createdWayspotAnchors); + return ids.ToArray(); + } + + /// Starts resolving the wayspot anchors. Anchors that are being resolved will report changes in position and rotation via the WayspotAnchorsResolved event + /// @param wayspotAnchors The wayspot anchors to start resolving + public async void StartResolvingWayspotAnchors(params IWayspotAnchor[] wayspotAnchors) + { + await SimulateServerWork(); + var ids = wayspotAnchors.Select(p => p.ID); + var createdWayspotAnchors = wayspotAnchors.Where + (p => !_wayspotAnchors.ContainsKey(p.ID)) + .Select(p => (_MockWayspotAnchor)p); + + CreateWayspotAnchors(createdWayspotAnchors.ToArray()); + resolvedWayspotAnchors.AddRange(ids); + } + + /// Stops resolving the wayspot anchors + /// param wayspotAnchors Wayspot anchors to stop resolving + public async void StopResolvingWayspotAnchors(params IWayspotAnchor[] wayspotAnchors) + { + await SimulateServerWork(); + var ids = wayspotAnchors.Select(p => p.ID); + foreach (var id in ids) + { + resolvedWayspotAnchors.Remove(id); + } + } + + private async void HandleARSessionPaused(ARSessionPausedArgs arSessionPausedArgs) + { + await SimulateServerWork(); + _localizationState = LocalizationState.Localizing; + var localizedLocalizationStateUpdatedArgs = new LocalizationStateUpdatedArgs + (LocalizationState.Localizing, LocalizationFailureReason.None); + + LocalizationStateUpdated?.Invoke(localizedLocalizationStateUpdatedArgs); + } + + private async void HandleARSessionRan(ARSessionRanArgs args) + { + await SimulateServerWork(); + _localizationState = LocalizationState.Localized; + var localizedLocalizationStateUpdatedArgs = new LocalizationStateUpdatedArgs + (LocalizationState.Localized, LocalizationFailureReason.None); + + LocalizationStateUpdated?.Invoke(localizedLocalizationStateUpdatedArgs); + } + + private async void CreateWayspotAnchors(Dictionary localPoses) + { + await SimulateServerWork(); + var createdWayspotAnchors = new List(); + foreach (var localPose in localPoses) + { + var wayspotAnchor = new _MockWayspotAnchor(localPose.Key, localPose.Value); + createdWayspotAnchors.Add(wayspotAnchor); + _wayspotAnchors.Add(wayspotAnchor.ID, wayspotAnchor); + } + + var wayspotAnchorsCreatedArgs = new WayspotAnchorsCreatedArgs + (createdWayspotAnchors.ToArray()); + + WayspotAnchorsCreated?.Invoke(wayspotAnchorsCreatedArgs); + var statuses = new List(); + foreach (var createdWayspotAnchor in createdWayspotAnchors) + { + var id = createdWayspotAnchor.ID; + var status = new WayspotAnchorStatusUpdate(id, WayspotAnchorStatusCode.Success); + statuses.Add(status); + } + + var wayspotAnchorStatusUpdatedArgs = new WayspotAnchorStatusUpdatedArgs(statuses.ToArray()); + WayspotAnchorStatusUpdated?.Invoke(wayspotAnchorStatusUpdatedArgs); + } + + private void CreateWayspotAnchors(params _MockWayspotAnchor[] wayspotAnchors) + { + var statuses = new List(); + foreach (var wayspotAnchor in wayspotAnchors) + { + var id = wayspotAnchor.ID; + _wayspotAnchors.Add(id, wayspotAnchor); + var status = new WayspotAnchorStatusUpdate(id, WayspotAnchorStatusCode.Success); + statuses.Add(status); + } + + var wayspotAnchorStatusUpdatedArgs = new WayspotAnchorStatusUpdatedArgs(statuses.ToArray()); + WayspotAnchorStatusUpdated?.Invoke(wayspotAnchorStatusUpdatedArgs); + } + + private async void ResolveWayspotAnchors() + { + while (!_isDisposed) + { + if (_localizationState != LocalizationState.Localized) + { + await Task.Delay(1); + continue; + } + await SimulateServerWork(); + var resolutions = new List(); + foreach (var id in resolvedWayspotAnchors) + { + var wayspotAnchor = _wayspotAnchors[id]; + var localPose = wayspotAnchor.LocalPose; + var resolution = new WayspotAnchorResolvedArgs(id, localPose); + resolutions.Add(resolution); + } + + var wayspotAnchorsResolvedArgs = new WayspotAnchorsResolvedArgs(resolutions.ToArray()); + WayspotAnchorsResolved?.Invoke(wayspotAnchorsResolvedArgs); + } + } + + private async Task SimulateServerWork() + { + await Task.Delay(100); + } + } +} diff --git a/Assets/ARDK/AR/WayspotAnchors/MockWayspotAnchorImplementation.cs.meta b/Assets/ARDK/AR/WayspotAnchors/MockWayspotAnchorImplementation.cs.meta new file mode 100644 index 0000000..4b9c70c --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/MockWayspotAnchorImplementation.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e7d8b5db6981d42abac1f0f218989f6b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/WayspotAnchors/NativeWayspotAnchorImplementation.cs b/Assets/ARDK/AR/WayspotAnchors/NativeWayspotAnchorImplementation.cs new file mode 100644 index 0000000..41b404b --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/NativeWayspotAnchorImplementation.cs @@ -0,0 +1,816 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; +using System.Runtime.InteropServices; + +using AOT; + +using Niantic.ARDK.Internals; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; + +namespace Niantic.ARDK.AR.WayspotAnchors +{ + internal sealed class NativeWayspotAnchorImplementation: + _ThreadCheckedObject, + _IWayspotAnchorImplementation + { + // Private handles and code to deal with native callbacks and initialization + private IntPtr _nativeHandle; + + // Caching `this` for native device callbacks + private IntPtr _cachedHandleIntPtr = IntPtr.Zero; + private SafeGCHandle _cachedHandle; + + private IntPtr _handle + { + get + { + _CheckThread(); + + var cachedHandleIntPtr = _cachedHandleIntPtr; + if (cachedHandleIntPtr != IntPtr.Zero) + return cachedHandleIntPtr; + + _cachedHandle = SafeGCHandle.Alloc(this); + cachedHandleIntPtr = _cachedHandle.ToIntPtr(); + _cachedHandleIntPtr = cachedHandleIntPtr; + + return cachedHandleIntPtr; + } + } + + private readonly IARSession _arSession; + + private ArdkEventHandler _localizationStateUpdated; + + /// Called when the localization state has changed + public event ArdkEventHandler LocalizationStateUpdated + { + add + { + _CheckThread(); + + _SubscribeToDidUpdateLocalizationState(); + + _localizationStateUpdated += value; + } + remove + { + _localizationStateUpdated -= value; + } + } + + private ArdkEventHandler _wayspotAnchorStatusesUpdated; + + /// Called when the status of wayspot anchors has changed + public event ArdkEventHandler WayspotAnchorStatusUpdated + { + add + { + _CheckThread(); + + _SubscribeToDidUpdateWayspotAnchorStatuses(); + + _wayspotAnchorStatusesUpdated += value; + } + remove + { + _wayspotAnchorStatusesUpdated -= value; + } + } + + private ArdkEventHandler _wayspotAnchorsCreated; + + /// Called when new wayspot anchors have been created + public event ArdkEventHandler WayspotAnchorsCreated + { + add + { + _CheckThread(); + + _SubscribeToDidCreateWayspotAnchors(); + + _wayspotAnchorsCreated += value; + } + remove + { + _wayspotAnchorsCreated -= value; + } + } + + private ArdkEventHandler _wayspotAnchorsResolved; + + /// Called when wayspot anchors have been resolved + public event ArdkEventHandler WayspotAnchorsResolved + { + add + { + _CheckThread(); + + _SubscribeToDidResoveWayspotAnchors(); + + _wayspotAnchorsResolved += value; + } + remove + { + _wayspotAnchorsResolved -= value; + } + } + + /// Creates a new native wayspot anchor controller + /// @param session The session used to create the native wayspot anchor controller + internal NativeWayspotAnchorImplementation(IARSession session) + { + _arSession = session; + _nativeHandle = _NAR_ManagedPoseController_Init(session.StageIdentifier.ToByteArray()); + if (_nativeHandle == IntPtr.Zero) + throw new ArgumentException("nativeHandle can't be Zero.", nameof(_nativeHandle)); + } + + /// Creates new wayspot anchors + /// @param localPoses The local poses (position and rotation only) used to create the wayspot anchors + /// @return The IDs of the newly created wayspot anchors + public Guid[] CreateWayspotAnchors(params Matrix4x4[] localPoses) + { + _CheckThread(); + + var numPoses = localPoses.Length; + float[] nativeTransforms = new float[16 * numPoses]; + for (int i = 0; i < numPoses; i++) + { + var poseArray = _Convert.Matrix4x4ToInternalArray + (NARConversions.FromUnityToNAR(localPoses[i])); + + for (int x = 0; x < 16; x++) + { + nativeTransforms[16 * i + x] = poseArray[x]; + } + } + + int kBytesPerIdentifier = 16; + byte[] identifierByteArrayOut = new byte[kBytesPerIdentifier * numPoses]; + + unsafe + { + fixed (byte* ptr = identifierByteArrayOut) + { + IntPtr identifierPtr = (IntPtr)ptr; + _NAR_ManagedPoseController_CreateManagedPoses + ( + _nativeHandle, + (UInt64)numPoses, + nativeTransforms, + identifierPtr + ); + } + } + + var identifierArrayOut = new Guid[numPoses]; + for (int i = 0; i < numPoses; i++) + { + byte[] identifierBytes = new byte[kBytesPerIdentifier]; + for (int b = 0; b < kBytesPerIdentifier; b++) + { + identifierBytes[b] = identifierByteArrayOut[kBytesPerIdentifier * i + b]; + } + + identifierArrayOut[i] = new Guid(identifierBytes); + } + + return identifierArrayOut; + } + + /// Starts resolving wayspot anchors. Resolving anchors will have their position and rotation updates reported via the _wayspotAnchorsResolved + /// event + /// @param wayspotAnchors The wayspot anchors to update + public void StartResolvingWayspotAnchors(params IWayspotAnchor[] wayspotAnchors) + { + _CheckThread(); + + if (!_ValidateARSessionIsAlive()) + { + throw new Exception("AR Session validation has failed."); + } + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + var numPoses = wayspotAnchors.Length; + + IntPtr[] wayspotAnchorsHandles = new IntPtr[numPoses]; + for (int i = 0; i < numPoses; i++) + { + var wayspotAnchor = wayspotAnchors[i]; + if (wayspotAnchor is _NativeWayspotAnchor nativeWayspotAnchor) + { + wayspotAnchorsHandles[i] = nativeWayspotAnchor._NativeHandle; + } + else + { + ARLog._Error + ( + $"Must use a {nameof(_NativeWayspotAnchor)} with {nameof(NativeWayspotAnchorImplementation)}" + ); + + return; + } + } + + _NAR_ManagedPoseController_StartResolvingManagedPoses(_nativeHandle, (UInt64)numPoses, wayspotAnchorsHandles); + } + } + + /// Stops resolving the wayspot anchors + /// @param wayspotAnchors The wayspot anchors to stop resolving + public void StopResolvingWayspotAnchors(params IWayspotAnchor[] wayspotAnchors) + { + _CheckThread(); + + if (!_ValidateARSessionIsAlive()) + { + ARLog._Error("The ARSession is deinitialized, cannot stop localization"); + return; + } + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + var numPoses = wayspotAnchors.Length; + + IntPtr[] wayspotAnchorHandles = new IntPtr[numPoses]; + for (int i = 0; i < numPoses; i++) + { + var wayspotAnchor = wayspotAnchors[i]; + if (wayspotAnchor is _NativeWayspotAnchor nativeWayspotAnchor) + { + wayspotAnchorHandles[i] = nativeWayspotAnchor._NativeHandle; + } + else + { + var error = "Must use a _NativeManagedPose with _NativeManagedPoseController"; + ARLog._Error(error); + return; + } + } + + _NAR_ManagedPoseController_StopResolvingManagedPoses + (_nativeHandle, (UInt64)numPoses, wayspotAnchorHandles); + } + } + + /// Whether or not the native wayspot anchor controller has been destroyed + public bool IsDestroyed + { + get => _nativeHandle == IntPtr.Zero; + } + + /// Disposees of the native wayspot anchor controller + public void Dispose() + { + _CheckThread(); + + GC.SuppressFinalize(this); + + var nativeHandle = _nativeHandle; + if (nativeHandle != IntPtr.Zero) + { + _nativeHandle = IntPtr.Zero; + + _ReleaseImmediate(nativeHandle); + } + + _cachedHandle.Free(); + _cachedHandleIntPtr = IntPtr.Zero; + } + + /// + public void StartVPS(IWayspotAnchorsConfiguration wayspotAnchorsConfiguration) + { + _CheckThread(); + + if (wayspotAnchorsConfiguration == null) + { + throw new ArgumentNullException(nameof(wayspotAnchorsConfiguration)); + } + + if (!_ValidateARSessionIsAlive()) + { + ARLog._Error("The ARSession is deinitialized, cannot start localization"); + return; + } + + if (_arSession is _NativeARSession nativeSession) + { + if (!nativeSession._IsLocationServiceInitialized()) + { + ARLog._Error + ( + "SetupLocationService(locationService) must be called before attempting to localize" + + " against any available world coordinate space." + ); + + return; + } + } + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + if (wayspotAnchorsConfiguration is _NativeWayspotAnchorsConfiguration nativeConfig) + { + _NAR_ManagedPoseController_StartVPS + ( + _nativeHandle, + nativeConfig._NativeHandle + ); + } + else + { + ARLog._Error + ( + $"Must use a {nameof(_NativeWayspotAnchorsConfiguration)} with {nameof(NativeWayspotAnchorImplementation)}" + ); + } + } + } + + /// + public void StopVPS() + { + _CheckThread(); + + if (!_ValidateARSessionIsAlive()) + { + ARLog._Error("The ARSession is deinitialized, cannot stop localization"); + return; + } + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NAR_ManagedPoseController_StopVPS(_nativeHandle); + } + + private static void _ReleaseImmediate(IntPtr nativeHandle) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + _NAR_ManagedPoseController_Release(nativeHandle); + } + } + + private bool _ValidateARSessionIsAlive() + { + if (_arSession is _NativeARSession nativeSession) + { + return !nativeSession.IsDestroyed; + } + + ARLog._Error + ( + $"Must use a {nameof(_NativeWayspotAnchorsConfiguration)} with ${nameof(NativeWayspotAnchorImplementation)}" + ); + + return false; + } + + private bool _onDidUpdateLocalizationState; + + private void _SubscribeToDidUpdateLocalizationState() + { + _CheckThread(); + + if (_onDidUpdateLocalizationState) + return; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + _NAR_ManagedPoseController_Set_didUpdateLocalizationStateCallback + ( + _handle, + _nativeHandle, + _onDidUpdateLocalizationStateNative + ); + + ARLog._Debug("Subscribed to native localization updated"); + } + + _onDidUpdateLocalizationState = true; + } + + private bool _onDidUpdateWayspotAnchorStatuses; + + private void _SubscribeToDidUpdateWayspotAnchorStatuses() + { + _CheckThread(); + + if (_onDidUpdateWayspotAnchorStatuses) + return; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + _NAR_ManagedPoseController_Set_didUpdateManagedPoseStatusCodesCallback + ( + _handle, + _nativeHandle, + _onDidUpdateManagedPoseStatusesNative + ); + + ARLog._Debug("Subscribed to native localization updated"); + } + + _onDidUpdateWayspotAnchorStatuses = true; + } + + private bool _onDidCreateWayspotAnchors; + + private void _SubscribeToDidCreateWayspotAnchors() + { + _CheckThread(); + + if (_onDidCreateWayspotAnchors) + return; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + _NAR_ManagedPoseController_Set_didCreateManagedPosesCallback + ( + _handle, + _nativeHandle, + _onDidCreateManagedPosesNative + ); + + ARLog._Debug("Subscribed to native localization updated"); + } + + _onDidCreateWayspotAnchors = true; + } + + private bool _onDidResolveWayspotAnchors; + + private void _SubscribeToDidResoveWayspotAnchors() + { + _CheckThread(); + + if (_onDidResolveWayspotAnchors) + return; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + _NAR_ManagedPoseController_Set_didResolveManagedPosesCallback + ( + _handle, + _nativeHandle, + _onDidResolveManagedPosesNative + ); + + ARLog._Debug("Subscribed to native localization updated"); + } + + _onDidResolveWayspotAnchors = true; + } + + +#region NativeCallbacks + [MonoPInvokeCallback(typeof(_onDidUpdateLocalizationState_Definition))] + private static void _onDidUpdateLocalizationStateNative + ( + IntPtr context, + UInt32 state, + UInt32 failureReason + ) + { + var controller = SafeGCHandle.TryGetInstance(context); + if (controller == null || controller.IsDestroyed) + { + // controller was deallocated + ARLog._Debug("controller is null in _onDidUpdateLocalizationStateNative()"); + return; + } + + _CallbackQueue.QueueCallback + ( + () => + { + if (controller.IsDestroyed) + { + // controller was deallocated + return; + } + + if (controller._localizationStateUpdated != null) + { + var args = + new LocalizationStateUpdatedArgs + ( + (LocalizationState)state, + (LocalizationFailureReason)failureReason + ); + + controller._localizationStateUpdated(args); + } + } + ); + } + + [MonoPInvokeCallback(typeof(_onDidUpdateManagedPoseStatusesDefinition))] + private static void _onDidUpdateManagedPoseStatusesNative + ( + IntPtr context, + IntPtr identifiers, + IntPtr statusCodes, + UInt64 numOfWayspotAnchors + ) + { + int kBytesPerIdentifier = 16; + int count = (int)numOfWayspotAnchors; + byte[] byteArray = new byte[count * kBytesPerIdentifier]; + Guid[] guids = new Guid[count]; + Marshal.Copy(identifiers, byteArray, 0, count * kBytesPerIdentifier); + for (int i = 0; i < count; i++) + { + byte[] identifierBytes = new byte[kBytesPerIdentifier]; + for (int b = 0; b < kBytesPerIdentifier; b++) + { + identifierBytes[b] = byteArray[kBytesPerIdentifier * i + b]; + } + guids[i] = new Guid(identifierBytes); + } + + + int numStatusCodes = (int)numOfWayspotAnchors; + int[] statusCodesArray = new int[numStatusCodes]; + Marshal.Copy(statusCodes, statusCodesArray, 0, numStatusCodes); + + + var controller = SafeGCHandle.TryGetInstance(context); + if (controller == null || controller.IsDestroyed) + { + // controller was deallocated + ARLog._Debug("controller is null in _onDidUpdateManagedPoseStatusesNative()"); + return; + } + + _CallbackQueue.QueueCallback + ( + () => + { + if (controller.IsDestroyed) + { + // controller was deallocated + return; + } + + if (controller._wayspotAnchorStatusesUpdated != null) + { + WayspotAnchorStatusUpdate[] statusesArray = new WayspotAnchorStatusUpdate[numOfWayspotAnchors]; + for (int i = 0; i < (int)numOfWayspotAnchors; i++) + { + var status = new WayspotAnchorStatusUpdate + ( + guids[i], + (WayspotAnchorStatusCode)statusCodesArray[i] + ); + statusesArray[i] = status; + } + + var args = new WayspotAnchorStatusUpdatedArgs(statusesArray); + controller._wayspotAnchorStatusesUpdated(args); + } + } + ); + } + + [MonoPInvokeCallback(typeof(_onDidCreateManagedPoses_Definition))] + private static void _onDidCreateManagedPosesNative + ( + IntPtr context, + IntPtr[] wayspotAnchorHandles, + UInt64 numOfWayspotAnchors + ) + { + var controller = SafeGCHandle.TryGetInstance(context); + if (controller == null || controller.IsDestroyed) + { + // controller was deallocated + ARLog._Debug("controller is null in _onDidCreateManagedPosesNative()"); + return; + } + + _CallbackQueue.QueueCallback + ( + () => + { + if (controller.IsDestroyed) + { + // controller was deallocated + return; + } + + if (controller._wayspotAnchorsCreated != null) + { + IWayspotAnchor[] wayspotAnchors = new IWayspotAnchor[numOfWayspotAnchors]; + for (int i = 0; i < (int)numOfWayspotAnchors; i++) + { + var wayspotAnchor = new _NativeWayspotAnchor(wayspotAnchorHandles[i]); + wayspotAnchors[i] = wayspotAnchor; + } + + var args = new WayspotAnchorsCreatedArgs(wayspotAnchors); + + controller._wayspotAnchorsCreated(args); + } + } + ); + } + + [MonoPInvokeCallback(typeof(_onDidResolveManagedPoses_Definition))] + private static void _onDidResolveManagedPosesNative + ( + IntPtr context, + IntPtr identifiers, //guid[] + IntPtr localPoses, //float[] + IntPtr accuracies, //float[] + UInt64 numOfWayspotAnchors + ) + { + int count = (int)numOfWayspotAnchors; + if (count <= 0) + { + ARLog._Error($"Invalid number of managed poses resolved! ({count})"); + return; + } + byte[] byteArray = new byte[count * 16]; + Guid[] guids = new Guid[count]; + Marshal.Copy(identifiers, byteArray, 0, count * 16); + for (int i = 0; i < count; i++) + { + byte[] identifierBytes = new byte[16]; + for (int b = 0; b < 16; b++) + { + identifierBytes[b] = byteArray[16 * i + b]; + } + + guids[i] = new Guid(identifierBytes); + } + + int lpSize = (int)numOfWayspotAnchors * 16; + float[] lp = new float[lpSize]; + Marshal.Copy(localPoses, lp, 0, lpSize); + + int accSize = (int)numOfWayspotAnchors * 6; + float[] acc = new float[accSize]; + Marshal.Copy(accuracies, acc, 0, accSize); + + var controller = SafeGCHandle.TryGetInstance(context); + if (controller == null || controller.IsDestroyed) + { + // controller was deallocated + ARLog._Debug("controller is null in _onDidResolveManagedPosesNative()"); + return; + } + + _CallbackQueue.QueueCallback + ( + () => + { + if (controller.IsDestroyed) + { + // controller was deallocated + return; + } + + if (controller._wayspotAnchorsResolved != null) + { + var resolutions = new WayspotAnchorResolvedArgs[numOfWayspotAnchors]; + for (int i = 0; i < (int)numOfWayspotAnchors; i++) + { + float[] localPoseArray = new float[16]; + for (int x = 0; x < 16; x++) + { + localPoseArray[x] = lp[i * 16 + x]; + } + + var localPoseTransform = NARConversions.FromNARToUnity + (_Convert.InternalToMatrix4x4(localPoseArray)); + + var resolution = new WayspotAnchorResolvedArgs(guids[i], localPoseTransform); + resolutions[i] = resolution; + } + + var args = new WayspotAnchorsResolvedArgs(resolutions); + + controller._wayspotAnchorsResolved(args); + } + } + ); + } +#endregion + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NAR_ManagedPoseController_Init(byte[] stageIdentifier); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NAR_ManagedPoseController_Release(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern bool _NAR_ManagedPoseController_StartVPS + ( + IntPtr nativeHandle, + IntPtr nativeConfigHandle + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern bool _NAR_ManagedPoseController_StopVPS(IntPtr nativeHandle); + + + [DllImport(_ARDKLibrary.libraryName)] + private static extern bool _NAR_ManagedPoseController_CreateManagedPoses + ( + IntPtr nativeHandle, + UInt64 numOfWayspotAnchors, + float[] localPosesIn, + IntPtr wayspotAnchorIdsOut + ); + + + [DllImport(_ARDKLibrary.libraryName)] + private static extern bool _NAR_ManagedPoseController_StartResolvingManagedPoses + ( + IntPtr nativeHandle, + UInt64 numOfWayspotAnchors, + IntPtr[] wayspotAnchorHandlesArray + ); + + + [DllImport(_ARDKLibrary.libraryName)] + private static extern bool _NAR_ManagedPoseController_StopResolvingManagedPoses + ( + IntPtr nativeHandle, + UInt64 numOfWayspotAnchors, + IntPtr[] wayspotAnchorHandlesArray + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NAR_ManagedPoseController_Set_didUpdateLocalizationStateCallback + ( + IntPtr applicationSession, + IntPtr platformSession, + _onDidUpdateLocalizationState_Definition callback + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void + _NAR_ManagedPoseController_Set_didUpdateManagedPoseStatusCodesCallback + ( + IntPtr applicationSession, + IntPtr platformSession, + _onDidUpdateManagedPoseStatusesDefinition callback + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NAR_ManagedPoseController_Set_didCreateManagedPosesCallback + ( + IntPtr applicationSession, + IntPtr platformSession, + _onDidCreateManagedPoses_Definition callback + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NAR_ManagedPoseController_Set_didResolveManagedPosesCallback + ( + IntPtr applicationSession, + IntPtr platformSession, + _onDidResolveManagedPoses_Definition callback + ); + + private delegate void _onDidUpdateLocalizationState_Definition + ( + IntPtr handle, + UInt32 state, + UInt32 error + ); + + + private delegate void _onDidUpdateManagedPoseStatusesDefinition + ( + IntPtr handle, + IntPtr identifierArrays, + IntPtr statusCodes, + UInt64 numOfWayspotAnchors + ); + + private delegate void _onDidCreateManagedPoses_Definition + ( + IntPtr handle, + IntPtr[] wayspotAnchorHandles, + UInt64 numOfWayspotAnchors + ); + + private delegate void _onDidResolveManagedPoses_Definition + ( + IntPtr handle, + IntPtr identifierArrays, + IntPtr localPoses, + IntPtr accuracies, + UInt64 numOfWayspotAnchors + ); + } +} diff --git a/Assets/ARDK/AR/WayspotAnchors/NativeWayspotAnchorImplementation.cs.meta b/Assets/ARDK/AR/WayspotAnchors/NativeWayspotAnchorImplementation.cs.meta new file mode 100644 index 0000000..e033ea6 --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/NativeWayspotAnchorImplementation.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6af37f5b863404521866d2f51ed81afd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorController.cs b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorController.cs new file mode 100644 index 0000000..9c7acac --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorController.cs @@ -0,0 +1,183 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; +using System.Collections.Generic; +using System.ComponentModel; + +using Niantic.ARDK.AR.ARSessionEventArgs; +using Niantic.ARDK.LocationService; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; + +namespace Niantic.ARDK.AR.WayspotAnchors +{ + public class WayspotAnchorController + { + /// Called when the localization status has changed + public ArdkEventHandler LocalizationStateUpdated; + + /// Called when new anchors have been created + public ArdkEventHandler WayspotAnchorsCreated; + + /// Called when wayspot anchors report a new position/rotation + public ArdkEventHandler WayspotAnchorsTrackingUpdated; + + /// Called when the status of wayspot anchors has changed + public ArdkEventHandler WayspotAnchorStatusUpdated; + + private IARSession _arSession; + private _IWayspotAnchorImplementation _wayspotAnchorImplementation; + private LocalizationState _localizationState; + + /// Creates a new wayspot anchor API to consume + /// @param arSession The AR session required by the WayspotAnchorController to run VPS. + /// @param locationService The location service required by the WayspotAnchorController to run VPS. + public WayspotAnchorController(IARSession arSession, ILocationService locationService) + { + _arSession = arSession; + _arSession.SetupLocationService(locationService); + _arSession.Deinitialized += HandleSessionDeinitialized; + _wayspotAnchorImplementation = CreateWayspotAnchorController(); + } + + /// Starts the virtual position system + /// @param wayspotAnchorsConfiguration The configuration to start VPS with + public void StartVps(IWayspotAnchorsConfiguration wayspotAnchorsConfiguration) + { + _wayspotAnchorImplementation.StartVPS(wayspotAnchorsConfiguration); + ARLog._Debug($"Started VPS for Stage ID: {_arSession.StageIdentifier}"); + } + + /// Stops the virtual position system + /// @note This will reset the state and stop all pending creations and trackings + public void StopVps() + { + _wayspotAnchorImplementation.StopVPS(); + } + + /// Creates new wayspot anchors based on position and rotations + /// @param localPoses The position and rotation used to create new wayspot anchors with + /// @return The IDs of the newly created wayspot anchors + public Guid[] CreateWayspotAnchors(params Matrix4x4[] localPoses) + { + if (_localizationState != LocalizationState.Localized) + { + ARLog._Error + ( + $"Failed to create wayspot anchor, because the Localization State is {_localizationState}." + ); + + return Array.Empty(); + } + + return _wayspotAnchorImplementation.CreateWayspotAnchors(localPoses); + } + + /// Pauses the tracking of wayspot anchors. This can be used to conserve resources for wayspot anchors which you currently do not care about, + /// but may again in the future + /// @param wayspotAnchors The wayspot anchors to pause tracking for + public void PauseTracking(params IWayspotAnchor[] wayspotAnchors) + { + _wayspotAnchorImplementation.StopResolvingWayspotAnchors(wayspotAnchors); + foreach (var wayspotAnchor in wayspotAnchors) + { + var trackable = ((_IInternalTrackable)wayspotAnchor); + trackable.SetTrackingEnabled(false); + } + } + + /// Resumes the tracking of previously paused wayspot anchors + /// @param wayspotAnchors The wayspot anchors to resume tracking for + public void ResumeTracking(params IWayspotAnchor[] wayspotAnchors) + { + _wayspotAnchorImplementation.StartResolvingWayspotAnchors(wayspotAnchors); + foreach (var wayspotAnchor in wayspotAnchors) + { + var trackable = ((_IInternalTrackable)wayspotAnchor); + trackable.SetTrackingEnabled(true); + } + } + + /// Restores previously created wayspot anchors via their payloads. Use this to restore wayspot anchors from the payload stored in your database + /// from a another session. + /// @param wayspotAnchorPayloads The payload (data) used to restore previously created wayspot anchors + /// @return The restored wayspot anchors + public IWayspotAnchor[] RestoreWayspotAnchors(params WayspotAnchorPayload[] wayspotAnchorPayloads) + { + var wayspotAnchors = new List(); + foreach (var wayspotAnchorPayload in wayspotAnchorPayloads) + { + byte[] blob = wayspotAnchorPayload._Blob; + #if UNITY_EDITOR + var wayspotAnchor = new _MockWayspotAnchor(blob); + #else + var wayspotAnchor = new _NativeWayspotAnchor(blob); + #endif + wayspotAnchors.Add(wayspotAnchor); + } + + return wayspotAnchors.ToArray(); + } + + private void HandleSessionDeinitialized(ARSessionDeinitializedArgs arSessionDeinitializedArgs) + { + _arSession.Deinitialized -= HandleSessionDeinitialized; + _wayspotAnchorImplementation.LocalizationStateUpdated -= HandleLocalizationStateUpdated; + _wayspotAnchorImplementation.WayspotAnchorsCreated -= HandleWayspotAnchorsCreated; + _wayspotAnchorImplementation.WayspotAnchorsResolved -= HandleWayspotAnchorsResolved; + _wayspotAnchorImplementation.WayspotAnchorStatusUpdated -= HandleWayspotAnchorStatusUpdated; + + _wayspotAnchorImplementation.Dispose(); + } + + private _IWayspotAnchorImplementation CreateWayspotAnchorController() + { + _IWayspotAnchorImplementation wayspotAnchorImplementation; + switch (_arSession.RuntimeEnvironment) + { + case RuntimeEnvironment.Default: + case RuntimeEnvironment.Remote: + throw new NotImplementedException($"Remote runtime environment not yet supported."); + case RuntimeEnvironment.LiveDevice: + wayspotAnchorImplementation = new NativeWayspotAnchorImplementation(_arSession); + break; + + case RuntimeEnvironment.Mock: + wayspotAnchorImplementation = new MockWayspotAnchorImplementation(_arSession); + break; + + default: + throw new InvalidEnumArgumentException($"Invalid runtime environment! ({_arSession.RuntimeEnvironment})."); + } + + wayspotAnchorImplementation.LocalizationStateUpdated += HandleLocalizationStateUpdated; + wayspotAnchorImplementation.WayspotAnchorsCreated += HandleWayspotAnchorsCreated; + wayspotAnchorImplementation.WayspotAnchorsResolved += HandleWayspotAnchorsResolved; + wayspotAnchorImplementation.WayspotAnchorStatusUpdated += HandleWayspotAnchorStatusUpdated; + + return wayspotAnchorImplementation; + } + + private void HandleLocalizationStateUpdated(LocalizationStateUpdatedArgs localizationStateUpdatedArgs) + { + _localizationState = localizationStateUpdatedArgs.State; + LocalizationStateUpdated?.Invoke(localizationStateUpdatedArgs); + } + + private void HandleWayspotAnchorsCreated(WayspotAnchorsCreatedArgs wayspotAnchorsCreatedArgs) + { + WayspotAnchorsCreated?.Invoke(wayspotAnchorsCreatedArgs); + } + + private void HandleWayspotAnchorsResolved(WayspotAnchorsResolvedArgs wayspotAnchorsResolvedArgs) + { + WayspotAnchorsTrackingUpdated?.Invoke(wayspotAnchorsResolvedArgs); + } + + private void HandleWayspotAnchorStatusUpdated(WayspotAnchorStatusUpdatedArgs wayspotAnchorStatusUpdatedArgs) + { + WayspotAnchorStatusUpdated?.Invoke(wayspotAnchorStatusUpdatedArgs); + } + } +} diff --git a/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorController.cs.meta b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorController.cs.meta new file mode 100644 index 0000000..258011e --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorController.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3cfd5cf6e25da499d98613a917270590 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorPayload.cs b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorPayload.cs new file mode 100644 index 0000000..2ffecdd --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorPayload.cs @@ -0,0 +1,39 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; + +namespace Niantic.ARDK.AR.WayspotAnchors +{ + /// The wayspot anchor payload is the container for data used to save and recover wayspot anchors, via the RecoverWayspotAnchor methods + public class WayspotAnchorPayload + { + /// The blob of data sent to C++ to create a waypoint anchor. This is retrieved from the initially created waypoint anchor + internal byte[] _Blob { get; } + + /// Creates a new payload for a waypoint anchor + /// @param blob The data blob to create the payload with + internal WayspotAnchorPayload(byte[] blob) + { + _Blob = blob; + } + + /// Serializes the payload into a string that can be stored in external storage for later recovery + /// @return The string to save + public string Serialize() + { + string data = Convert.ToBase64String(_Blob); + + return data; + } + + /// Deserializes the previously serialized payload back into a payload + /// @param data The string from a previously serialized payload + /// The payload created from the data + public static WayspotAnchorPayload Deserialize(string data) + { + var blob = Convert.FromBase64String(data); + var payload = new WayspotAnchorPayload(blob); + + return payload; + } + } +} diff --git a/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorPayload.cs.meta b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorPayload.cs.meta new file mode 100644 index 0000000..21871d2 --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorPayload.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3489a19e3f9ea475f8c0ea27ec3aef92 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorResolvedArgs.cs b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorResolvedArgs.cs new file mode 100644 index 0000000..1bd92ee --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorResolvedArgs.cs @@ -0,0 +1,31 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; + +using Niantic.ARDK.Utilities; + +using UnityEngine; + +namespace Niantic.ARDK.AR.WayspotAnchors +{ + public class WayspotAnchorResolvedArgs: IArdkEventArgs + { + /// The ID of the wayspot anchor being resolved + public Guid ID { get; } + + /// The new position of the wayspot anchor + public Vector3 Position { get; } + + /// The new rotation of the wayspot anchor + public Quaternion Rotation { get; } + + /// Creates the args for wayspot anchor resolutions + /// param id The ID of the wayspot anchor being resolved + /// param localPose The new local pose of the wayspot anchor being resolved + internal WayspotAnchorResolvedArgs(Guid id, Matrix4x4 localPose) + { + ID = id; + Position = localPose.ToPosition(); + Rotation = localPose.ToRotation(); + } + } +} diff --git a/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorResolvedArgs.cs.meta b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorResolvedArgs.cs.meta new file mode 100644 index 0000000..3bd5e44 --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorResolvedArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3e956e99d619b45a08e5769af87e4e74 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorService.cs b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorService.cs new file mode 100644 index 0000000..cd1b82e --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorService.cs @@ -0,0 +1,304 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Threading.Tasks; + +using Niantic.ARDK.AR.ARSessionEventArgs; +using Niantic.ARDK.LocationService; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; + +namespace Niantic.ARDK.AR.WayspotAnchors +{ + public class WayspotAnchorService : IDisposable + { + /// The current localization state of the waypoint anchor service + public LocalizationState LocalizationState { get; private set; } + + private readonly WayspotAnchorController _wayspotAnchorController; + private readonly IARSession _arSession; + private readonly ILocationService _locationService; + private readonly IWayspotAnchorsConfiguration _wayspotAnchorsConfiguration; + private readonly Dictionary _wayspotAnchors; + private readonly Dictionary _wayspotAnchorStatusCodes; + + private const string _mustLocaliseBeforeCreatingAnchorErrorMessage = "Must localize before creating wayspot anchors."; + + /// Creates a new wayspot anchor service + /// @param arSession The AR Session used to create the wayspot anchor service + /// @param locationService The location service used to create the wayspot anchor service + /// @param wayspotAnchorsConfiguration The configuration of the wayspot anchors + public WayspotAnchorService + ( + IARSession arSession, + ILocationService locationService, + IWayspotAnchorsConfiguration wayspotAnchorsConfiguration + ) + { + _wayspotAnchors = new Dictionary(); + _wayspotAnchorStatusCodes = new Dictionary(); + _arSession = arSession; + _locationService = locationService; + _wayspotAnchorsConfiguration = wayspotAnchorsConfiguration; + _arSession.Deinitialized += HandleSessionDeinitialized; + _wayspotAnchorController = CreateWayspotAnchorController(); + _arSession.Paused += HandleARSessionPaused; + _arSession.Ran += HandleARSessionRan; + } + + private void HandleARSessionPaused(ARSessionPausedArgs args) + { + _wayspotAnchorController.PauseTracking(_wayspotAnchors.Values.ToArray()); + } + + private void HandleARSessionRan(ARSessionRanArgs args) + { + _wayspotAnchorController.ResumeTracking(_wayspotAnchors.Values.ToArray()); + } + + /// Creates new wayspot anchors + /// @param callback The callback when the wayspot anchors have been created + /// @param localPoses The positions and rotations used the create the wayspot anchors + public async void CreateWayspotAnchors(Action callback, params Matrix4x4[] localPoses) + { + if (LocalizationState != LocalizationState.Localized) + { + ARLog._Error(_mustLocaliseBeforeCreatingAnchorErrorMessage); + return; + } + + var wayspotAnchors = await CreateWayspotAnchorsAsync(localPoses); + callback?.Invoke(wayspotAnchors); + } + + /// Creates new wayspot anchors. The new wayspot anchor is tracked by default. + /// @param localPoses The positions and rotations used the create the wayspot anchors + /// @return The newly created wayspot anchors + public async Task CreateWayspotAnchorsAsync(params Matrix4x4[] localPoses) + { + if (LocalizationState != LocalizationState.Localized) + { + ARLog._Error(_mustLocaliseBeforeCreatingAnchorErrorMessage); + return default; + } + + var ids = _wayspotAnchorController.CreateWayspotAnchors(localPoses); + var wayspotAnchors = await GetCreatedWayspotAnchors(ids); + + return wayspotAnchors; + } + + /// Restores previously created wayspot anchors via the payload from them + /// @param wayspotAnchorPayloads The payloads from the wayspot anchors used to restore them + /// @return The restored wayspot anchors + public IWayspotAnchor[] RestoreWayspotAnchors(params WayspotAnchorPayload[] wayspotAnchorPayloads) + { + if (LocalizationState != LocalizationState.Localized) + { + ARLog._Error(_mustLocaliseBeforeCreatingAnchorErrorMessage); + return default; + } + + var wayspotAnchors = _wayspotAnchorController.RestoreWayspotAnchors(wayspotAnchorPayloads); + AddWayspotAnchors(wayspotAnchors); + return wayspotAnchors; + } + + /// Destroys existing wayspot anchors + /// @param anchors The wayspot anchors to destroy + public void DestroyWayspotAnchors(params IWayspotAnchor[] anchors) + { + var ids = anchors.Select(a => a.ID); + DestroyWayspotAnchors(ids.ToArray()); + } + + /// Destroys wayspot anchors by ID + /// @param ids The IDs of the wayspot anchors to destroy + public void DestroyWayspotAnchors(params Guid[] ids) + { + var wayspotAnchors = _wayspotAnchors.Values.Where + (a => Array.IndexOf(ids, a.ID) >= 0) + .ToArray(); + + _wayspotAnchorController.PauseTracking(wayspotAnchors); + foreach (var id in ids) + { + _wayspotAnchors[id].Dispose(); + _wayspotAnchors.Remove(id); + _wayspotAnchorStatusCodes.Remove(id); + } + } + + /// Gets all of the wayspot anchors + /// @return All of the wayspot anchors + public IWayspotAnchor[] GetAllWayspotAnchors() + { + return _wayspotAnchors.Values.ToArray(); + } + + /// Gets a wayspot anchor by its ID + /// @param id The ID of the wayspot anchor to retrieve + /// @return The wayspot anchor + public IWayspotAnchor GetWayspotAnchor(Guid id) + { + if (_wayspotAnchors.ContainsKey(id)) + { + return _wayspotAnchors[id]; + } + else + { + ARLog._Error($"Wayspot Anchor {id} does not exist."); + return default; + } + } + + /// Restarts VPS + public async void Restart() + { + _wayspotAnchorController.StopVps(); + _locationService.Stop(); + while (LocalizationState != LocalizationState.Failed) + { + await Task.Delay(1); + } + _locationService.Start(); + _wayspotAnchorController.StartVps(_wayspotAnchorsConfiguration); + } + + /// Disposes of the Wayspot Anchor Service + public void Dispose() + { + _arSession.Paused -= HandleARSessionPaused; + _arSession.Ran -= HandleARSessionRan; + } + + private WayspotAnchorController CreateWayspotAnchorController() + { + var wayspotAnchorController = new WayspotAnchorController(_arSession, _locationService); + wayspotAnchorController.LocalizationStateUpdated += HandleLocalizationStateUpdated; + wayspotAnchorController.WayspotAnchorsCreated += HandleWayspotAnchorsCreated; + wayspotAnchorController.WayspotAnchorsTrackingUpdated += HandleWayspotAnchorsResolved; + wayspotAnchorController.WayspotAnchorStatusUpdated += HandleWayspotAnchorStatusUpdated; + + wayspotAnchorController.StartVps(_wayspotAnchorsConfiguration); + + return wayspotAnchorController; + } + + private void HandleSessionDeinitialized(ARSessionDeinitializedArgs arSessionDeinitializedArgs) + { + DestroyWayspotAnchors(_wayspotAnchors.Keys.ToArray()); + _arSession.Deinitialized -= HandleSessionDeinitialized; + _wayspotAnchorController.LocalizationStateUpdated -= HandleLocalizationStateUpdated; + _wayspotAnchorController.WayspotAnchorsCreated -= HandleWayspotAnchorsCreated; + _wayspotAnchorController.WayspotAnchorsTrackingUpdated -= HandleWayspotAnchorsResolved; + _wayspotAnchorController.WayspotAnchorStatusUpdated -= HandleWayspotAnchorStatusUpdated; + } + + private void HandleLocalizationStateUpdated(LocalizationStateUpdatedArgs localizationStateUpdatedArgs) + { + LocalizationState = localizationStateUpdatedArgs.State; + if (LocalizationState == LocalizationState.Failed) + { + ARLog._Error($"Localization has failed: {localizationStateUpdatedArgs.FailureReason}"); + } + } + + private void HandleWayspotAnchorsCreated(WayspotAnchorsCreatedArgs wayspotAnchorsCreatedArgs) + { + AddWayspotAnchors(wayspotAnchorsCreatedArgs.WayspotAnchors); + } + + private void AddWayspotAnchors(params IWayspotAnchor[] anchors) + { + _wayspotAnchorController.ResumeTracking(anchors); + foreach (var anchor in anchors) + { + if (!_wayspotAnchors.ContainsKey(anchor.ID)) + { + _wayspotAnchors.Add(anchor.ID, anchor); + } + + if (!_wayspotAnchorStatusCodes.ContainsKey(anchor.ID)) + { + _wayspotAnchorStatusCodes.Add(anchor.ID, WayspotAnchorStatusCode.Success); + } + } + } + + private void HandleWayspotAnchorsResolved(WayspotAnchorsResolvedArgs wayspotAnchorsResolvedArgs) + { + foreach (var resolution in wayspotAnchorsResolvedArgs.Resolutions) + { + if (!_wayspotAnchors.ContainsKey(resolution.ID) || !_wayspotAnchorStatusCodes.ContainsKey(resolution.ID)) + { + continue; + } + + var wayspotAnchor = _wayspotAnchors[resolution.ID]; + if (_wayspotAnchorStatusCodes[resolution.ID] == WayspotAnchorStatusCode.Success) + { + wayspotAnchor.TrackingStateUpdated?.Invoke(resolution); + } + } + } + + private void HandleWayspotAnchorStatusUpdated(WayspotAnchorStatusUpdatedArgs wayspotAnchorStatusUpdatedArgs) + { + foreach (var wayspotStatus in wayspotAnchorStatusUpdatedArgs.WayspotAnchorStatusUpdates) + { + _wayspotAnchorStatusCodes[wayspotStatus.ID] = wayspotStatus.Code; + switch (wayspotStatus.Code) + { + case WayspotAnchorStatusCode.Failed: + ARLog._Error($"Wayspot Anchor has failed: {wayspotStatus.ID}"); + break; + + case WayspotAnchorStatusCode.Invalid: + break; + + case WayspotAnchorStatusCode.Limited: + break; + + case WayspotAnchorStatusCode.Pending: + break; + + case WayspotAnchorStatusCode.Success: + break; + + default: + throw new InvalidEnumArgumentException + ( + $"Invalid wayspot anchor status code provided for {wayspotStatus.ID}: {wayspotStatus.Code}" + ); + } + } + } + + private async Task GetCreatedWayspotAnchors(Guid[] ids) + { + IWayspotAnchor[] wayspotAnchors = null; + var task = TaskUtility.WaitUntil + ( + () => + { + wayspotAnchors = _wayspotAnchors.Where + (a => ids.Contains(a.Key)) + .Select(a => a.Value) + .ToArray(); + + return wayspotAnchors.Length == ids.Length; + } + ); + + var timeout = Task.Delay(1000); + await Task.WhenAny(task, timeout); + + return wayspotAnchors; + } + } +} diff --git a/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorService.cs.meta b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorService.cs.meta new file mode 100644 index 0000000..4fc8d12 --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorService.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8dce85e2a149a4292bf5d6ceb996f0f8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorStatusCode.cs b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorStatusCode.cs new file mode 100644 index 0000000..be5423f --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorStatusCode.cs @@ -0,0 +1,18 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +namespace Niantic.ARDK.AR.WayspotAnchors +{ + /// The enum for the wayspot anchor status codes + public enum WayspotAnchorStatusCode + { + // System is not ready yet to create/resolve anchor + Pending = 0, + // Anchor creation or resolution was successful using VPS + Success = 1, + // Anchor creation or resolution failed + Failed = 2, + // Anchor data is invalid + Invalid = 3, + // Anchor creation or resolution was successful but using GPS instead of VPS + Limited = 4 + } +} diff --git a/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorStatusCode.cs.meta b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorStatusCode.cs.meta new file mode 100644 index 0000000..cf21ecf --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorStatusCode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8e6d35d40bfb14f6b9e6c2438476d0e0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorStatusUpdate.cs b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorStatusUpdate.cs new file mode 100644 index 0000000..ee9db23 --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorStatusUpdate.cs @@ -0,0 +1,23 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; + +namespace Niantic.ARDK.AR.WayspotAnchors +{ + public class WayspotAnchorStatusUpdate + { + /// The ID of the wayspot anchor + public Guid ID { get; } + + /// The status code for thy wayspot anchor + public WayspotAnchorStatusCode Code { get; } + + /// Creates the status for the wayspot anchor + /// @param id The ID of the wayspot anchor + /// @param code The status code for the wayspot anchor + public WayspotAnchorStatusUpdate(Guid id, WayspotAnchorStatusCode code) + { + ID = id; + Code = code; + } + } +} diff --git a/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorStatusUpdate.cs.meta b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorStatusUpdate.cs.meta new file mode 100644 index 0000000..5ffb795 --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorStatusUpdate.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 011cbe07d6c1c495fb0d598324b5289a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorStatusUpdatedArgs.cs b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorStatusUpdatedArgs.cs new file mode 100644 index 0000000..7161ba8 --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorStatusUpdatedArgs.cs @@ -0,0 +1,18 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.AR.WayspotAnchors +{ + public class WayspotAnchorStatusUpdatedArgs: IArdkEventArgs + { + /// The statuses of waypoint anchors + public WayspotAnchorStatusUpdate[] WayspotAnchorStatusUpdates { get; } + + /// Creates the args for waypoint anchor statuses + /// @param wayspotAnchorStatusUpdates The statuses for the waypoint anchors + internal WayspotAnchorStatusUpdatedArgs(WayspotAnchorStatusUpdate[] wayspotAnchorStatusUpdates) + { + WayspotAnchorStatusUpdates = wayspotAnchorStatusUpdates; + } + } +} diff --git a/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorStatusUpdatedArgs.cs.meta b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorStatusUpdatedArgs.cs.meta new file mode 100644 index 0000000..ebbc253 --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorStatusUpdatedArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2bc069044750942e299f078a46167946 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorsConfiguationFactory.cs b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorsConfiguationFactory.cs new file mode 100644 index 0000000..9387373 --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorsConfiguationFactory.cs @@ -0,0 +1,19 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +namespace Niantic.ARDK.AR.WayspotAnchors +{ + /// Class factory for [WayspotAnchorsConfiguration] + /// @see [Working with the Visual Positioning System (VPS)](@ref working_with_vps) + public static class WayspotAnchorsConfigurationFactory + { + /// Initializes a new instance of the WayspotAnchorsConfiguration class. + public static IWayspotAnchorsConfiguration Create() + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return new _NativeWayspotAnchorsConfiguration(); + +#pragma warning disable 0162 + return new _SerializableWayspotAnchorsConfiguration(); +#pragma warning restore 0162 + } + } +} diff --git a/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorsConfiguationFactory.cs.meta b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorsConfiguationFactory.cs.meta new file mode 100644 index 0000000..a0b2ec0 --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorsConfiguationFactory.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 150a63edab33b400ca6173b2c2efea70 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorsCreatedArgs.cs b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorsCreatedArgs.cs new file mode 100644 index 0000000..4881740 --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorsCreatedArgs.cs @@ -0,0 +1,18 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.AR.WayspotAnchors +{ + public class WayspotAnchorsCreatedArgs: IArdkEventArgs + { + /// The newly created wayspot anchors + public IWayspotAnchor[] WayspotAnchors { get; } + + /// Creates the args for newly created wayspot anchors + /// @param wayspotAnchors The newly created wayspot anchors + internal WayspotAnchorsCreatedArgs(IWayspotAnchor[] wayspotAnchors) + { + WayspotAnchors = wayspotAnchors; + } + } +} diff --git a/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorsCreatedArgs.cs.meta b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorsCreatedArgs.cs.meta new file mode 100644 index 0000000..97a66d1 --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorsCreatedArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bc4d98e239ffd4a6881041c3e94463cb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorsResolvedArgs.cs b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorsResolvedArgs.cs new file mode 100644 index 0000000..07118eb --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorsResolvedArgs.cs @@ -0,0 +1,18 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.AR.WayspotAnchors +{ + public class WayspotAnchorsResolvedArgs: IArdkEventArgs + { + /// The resolutions for the wayspot anchors + public WayspotAnchorResolvedArgs[] Resolutions { get; } + + /// Creates the args for resolved wayspot anchors + /// @param resolutions The resolutions of the wayspot anchors + internal WayspotAnchorsResolvedArgs(WayspotAnchorResolvedArgs[] resolutions) + { + Resolutions = resolutions; + } + } +} diff --git a/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorsResolvedArgs.cs.meta b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorsResolvedArgs.cs.meta new file mode 100644 index 0000000..d6623d3 --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/WayspotAnchorsResolvedArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cf127319a4dda496a965d7dd98a7f91f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/WayspotAnchors/_IInternalTrackable.cs b/Assets/ARDK/AR/WayspotAnchors/_IInternalTrackable.cs new file mode 100644 index 0000000..29b3cae --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/_IInternalTrackable.cs @@ -0,0 +1,9 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +namespace Niantic.ARDK.AR.WayspotAnchors +{ + internal interface _IInternalTrackable + { + /// Sets whether or not the anchor should be tracked + void SetTrackingEnabled(bool tracking); + } +} \ No newline at end of file diff --git a/Assets/ARDK/AR/WayspotAnchors/_IInternalTrackable.cs.meta b/Assets/ARDK/AR/WayspotAnchors/_IInternalTrackable.cs.meta new file mode 100644 index 0000000..6bf391d --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/_IInternalTrackable.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f47eaf2d5094141b1b9f252c6e563fd6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/WayspotAnchors/_IWayspotAnchorImplementation.cs b/Assets/ARDK/AR/WayspotAnchors/_IWayspotAnchorImplementation.cs new file mode 100644 index 0000000..b8767a8 --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/_IWayspotAnchorImplementation.cs @@ -0,0 +1,44 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; + +using Niantic.ARDK.Utilities; + +using UnityEngine; + +namespace Niantic.ARDK.AR.WayspotAnchors +{ + internal interface _IWayspotAnchorImplementation: + IDisposable + { + /// Called when the VPS Localization State has changed + event ArdkEventHandler LocalizationStateUpdated; + + /// Called when the status for wayspot anchors has changed + event ArdkEventHandler WayspotAnchorStatusUpdated; + + /// Called when a new wayspot anchor has been created + event ArdkEventHandler WayspotAnchorsCreated; + + /// Called when a wayspot anchor position/rotation has been updated + event ArdkEventHandler WayspotAnchorsResolved; + + /// Starts VPS + /// @param The configuration to start VPS with + void StartVPS(IWayspotAnchorsConfiguration wayspotAnchorsConfiguration); + + /// Stops VPS + void StopVPS(); + + /// Creates new wayspot anchors + /// @param localPoses The local poses used ot create the wayspot anchors + Guid[] CreateWayspotAnchors(params Matrix4x4[] localPoses); + + /// Starts tracking the managed poses + /// @param wayspotAnchors The wayspot anchors to track + void StartResolvingWayspotAnchors(params IWayspotAnchor[] wayspotAnchors); + + /// Stops tracking wayspot anchors + /// @param wayspotAnchors The wayspot anchors to stop tracking + void StopResolvingWayspotAnchors(params IWayspotAnchor[] wayspotAnchors); + } +} diff --git a/Assets/ARDK/AR/WayspotAnchors/_IWayspotAnchorImplementation.cs.meta b/Assets/ARDK/AR/WayspotAnchors/_IWayspotAnchorImplementation.cs.meta new file mode 100644 index 0000000..924ff24 --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/_IWayspotAnchorImplementation.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e0749f6442e5c477987c4e5815c60286 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/WayspotAnchors/_MockWayspotAnchor.cs b/Assets/ARDK/AR/WayspotAnchors/_MockWayspotAnchor.cs new file mode 100644 index 0000000..908c28b --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/_MockWayspotAnchor.cs @@ -0,0 +1,116 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; +using System.Text; + +using Niantic.ARDK.Utilities; + +using UnityEngine; + +namespace Niantic.ARDK.AR.WayspotAnchors +{ + internal class _MockWayspotAnchor: + IWayspotAnchor, + _IInternalTrackable + { + /// Called when the position oof rotation of the mock wayspot anchor has been updated + public ArdkEventHandler TrackingStateUpdated { get; set; } + + /// Whether or not the mock anchor is currently being tracked + public bool Tracking { get; private set; } + + /// Sets whether or not the mock anchor should be tracked + /// @param tracking Whether or not to track the mock anchor + /// @note This is an internal method + void _IInternalTrackable.SetTrackingEnabled (bool tracking) //This method is internal, not private + { + Tracking = tracking; + } + + /// Gets the mock anchor's local pose + internal Matrix4x4 LocalPose { get; } + + /// Creates a mock anchor + /// @param id The ID of the mock anchor to create + /// @param localPose The local pose of the mock anchor + public _MockWayspotAnchor(Guid id, Matrix4x4 localPose) + { + ID = id; + LocalPose = localPose; + } + + /// Creates a mock anchor + /// @param blob The blob of data used to create the mock anchor + public _MockWayspotAnchor(byte[] blob) + { + string json = Encoding.UTF8.GetString(blob); + var mockWayspotAnchorData = JsonUtility.FromJson<_MockWayspotAnchorData>(json); + string id = mockWayspotAnchorData._ID; + var position = new Vector3 + ( + mockWayspotAnchorData._XPosition, + mockWayspotAnchorData._YPosition, + mockWayspotAnchorData._ZPosition + ); + + var rotation = new Vector3 + ( + mockWayspotAnchorData._XRotation, + mockWayspotAnchorData._YRotation, + mockWayspotAnchorData._ZRotation + ); + + var localPose = Matrix4x4.TRS(position, Quaternion.Euler(rotation), Vector3.one); + ID = Guid.Parse(id); + LocalPose = localPose; + } + + /// Gets the ID of the mock anchor + public Guid ID { get; } + + /// Gets the payload of the mock anchor + /// @note This is a wrapper around the blob of data + public WayspotAnchorPayload Payload + { + get + { + string id = ID.ToString(); + var position = LocalPose.ToPosition(); + var rotation = LocalPose.ToRotation().eulerAngles; + var mockWayspotAnchorData = new _MockWayspotAnchorData() + { + _ID = id, + _XPosition = position.x, + _YPosition = position.y, + _ZPosition = position.z, + _XRotation = rotation.x, + _YRotation = rotation.y, + _ZRotation = rotation.z + }; + + string json = JsonUtility.ToJson(mockWayspotAnchorData); + byte[] blob = Encoding.UTF8.GetBytes(json); + var payload = new WayspotAnchorPayload(blob); + + return payload; + } + } + + /// The data class used to serialize/deserialize the payload + [Serializable] + public class _MockWayspotAnchorData + { + public string _ID; + public float _XPosition; + public float _YPosition; + public float _ZPosition; + public float _XRotation; + public float _YRotation; + public float _ZRotation; + } + + /// Disposes the mock wayspot anchor + public void Dispose() + { + } + } +} diff --git a/Assets/ARDK/AR/WayspotAnchors/_MockWayspotAnchor.cs.meta b/Assets/ARDK/AR/WayspotAnchors/_MockWayspotAnchor.cs.meta new file mode 100644 index 0000000..50ac8f8 --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/_MockWayspotAnchor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a6d7012ee04204a52acee1c509488102 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/WayspotAnchors/_NativeWayspotAnchor.cs b/Assets/ARDK/AR/WayspotAnchors/_NativeWayspotAnchor.cs new file mode 100644 index 0000000..4fcf9b1 --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/_NativeWayspotAnchor.cs @@ -0,0 +1,139 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; +using System.Runtime.InteropServices; + +using Niantic.ARDK.Internals; +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.AR.WayspotAnchors +{ + internal class _NativeWayspotAnchor: + _ThreadCheckedObject, + IWayspotAnchor, + _IInternalTrackable + { + /// Gets the native handle for this wayspot anchor + internal IntPtr _NativeHandle { get; private set; } + + /// The event for when the position and/or rotation of the native wayspot acnhor has been updated + public ArdkEventHandler TrackingStateUpdated { get; set; } + + /// Checks whether or not the wayspot anchor's position/rotation is being tracked + public bool Tracking { get; private set; } + + /// Sets whether or not the native anchor should be tracked + /// @param tracking Whether or not to track the native anchor + /// @note This is an internal method + void _IInternalTrackable.SetTrackingEnabled(bool tracking) //This method is internal, not private + { + Tracking = tracking; + } + + /// Creates a new native wayspot anchor + /// @param nativeHandle The pointer to the native handle + public _NativeWayspotAnchor(IntPtr nativeHandle) + { + _NativeHandle = nativeHandle; + GC.AddMemoryPressure(_MemoryPressure); + } + + /// Creates a new native wayspot anchor + /// @param dataBlob The blob of data used to create the wayspot anchor + public _NativeWayspotAnchor(byte[] dataBlob) + { + var nativeHandle = _NAR_ManagedPose_InitFromBlob(dataBlob, dataBlob.Length); + if (nativeHandle == IntPtr.Zero) + throw new ArgumentException("Failed to create wayspot anchor!", nameof(nativeHandle)); + + _NativeHandle = nativeHandle; + GC.AddMemoryPressure(_MemoryPressure); + } + + private static void _ReleaseImmediate(IntPtr nativeHandle) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NAR_ManagedPose_Release(nativeHandle); + } + + /// Disposes of the native wayspot anchor + public void Dispose() + { + GC.SuppressFinalize(this); + + var nativeHandle = _NativeHandle; + if (nativeHandle == IntPtr.Zero) + return; + + _NativeHandle = IntPtr.Zero; + + _ReleaseImmediate(nativeHandle); + GC.RemoveMemoryPressure(_MemoryPressure); + } + + /// Gets the ID of the native wayspot anchor + public Guid ID + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + Guid id; + _NAR_ManagedPose_GetIdentifier(_NativeHandle, out id); + return id; + } +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + } + + /// Gets the payload for the native wayspot anchor + public WayspotAnchorPayload Payload + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + var dataSize = _NAR_ManagedPose_GetDataSize(_NativeHandle); + byte[] dataArray = new byte[dataSize]; + unsafe + { + fixed (byte* ptr = dataArray) + { + IntPtr identifierPtr = (IntPtr)ptr; + _NAR_ManagedPose_GetData(_NativeHandle, identifierPtr); + } + } + + var payload = new WayspotAnchorPayload(dataArray); + return payload; + } +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + } + + private long _MemoryPressure + { + get => (255L); + } + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NAR_ManagedPose_InitFromBlob(byte[] blob, int dataSize); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NAR_ManagedPose_Release(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern bool _NAR_ManagedPose_GetIdentifier + (IntPtr nativeHandle, out Guid wayspotAnchorId); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern bool _NAR_ManagedPose_GetData + (IntPtr nativeHandle, IntPtr wayspotAnchorData); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern int _NAR_ManagedPose_GetDataSize(IntPtr nativeHandle); + } +} diff --git a/Assets/ARDK/AR/WayspotAnchors/_NativeWayspotAnchor.cs.meta b/Assets/ARDK/AR/WayspotAnchors/_NativeWayspotAnchor.cs.meta new file mode 100644 index 0000000..77d547c --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/_NativeWayspotAnchor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 02b85c796524b488c845357e81d7de2e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/WayspotAnchors/_NativeWayspotAnchorsConfiguration.cs b/Assets/ARDK/AR/WayspotAnchors/_NativeWayspotAnchorsConfiguration.cs new file mode 100644 index 0000000..51a71ef --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/_NativeWayspotAnchorsConfiguration.cs @@ -0,0 +1,592 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using Niantic.ARDK.Internals; + +using System; +using System.Text; +using System.Runtime.InteropServices; + +namespace Niantic.ARDK.AR.WayspotAnchors +{ + internal sealed class _NativeWayspotAnchorsConfiguration: + IWayspotAnchorsConfiguration + { + internal _NativeWayspotAnchorsConfiguration() + { + var nativeHandle = _NARVPSConfiguration_Init(); + if (nativeHandle == IntPtr.Zero) + throw new ArgumentException("nativeHandle can't be Zero.", nameof(nativeHandle)); + + _nativeHandle = nativeHandle; + GC.AddMemoryPressure(_MemoryPressure); + } + + private static void _ReleaseImmediate(IntPtr nativeHandle) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARVPSConfiguration_Release(nativeHandle); + } + + ~_NativeWayspotAnchorsConfiguration() + { + if (_nativeHandle != IntPtr.Zero) + { + _ReleaseImmediate(_nativeHandle); + } + + GC.RemoveMemoryPressure(_MemoryPressure); + } + + public void Dispose() + { + GC.SuppressFinalize(this); + + var nativeHandle = _nativeHandle; + if (nativeHandle != IntPtr.Zero) + { + _nativeHandle = IntPtr.Zero; + + _ReleaseImmediate(nativeHandle); + GC.RemoveMemoryPressure(_MemoryPressure); + } + } + + private IntPtr _nativeHandle; + + internal IntPtr _NativeHandle + { + get => _nativeHandle; + } + + // (string/uuid)coordinateSpace + (float)localizationTimeOut + (float)requestTimeLimit + + // (float)requestPerSecond + (float)gpsWait + (uint32_t)maxRequestInTransit + (uint32_t)meshType + // (string)localizationEndpoint + (string)meshDownloadEndpoint + // 1 string/uuid + 4 floats + 2 uint32_t + 2(120-byte strings) + private long _MemoryPressure + { + get => (1L * 8L) + (4L * 4L) + (2L * 4L) + (2L * 120L); + } + + public float LocalizationTimeout + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _NARVPSConfiguration_GetLocalizationTimeout(_NativeHandle); +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + set + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARVPSConfiguration_SetLocalizationTimeout(_NativeHandle, value); + } + } + + public float RequestTimeLimit + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _NARVPSConfiguration_GetRequestTimeLimit(_NativeHandle); +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + set + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARVPSConfiguration_SetRequestTimeLimit(_NativeHandle, value); + } + } + + public float RequestsPerSecond + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _NARVPSConfiguration_GetRequestsPerSecond(_NativeHandle); +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + set + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARVPSConfiguration_SetRequestsPerSecond(_NativeHandle, value); + } + } + + public float MaxResolutionsPerSecond + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _NARVPSConfiguration_GetResolutionsPerSecond(_NativeHandle); +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + set + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARVPSConfiguration_SetResolutionsPerSecond(_NativeHandle, value); + } + } + + public float GoodTrackingWait + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _NARVPSConfiguration_GetGoodTrackingWaitSeconds(_NativeHandle); +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + set + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARVPSConfiguration_SetGoodTrackingWaitSeconds(_NativeHandle, value); + } + } + + + public bool ContinuousLocalizationEnabled + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _NARVPSConfiguration_GetContinuousLocalizationEnabled(_NativeHandle) != 0; +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + set + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARVPSConfiguration_SetContinuousLocalizationEnabled + (_NativeHandle, value ? 1 : (UInt32)0); + } + } + + public bool CloudProcessingForced + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _NARVPSConfiguration_GetCloudProcessingForced(_NativeHandle) != 0; +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + set + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARVPSConfiguration_SetCloudProcessingForced(_NativeHandle, value ? 1 : (UInt32)0); + } + } + + public bool ClientProcessingForced + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + return _NARVPSConfiguration_GetClientProcessingForced(_NativeHandle) != 0; +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + set + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARVPSConfiguration_SetClientProcessingForced(_NativeHandle, value ? 1 : (UInt32)0); + } + } + + public string ConfigURL + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + const int MaxUrlLength = 2083; + var stringBuilder = new StringBuilder(MaxUrlLength); + _NARVPSConfiguration_GetConfigEndpoint + (_NativeHandle, stringBuilder, (ulong)stringBuilder.Capacity); + + var result = stringBuilder.ToString(); + return result; + } +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + set + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARVPSConfiguration_SetConfigEndpoint(_NativeHandle, value); + } + } + + public string HealthURL + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + var stringBuilder = new StringBuilder(512); + _NARVPSConfiguration_GetHealthEndpoint + (_NativeHandle, stringBuilder, (ulong)stringBuilder.Capacity); + + var result = stringBuilder.ToString(); + return result; + } +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + set + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARVPSConfiguration_SetHealthEndpoint(_NativeHandle, value); + } + } + + public string LocalizationURL + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + var stringBuilder = new StringBuilder(512); + _NARVPSConfiguration_GetLocalizationEndpoint + (_NativeHandle, stringBuilder, (ulong)stringBuilder.Capacity); + + var result = stringBuilder.ToString(); + return result; + } +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + set + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARVPSConfiguration_SetLocalizationEndpoint(_NativeHandle, value); + } + } + + public string GraphSyncURL + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + var stringBuilder = new StringBuilder(512); + _NARVPSConfiguration_GetGraphSyncEndpoint + (_NativeHandle, stringBuilder, (ulong)stringBuilder.Capacity); + + var result = stringBuilder.ToString(); + return result; + } +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + set + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARVPSConfiguration_SetGraphSyncEndpoint(_NativeHandle, value); + } + } + + public string WayspotAnchorCreateURL + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + var stringBuilder = new StringBuilder(512); + _NARVPSConfiguration_GetManagedPoseCreateEndpoint + (_NativeHandle, stringBuilder, (ulong)stringBuilder.Capacity); + + var result = stringBuilder.ToString(); + return result; + } +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + set + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARVPSConfiguration_SetManagedPoseCreateEndpoint(_NativeHandle, value); + } + } + + public string WayspotAnchorResolveURL + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + var stringBuilder = new StringBuilder(512); + _NARVPSConfiguration_GetManagedPoseResolveEndpoint + (_NativeHandle, stringBuilder, (ulong)stringBuilder.Capacity); + + var result = stringBuilder.ToString(); + return result; + } +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + set + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARVPSConfiguration_SetManagedPoseResolveEndpoint(_NativeHandle, value); + } + } + + public string RegisterNodeURL + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + var stringBuilder = new StringBuilder(512); + _NARVPSConfiguration_GetRegisterNodeEndpoint + (_NativeHandle, stringBuilder, (ulong)stringBuilder.Capacity); + + var result = stringBuilder.ToString(); + return result; + } +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + set + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARVPSConfiguration_SetRegisterNodeEndpoint(_NativeHandle, value); + } + } + + public string LookUpNodeURL + { + get + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + var stringBuilder = new StringBuilder(512); + _NARVPSConfiguration_GetLookUpNodeEndpoint + (_NativeHandle, stringBuilder, (ulong)stringBuilder.Capacity); + + var result = stringBuilder.ToString(); + return result; + } +#pragma warning disable 0162 + throw new IncorrectlyUsedNativeClassException(); +#pragma warning restore 0162 + } + set + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + _NARVPSConfiguration_SetLookUpNodeEndpoint(_NativeHandle, value); + } + } + + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NARVPSConfiguration_Init(); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARVPSConfiguration_Release(IntPtr nativeHandle); + + + [DllImport(_ARDKLibrary.libraryName)] + private static extern float _NARVPSConfiguration_GetLocalizationTimeout(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARVPSConfiguration_SetLocalizationTimeout + ( + IntPtr nativeHandle, + float value + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern float _NARVPSConfiguration_GetRequestTimeLimit(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARVPSConfiguration_SetRequestTimeLimit + ( + IntPtr nativeHandle, + float value + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern float _NARVPSConfiguration_GetRequestsPerSecond(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARVPSConfiguration_SetRequestsPerSecond + ( + IntPtr nativeHandle, + float value + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern float _NARVPSConfiguration_GetResolutionsPerSecond(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARVPSConfiguration_SetResolutionsPerSecond + ( + IntPtr nativeHandle, + float value + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern float _NARVPSConfiguration_GetGoodTrackingWaitSeconds(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARVPSConfiguration_SetGoodTrackingWaitSeconds + ( + IntPtr nativeHandle, + float value + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern UInt32 _NARVPSConfiguration_GetContinuousLocalizationEnabled + (IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARVPSConfiguration_SetContinuousLocalizationEnabled + ( + IntPtr nativeHandle, + UInt32 value + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern UInt32 _NARVPSConfiguration_GetCloudProcessingForced(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARVPSConfiguration_SetCloudProcessingForced + ( + IntPtr nativeHandle, + UInt32 value + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern UInt32 _NARVPSConfiguration_GetClientProcessingForced + (IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARVPSConfiguration_SetClientProcessingForced + ( + IntPtr nativeHandle, + UInt32 value + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARVPSConfiguration_SetConfigEndpoint + (IntPtr nativeHandle, string url); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARVPSConfiguration_GetConfigEndpoint + ( + IntPtr nativeHandle, + StringBuilder outUrl, + ulong maxKeySize + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARVPSConfiguration_SetHealthEndpoint + (IntPtr nativeHandle, string url); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARVPSConfiguration_GetHealthEndpoint + ( + IntPtr nativeHandle, + StringBuilder outUrl, + ulong maxKeySize + ); + + // Set VPS Endpoint + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARVPSConfiguration_SetLocalizationEndpoint + (IntPtr nativeHandle, string url); + + // Get VPS Endpoint + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARVPSConfiguration_GetLocalizationEndpoint + ( + IntPtr nativeHandle, + StringBuilder outUrl, + ulong maxKeySize + ); + + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARVPSConfiguration_SetGraphSyncEndpoint + (IntPtr nativeHandle, string url); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARVPSConfiguration_GetGraphSyncEndpoint + ( + IntPtr nativeHandle, + StringBuilder outUrl, + ulong maxKeySize + ); + + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARVPSConfiguration_SetManagedPoseCreateEndpoint + (IntPtr nativeHandle, string url); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARVPSConfiguration_GetManagedPoseCreateEndpoint + ( + IntPtr nativeHandle, + StringBuilder outUrl, + ulong maxKeySize + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARVPSConfiguration_SetManagedPoseResolveEndpoint + (IntPtr nativeHandle, string url); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARVPSConfiguration_GetManagedPoseResolveEndpoint + ( + IntPtr nativeHandle, + StringBuilder outUrl, + ulong maxKeySize + ); + + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARVPSConfiguration_SetRegisterNodeEndpoint + (IntPtr nativeHandle, string url); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARVPSConfiguration_GetRegisterNodeEndpoint + ( + IntPtr nativeHandle, + StringBuilder outUrl, + ulong maxKeySize + ); + + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARVPSConfiguration_SetLookUpNodeEndpoint + (IntPtr nativeHandle, string url); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARVPSConfiguration_GetLookUpNodeEndpoint + ( + IntPtr nativeHandle, + StringBuilder outUrl, + ulong maxKeySize + ); + } +} diff --git a/Assets/ARDK/AR/WayspotAnchors/_NativeWayspotAnchorsConfiguration.cs.meta b/Assets/ARDK/AR/WayspotAnchors/_NativeWayspotAnchorsConfiguration.cs.meta new file mode 100644 index 0000000..06fa2bf --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/_NativeWayspotAnchorsConfiguration.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 301315249edbc419e81c6b186e2e44e6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/WayspotAnchors/_SerializableWayspotAnchorsConfiguration.cs b/Assets/ARDK/AR/WayspotAnchors/_SerializableWayspotAnchorsConfiguration.cs new file mode 100644 index 0000000..ca9578a --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/_SerializableWayspotAnchorsConfiguration.cs @@ -0,0 +1,46 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; + +namespace Niantic.ARDK.AR.WayspotAnchors +{ + internal sealed class _SerializableWayspotAnchorsConfiguration: + IWayspotAnchorsConfiguration + { + public float LocalizationTimeout { get; set; } + + public float RequestTimeLimit { get; set; } + + public float RequestsPerSecond { get; set; } + + public float MaxResolutionsPerSecond { get; set; } + + public float GoodTrackingWait { get; set; } + + public bool ContinuousLocalizationEnabled { get; set; } + + public bool CloudProcessingForced { get; set; } + + public bool ClientProcessingForced { get; set; } + + public string ConfigURL { get; set; } + + public string HealthURL { get; set; } + + public string LocalizationURL { get; set; } + + public string GraphSyncURL { get; set; } + + public string WayspotAnchorCreateURL { get; set; } + + public string WayspotAnchorResolveURL { get; set; } + + public string RegisterNodeURL { get; set; } + + public string LookUpNodeURL { get; set; } + + void IDisposable.Dispose() + { + // Do nothing. This implementation of ILocalizationConfiguration is fully managed. + } + } +} diff --git a/Assets/ARDK/AR/WayspotAnchors/_SerializableWayspotAnchorsConfiguration.cs.meta b/Assets/ARDK/AR/WayspotAnchors/_SerializableWayspotAnchorsConfiguration.cs.meta new file mode 100644 index 0000000..f995b0e --- /dev/null +++ b/Assets/ARDK/AR/WayspotAnchors/_SerializableWayspotAnchorsConfiguration.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6deeaf5d93fc948898b64c247c61fa51 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/_Convert.cs b/Assets/ARDK/AR/_Convert.cs new file mode 100644 index 0000000..df217e2 --- /dev/null +++ b/Assets/ARDK/AR/_Convert.cs @@ -0,0 +1,103 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using UnityEngine; + +namespace Niantic.ARDK.AR +{ + /// A utility class used to convert to and from raw arrays and matrices. + internal static class _Convert + { + /// Converts a flat, column-major, float array to a Matrix4x4 + internal static Matrix4x4 InternalToMatrix4x4(float[] internalArray) + { + var matrix4x4 = Matrix4x4.zero; + + for (int col = 0; col < 4; col++) + { + for (int row = 0; row < 4; row++) + { + // internalArray is column-major. + matrix4x4[row, col] = internalArray[row + (col * 4)]; + } + } + + return matrix4x4; + } + + /// Converts a flat, column-major, 9-element, float array to a Matrix4x4 + internal static Matrix4x4 Internal3x3ToMatrix4x4(float[] internalArray) + { + var matrix4x4 = Matrix4x4.identity; + + matrix4x4[0, 0] = internalArray[0]; + matrix4x4[1, 0] = internalArray[1]; + matrix4x4[3, 0] = internalArray[2]; + + matrix4x4[0, 1] = internalArray[3]; + matrix4x4[1, 1] = internalArray[4]; + matrix4x4[3, 1] = internalArray[5]; + + matrix4x4[0, 3] = internalArray[6]; + matrix4x4[1, 3] = internalArray[7]; + matrix4x4[3, 3] = internalArray[8]; + + return matrix4x4; + } + + /// Converts a flat affine display transform to a Matrix4x4. + /// @remarks Represents a transformation matrix meant to be applied to column vectors + /// ``` + /// | a c 0 tx | + /// | b d 0 ty | + /// | 0 0 1 0 | + /// | 0 0 0 1 | + /// ``` + internal static Matrix4x4 DisplayAffineToMatrix4x4(float[] affine) + { + var matrix4x4 = Matrix4x4.identity; + // [row, col] + matrix4x4[0, 0] = affine[0]; // a + matrix4x4[1, 0] = affine[1]; // b + matrix4x4[0, 1] = affine[2]; // c + matrix4x4[1, 1] = affine[3]; // d + matrix4x4[0, 3] = affine[4]; // tx + matrix4x4[1, 3] = affine[5]; // ty + + return matrix4x4; + } + + /// Converts a generic Matrix4x4 to a flat, column-major array. + internal static float[] Matrix4x4ToInternalArray(Matrix4x4 matrix4x4) + { + float[] internalArray = new float[16]; + + for (int col = 0; col < 4; col++) + { + for (int row = 0; row < 4; row++) + { + // internalArray is column-major + internalArray[row + (col * 4)] = matrix4x4[row, col]; + } + } + + return internalArray; + } + + /// Scales the provided matrix by the scale. + internal static void ApplyScale(ref Matrix4x4 matrix, float scale) + { + // Apply scale to translation + // [row, col] + matrix[0, 3] *= scale; + matrix[1, 3] *= scale; + matrix[2, 3] *= scale; + } + + /// Applies the inverse of the scale to the provided matrix. + internal static void ApplyInverseScale(ref Matrix4x4 matrix, float scale) + { + // invert the scale and scale! + ApplyScale(ref matrix, 1 / scale); + } + } +} diff --git a/Assets/ARDK/AR/_Convert.cs.meta b/Assets/ARDK/AR/_Convert.cs.meta new file mode 100644 index 0000000..40fd1da --- /dev/null +++ b/Assets/ARDK/AR/_Convert.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b33178d7628bc45be971ea05cf870076 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/_CppAddressAndScale.cs b/Assets/ARDK/AR/_CppAddressAndScale.cs new file mode 100644 index 0000000..6b48557 --- /dev/null +++ b/Assets/ARDK/AR/_CppAddressAndScale.cs @@ -0,0 +1,38 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +namespace Niantic.ARDK.AR +{ + internal struct _CppAddressAndScale: + IEquatable<_CppAddressAndScale> + { + internal readonly IntPtr _cppAddress; + internal readonly float _scale; + + internal _CppAddressAndScale(IntPtr cppAddress, float scale) + { + _cppAddress = cppAddress; + _scale = scale; + } + + public override bool Equals(object obj) + { + if (!(obj is _CppAddressAndScale)) + return false; + + var other = (_CppAddressAndScale)obj; + return Equals(other); + } + + public bool Equals(_CppAddressAndScale other) + { + return _cppAddress == other._cppAddress && _scale == other._scale; + } + + public override int GetHashCode() + { + return _cppAddress.GetHashCode() ^ _scale.GetHashCode(); + } + } +} diff --git a/Assets/ARDK/AR/_CppAddressAndScale.cs.meta b/Assets/ARDK/AR/_CppAddressAndScale.cs.meta new file mode 100644 index 0000000..3f3178a --- /dev/null +++ b/Assets/ARDK/AR/_CppAddressAndScale.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9583e41e72d8d4b1d8224bca60cc3307 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/_IARSession.cs b/Assets/ARDK/AR/_IARSession.cs new file mode 100644 index 0000000..92ead43 --- /dev/null +++ b/Assets/ARDK/AR/_IARSession.cs @@ -0,0 +1,17 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.AR.Configuration; + +namespace Niantic.ARDK.AR +{ + internal interface _IARSession: + IARSession + { + ARSessionChangesCollector ARSessionChangesCollector { get; } + + /// Gets how this session will transition the AR state when re-run. + ARSessionRunOptions RunOptions { get; } + + bool IsPlayback { get; } + } +} diff --git a/Assets/ARDK/AR/_IARSession.cs.meta b/Assets/ARDK/AR/_IARSession.cs.meta new file mode 100644 index 0000000..f4c68bd --- /dev/null +++ b/Assets/ARDK/AR/_IARSession.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3af03078328a446e99881c14f662751c +timeCreated: 1613581197 \ No newline at end of file diff --git a/Assets/ARDK/AR/_NativeARSession.cs b/Assets/ARDK/AR/_NativeARSession.cs new file mode 100644 index 0000000..5d8aaa0 --- /dev/null +++ b/Assets/ARDK/AR/_NativeARSession.cs @@ -0,0 +1,1940 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading; + +using AOT; + +using UnityEngine; +using UnityEngine.Rendering; + +using Niantic.ARDK.AR.Anchors; +using Niantic.ARDK.AR.ARSessionEventArgs; +using Niantic.ARDK.AR.Awareness; +using Niantic.ARDK.AR.Camera; +using Niantic.ARDK.AR.Configuration; +using Niantic.ARDK.AR.Awareness.Depth.Generators; +using Niantic.ARDK.AR.Frame; +using Niantic.ARDK.AR.PointCloud; +using Niantic.ARDK.AR.Mesh; +using Niantic.ARDK.AR.SLAM; +using Niantic.ARDK.Extensions.Meshing; +using Niantic.ARDK.Internals; +using Niantic.ARDK.LocationService; +using Niantic.ARDK.Rendering; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers; +using Niantic.ARDK.Utilities.Collections; +using Niantic.ARDK.Utilities.Logging; + +namespace Niantic.ARDK.AR +{ + /// + internal sealed class _NativeARSession: + _ThreadCheckedObject, + _IARSession + { + /// Indicates whether this is a playback based session + private bool _playbackEnabled = false; + + RuntimeEnvironment IARSession.RuntimeEnvironment + { + // Maybe Playback will become a different Kind... for now, LiveDevice is the only one available. + get => RuntimeEnvironment.LiveDevice; + } + + public bool IsPlayback { get { return _playbackEnabled; } } + + /// + public IARConfiguration Configuration { get; private set; } + + private IARFrame _currentFrame; + /// + public IARFrame CurrentFrame + { + get => _currentFrame; + internal set + { + _CheckThread(); + + _SessionFrameSharedLogic._MakeSessionFrameBecomeNonCurrent(this); + _currentFrame = value; + } + } + + public ARSessionChangesCollector ARSessionChangesCollector { get; private set; } + + /// + public ARFrameDisposalPolicy DefaultFrameDisposalPolicy { get; set; } + +#pragma warning disable 0414 + private DepthPointCloudGenerator _depthPointCloudGen; +#pragma warning restore 0414 + + private _NativeLocationServiceAdapter _locationServiceAdapter; + private bool _hasSetupCommandBuffer; + private _VirtualCamera _virtualCamera; + + /// + public float WorldScale { get; set; } = 1; + + public ARSessionRunOptions RunOptions { get; private set; } + + /// + public Guid StageIdentifier { get; } + + static _NativeARSession() + { + Platform.Init(); + } + + /// + public ARSessionState State { get; private set; } + + public IARMesh Mesh + { + get => _meshDataParser; + } + + private _MeshDataParser _meshDataParser = new _MeshDataParser(); + + /// + internal _NativeARSession(Guid stageIdentifier, bool playbackEnabled=false) + { + _FriendTypeAsserter.AssertCallerIs(typeof(ARSessionFactory)); + +#if UNITY_ANDROID + if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Vulkan) + ARLog._Error("AR Core is not compatible with Vulkan. You're going to get a black screen."); +#endif + + ARLog._DebugFormat("Creating _NativeARSession with stage identifier: {0}", false, stageIdentifier); + + StageIdentifier = stageIdentifier; + _playbackEnabled = playbackEnabled; + ARSessionChangesCollector = new ARSessionChangesCollector(this); + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + if (playbackEnabled) + _nativeHandle = _NARPlaybackSession_Init(StageIdentifier.ToByteArray()); + else + _nativeHandle = _NARSession_Init(StageIdentifier.ToByteArray()); + + // Inform the GC that this class is holding a large native object, so it gets cleaned up fast + // TODO(awang): Make an IReleasable interface that handles this for all native-related classes + GC.AddMemoryPressure(GCPressure); + + ARLog._DebugFormat("Created _NativeARSession with handle: {0}", false, _nativeHandle); + SubscribeToInternalCallbacks(); + } + #pragma warning disable 0162 + else + { + _nativeHandle = (IntPtr)1; + } + #pragma warning restore 0162 + } + + ~_NativeARSession() + { + Dispose(false); + } + + /// + public void Dispose() + { + _CheckThread(); + + ARLog._Debug($"Dispose called on {nameof(_NativeARSession)}"); + + GC.SuppressFinalize(this); + Dispose(true); + } + + private void Dispose(bool disposing) + { + if (disposing) + { + var deinitializing = Deinitialized; + if (deinitializing != null) + { + var args = new ARSessionDeinitializedArgs(); + deinitializing(args); + } + + DisposeGenerators(); + + var cachedAnchors = _cachedAnchors; + if (cachedAnchors != null) + { + _cachedAnchors = null; + + foreach (var anchor in cachedAnchors.Values) + anchor.Dispose(); + } + + CurrentFrame?.Dispose(); + CurrentFrame = null; + ARSessionChangesCollector = null; + + _meshDataParser?.Dispose(); + _meshDataParser = null; + } + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + _NARSession_Release(_nativeHandle); + GC.RemoveMemoryPressure(GCPressure); + + ARLog._Debug("Released native ARSession objects"); + } + + _cachedHandle.Free(); + _cachedHandleIntPtr = IntPtr.Zero; + + _nativeHandle = IntPtr.Zero; + ARLog._Debug("Done disposing _NativeARSession"); + } + + private void DisposeGenerators() + { + var depthPointCloudGen = _depthPointCloudGen; + if (depthPointCloudGen != null) + { + _depthPointCloudGen = null; + depthPointCloudGen.Dispose(); + ARLog._Debug("Disposed depth point cloud generator"); + } + } + + public bool IsDestroyed + { + get => _nativeHandle == IntPtr.Zero; + } + + /// + public void Run + ( + IARConfiguration configuration, + ARSessionRunOptions options = ARSessionRunOptions.None + ) + { + _CheckThread(); + + if (_nativeHandle == IntPtr.Zero) + { + ARLog._Debug("Session was freed before Run()"); + return; + } + + ARSessionChangesCollector._CollectChanges(configuration, ref options); + + if (!_ARConfigurationValidator.RunAllChecks(this, configuration)) + { + ARLog._Error("Configuration validation failed, not running session"); + return; + } + + Configuration = configuration; + RunOptions = options; + + // Need to destroy the generators so they can be recreated once we get new depth data + DisposeGenerators(); + + if ((RunOptions & ARSessionRunOptions.RemoveExistingMesh) != 0) + _meshDataParser.Clear(); + +#if UNITY_ANDROID && !UNITY_EDITOR + if (!_hasSetupCommandBuffer) + { + var msg = + "No command buffer was set up to fetch ARCore updates, so _NativeARSession" + + " will create and set up execution of one on a new virtual camera. This virtual" + + " camera will be disposed if ARSessionBuffersHelper.IssuePluginEventAndData is " + + " called to explicitly set up a command buffer later."; + ARLog._Debug(msg); + + var commandBuffer = new CommandBuffer(); + commandBuffer.IssuePluginEventAndData(this); + _virtualCamera = _VirtualCameraFactory.CreateContinousVirtualCamera(commandBuffer); + } +#endif + + ARLog._DebugFormat("Running _NativeARSession with options: {0}", false, options); + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + var nativeConfiguration = (_NativeARConfiguration)configuration; + _NARSession_Run(_nativeHandle, nativeConfiguration._NativeHandle, (UInt64)options); + } + + State = ARSessionState.Running; + _ran(new ARSessionRanArgs()); + } + + /// + public void Pause() + { + _CheckThread(); + + ARLog._Debug("Pausing _NativeARSession"); + + CurrentFrame = null; + + if (_nativeHandle == IntPtr.Zero) + { + ARLog._Debug("Session was freed before Pause()"); + return; + } + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + _NARSession_Pause(_nativeHandle); + ARLog._Debug("Called pause on native object"); + } + + State = ARSessionState.Paused; + _paused(new ARSessionPausedArgs()); + } + + /// + public IARAnchor AddAnchor(Matrix4x4 transform) + { + _CheckThread(); + + if (_nativeHandle == IntPtr.Zero) + { + ARLog._Debug("Session was freed before AddAnchor()"); + return null; // TODO: Should we log error and throw here? + } + + var anchor = _ARAnchorFactory._Create(transform); + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + var nativeAnchor = anchor as _NativeARAnchor; + if (nativeAnchor != null) + { + _NARSession_AddAnchor(_nativeHandle, nativeAnchor._NativeHandle); + + var identifier = nativeAnchor.Identifier; + if (!_cachedAnchors.ContainsKey(identifier)) + _cachedAnchors.Add(identifier, nativeAnchor); + + ARLog._DebugFormat("Added native anchor {0}", false, identifier); + } + else + { + ARLog._Debug("Anchor creation failed, did not add native anchor"); + } + } + + return anchor; + } + + /// + public void RemoveAnchor(IARAnchor anchor) + { + _CheckThread(); + + if (_nativeHandle == IntPtr.Zero) + { + ARLog._Debug("Session was freed before RemoveAnchor()"); + return; + } + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + ARLog._DebugFormat("Removing native anchor {0}", false, anchor.Identifier); + var nativeAnchor = anchor as _NativeARAnchor; + if (nativeAnchor != null) + _NARSession_RemoveAnchor(_nativeHandle, nativeAnchor._NativeHandle); + } + } + + internal bool _IsLocationServiceInitialized() + { + return _locationServiceAdapter != null; + } + + public void SetupLocationService(ILocationService locationService) + { + _CheckThread(); + + if (_locationServiceAdapter != null) + { + ARLog._Error("This ARSession is already listening to a LocationService instance."); + return; + } + + _locationServiceAdapter = + new _NativeLocationServiceAdapter(StageIdentifier, locationService); + + _locationServiceAdapter.AssignWrapper(locationService); + } + + private struct AwarenessFeaturesCheckStatus + { + public AwarenessInitializationStatus Status; + public AwarenessInitializationError Error; + public string Message; + } + + private AwarenessFeaturesCheckStatus? _awarenessFeaturesCheck; + + public AwarenessInitializationStatus GetAwarenessInitializationStatus + ( + out AwarenessInitializationError error, + out string errorMessage + ) + { + _CheckThread(); + + if (_nativeHandle != IntPtr.Zero) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + var code = (_NativeAwarenessInitializationCode)_NARSession_GetAwarenessFeaturesError(_nativeHandle); + var status = code.ToStatus(); + error = code.ToError(); + + var complete = + status == AwarenessInitializationStatus.Ready || + status == AwarenessInitializationStatus.Failed; + + if (complete) + { + var ptr = _NARSession_GetAwarenessFeaturesErrorMessage(_nativeHandle); + if (ptr != IntPtr.Zero) + errorMessage = Marshal.PtrToStringAnsi(ptr); + else + errorMessage = string.Empty; + + _awarenessFeaturesCheck = + new AwarenessFeaturesCheckStatus + { + Status = code.ToStatus(), + Error = code.ToError(), + Message = errorMessage + }; + } + else + { + errorMessage = string.Empty; + } + + return status; + } + } + else + { + ARLog._Debug("Session was freed before call to _GetAwarenessFeaturesStatus()"); + } + + // Default values when native was not queried + error = AwarenessInitializationError.None; + errorMessage = string.Empty; + return AwarenessInitializationStatus.Unknown; + } + + internal void SetupCommandBuffer(CommandBuffer commandBuffer) + { + _CheckThread(); + + if (_hasSetupCommandBuffer && _virtualCamera == null) + { + ARLog._Debug("Multiple command buffers are being set up to fetch AR updates." + + "This is expected on the Android platform, but may not be desired otherwise."); + } + + if (_virtualCamera != null) + { + _virtualCamera.Dispose(); + _virtualCamera = null; + + ARLog._Debug("A command buffer was explicitly set up to fetch AR updates, so the virtual " + + " camera set up to do so previously has been disposed."); + } + + commandBuffer.IssuePluginEventAndData(GetRenderEventFunc(), 1, _nativeHandle); + _hasSetupCommandBuffer = true; + } + + /// @name Events + /// @{ + /// + public event ArdkEventHandler Deinitialized; + + /// + public event ArdkEventHandler Ran + { + add + { + _CheckThread(); + + _ran += value; + + if (State == ARSessionState.Running) + value(new ARSessionRanArgs()); + } + remove => _ran -= value; + } + + /// + public event ArdkEventHandler Paused + { + add + { + _CheckThread(); + + _paused += value; + + if (State == ARSessionState.Paused) + value(new ARSessionPausedArgs()); + } + remove => _paused -= value; + } + + private ArdkEventHandler _frameUpdated; + + /// + public event ArdkEventHandler FrameUpdated + { + add + { + _CheckThread(); + + SubscribeToDidUpdateFrame(); + + _frameUpdated += value; + } + remove => _frameUpdated -= value; + } + + private ArdkEventHandler _anchorsAdded; + + /// + public event ArdkEventHandler AnchorsAdded + { + add + { + _CheckThread(); + + SubscribeToDidAddAnchors(); + + _anchorsAdded += value; + } + remove => _anchorsAdded -= value; + } + + + private ArdkEventHandler _anchorsUpdated; + + /// + public event ArdkEventHandler AnchorsUpdated + { + add + { + _CheckThread(); + + SubscribeToDidUpdateAnchors(); + + _anchorsUpdated += value; + } + remove => _anchorsUpdated -= value; + } + + + private ArdkEventHandler _anchorsRemoved; + + /// + public event ArdkEventHandler AnchorsRemoved + { + add + { + _CheckThread(); + + SubscribeToDidRemoveAnchors(); + + _anchorsRemoved += value; + } + remove => _anchorsRemoved -= value; + } + + /// + public event ArdkEventHandler AnchorsMerged + { + add + { + _CheckThread(); + + SubscribeToDidMergeAnchors(); + + _anchorsMerged += value; + } + remove => _anchorsMerged -= value; + } + + private ArdkEventHandler _mapsAdded; + + /// + public event ArdkEventHandler MapsAdded + { + add + { + _CheckThread(); + + SubscribeToDidAddMaps(); + + _mapsAdded += value; + } + remove => _mapsAdded -= value; + } + + + private ArdkEventHandler _mapsUpdated; + + /// + public event ArdkEventHandler MapsUpdated + { + add + { + _CheckThread(); + + SubscribeToDidUpdateMaps(); + + _mapsUpdated += value; + } + remove => _mapsUpdated -= value; + } + + private ArdkEventHandler _cameraTrackingStateChanged; + + /// + public event ArdkEventHandler CameraTrackingStateChanged + { + add + { + _CheckThread(); + + SubscribeToCameraDidChangeTrackingState(); + + _cameraTrackingStateChanged += value; + } + remove => _cameraTrackingStateChanged -= value; + } + + /// + public event ArdkEventHandler SessionInterrupted + { + add + { + _CheckThread(); + + SubscribeToWasInterrupted(); + + _sessionInterrupted += value; + } + remove => _sessionInterrupted -= value; + } + + /// + public event ArdkEventHandler SessionInterruptionEnded + { + add + { + _CheckThread(); + + SubscribeToInterruptionEnded(); + + _sessionInterruptionEnded += value; + } + remove => _sessionInterruptionEnded -= value; + } + + /// + public event ArdkEventHandler + QueryingShouldSessionAttemptRelocalization + { + add + { + _CheckThread(); + + SubscribeToShouldAttemptRelocalization(); + + _queryingShouldSessionAttemptRelocalization.Add(value); + } + remove => _queryingShouldSessionAttemptRelocalization.Remove(value); + } + + /// + public event ArdkEventHandler SessionFailed + { + add + { + _CheckThread(); + + SubscribeToDidFailWithError(); + + _sessionFailed += value; + } + remove => _sessionFailed -= value; + } + + /// @} + + // Private handles and code to deal with native callbacks and initialization + private IntPtr _nativeHandle; + + // Caching `this` for native device callbacks + private IntPtr _cachedHandleIntPtr = IntPtr.Zero; + private SafeGCHandle<_NativeARSession> _cachedHandle; + + // Approx memory consumption of native objects + ARCore/ARKit session + // Magic number representing 100MB, which is approximately the profiled + // consumption on an iPhone 8 + private const long GCPressure = 100L * 1024L * 1024L; + + private IntPtr _handle + { + get + { + _CheckThread(); + + var cachedHandleIntPtr = _cachedHandleIntPtr; + if (cachedHandleIntPtr != IntPtr.Zero) + return cachedHandleIntPtr; + + _cachedHandle = SafeGCHandle.Alloc(this); + cachedHandleIntPtr = _cachedHandle.ToIntPtr(); + _cachedHandleIntPtr = cachedHandleIntPtr; + + return cachedHandleIntPtr; + } + } + +#region CallbackImplementation + private bool _updateFrameInitialized; + private bool _updateMeshInitialized; + private bool _addAnchorsInitialized; + private bool _updateAnchorsInitialized; + private bool _removeAnchorsInitialized; + private bool _mergeAnchorsInitialized; + private bool _addMapsInitialized; + private bool _updateMapsInitialized; + + private bool _cameraDidChangeTrackingStateInitialized; + private bool _sessionWasInterruptedInitialized; + private bool _sessionInterruptionEndedInitialized; + private bool _sessionShouldAttemptRelocalizationInitialized; + private bool _sessionDidFailWithErrorInitialized; + +#region InternalSubscriptions + // This callback is subscribed to at initialization as it sets data that will be provided by + // accessors (CurrentFrame and Mesh) + private void SubscribeToInternalCallbacks() + { + SubscribeToDidUpdateFrame(); + SubscribeToDidUpdateMesh(); + } + + private void SubscribeToDidUpdateFrame() + { + _CheckThread(); + + if (_updateFrameInitialized) + return; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + _NARSession_Set_didUpdateFrameCallback + ( + _handle, + _nativeHandle, + _onDidUpdateFrameNative + ); + + ARLog._Debug("Subscribed to native frame update"); + } + + _updateFrameInitialized = true; + } + + internal void SubscribeToDidUpdateMesh() + { + if (_updateMeshInitialized) + return; + + lock (this) + { + if (_updateMeshInitialized) + return; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + _NARSession_Set_didUpdateMeshCallback(_handle, _nativeHandle, _onDidUpdateMeshNative); + } + + _updateMeshInitialized = true; + } + } + + private void SubscribeToDidAddAnchors() + { + _CheckThread(); + + if (_addAnchorsInitialized) + return; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + _NARSession_Set_didAddAnchorsCallback + ( + _handle, + _nativeHandle, + _onDidAddAnchorsNative + ); + + ARLog._Debug("Subscribed to native anchors added"); + } + + _addAnchorsInitialized = true; + } + + private void SubscribeToDidUpdateAnchors() + { + _CheckThread(); + + if (_updateAnchorsInitialized) + return; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + _NARSession_Set_didUpdateAnchorsCallback + ( + _handle, + _nativeHandle, + _onDidUpdateAnchorsNative + ); + + ARLog._Debug("Subscribed to native anchors updated"); + } + + _updateAnchorsInitialized = true; + } + + private void SubscribeToDidRemoveAnchors() + { + _CheckThread(); + + if (_removeAnchorsInitialized) + return; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + _NARSession_Set_didRemoveAnchorsCallback + ( + _handle, + _nativeHandle, + _onDidRemoveAnchorsNative + ); + + ARLog._Debug("Subscried to native anchors removed"); + } + + _removeAnchorsInitialized = true; + } + + private unsafe void SubscribeToDidMergeAnchors() + { + _CheckThread(); + + if (_mergeAnchorsInitialized) + return; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + _NARSession_Set_didMergeAnchorsCallback + ( + _handle, + _nativeHandle, + _onDidMergeAnchorsNative + ); + + ARLog._Debug("Subscribed to native anchors merged"); + } + + _mergeAnchorsInitialized = true; + } + + private void SubscribeToDidAddMaps() + { + _CheckThread(); + + if (_addMapsInitialized) + return; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + _NARSession_Set_didAddMapsCallback + ( + _handle, + _nativeHandle, + _onDidAddMapsNative + ); + + ARLog._Debug("Subscribed to native maps added"); + } + + _addMapsInitialized = true; + } + + private void SubscribeToDidUpdateMaps() + { + _CheckThread(); + + if (_updateMapsInitialized) + return; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + _NARSession_Set_didUpdateMapsCallback + ( + _handle, + _nativeHandle, + _onDidUpdateMapsNative + ); + + ARLog._Debug("Subscribed to native maps updated"); + } + + _updateMapsInitialized = true; + } + + private void SubscribeToCameraDidChangeTrackingState() + { + _CheckThread(); + + if (_cameraDidChangeTrackingStateInitialized) + return; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + _NARSession_Set_cameraDidChangeTrackingStateCallback + ( + _handle, + _nativeHandle, + _onCameraDidChangeTrackingStateNative + ); + + ARLog._Debug("Subscribed to native camera tracking state updates"); + } + + _cameraDidChangeTrackingStateInitialized = true; + } + + private void SubscribeToWasInterrupted() + { + _CheckThread(); + + if (_sessionWasInterruptedInitialized) + return; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + _NARSession_Set_wasInterruptedCallback + ( + _handle, + _nativeHandle, + _onSessionWasInterruptedNative + ); + + ARLog._Debug("Subscribed to native session interrupted event"); + } + + _sessionWasInterruptedInitialized = true; + } + + private void SubscribeToInterruptionEnded() + { + _CheckThread(); + + if (_sessionInterruptionEndedInitialized) + return; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + _NARSession_Set_interruptionEndedCallback + ( + _handle, + _nativeHandle, + _onSessionInterruptionEndedNative + ); + + ARLog._Debug("Subscribed to native session interruption ended event"); + } + + _sessionInterruptionEndedInitialized = true; + } + + private void SubscribeToShouldAttemptRelocalization() + { + _CheckThread(); + + if (_sessionShouldAttemptRelocalizationInitialized) + return; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + _NARSession_Set_shouldAttemptRelocalizationCallback + ( + _handle, + _nativeHandle, + _onSessionShouldAttemptRelocalizationNative + ); + + ARLog._Debug("Subscribed to native should attempt relocalization event"); + } + + _sessionShouldAttemptRelocalizationInitialized = true; + } + + private void SubscribeToDidFailWithError() + { + _CheckThread(); + + if (_sessionDidFailWithErrorInitialized) + return; + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + _NARSession_Set_didFailWithErrorCallback + ( + _handle, + _nativeHandle, + _onSessionDidFailWithErrorNative + ); + + ARLog._Debug("Subscribed to native session failed event"); + } + + _sessionDidFailWithErrorInitialized = true; + } + +#endregion + +#region NativeCallbacks + + private ArdkEventHandler _anchorsMerged = args => {}; + + private ArdkEventHandler _sessionInterrupted = (args) => {}; + + private ArdkEventHandler _sessionInterruptionEnded = (args) => {}; + + private readonly List> + _queryingShouldSessionAttemptRelocalization = + new List>(); + + private ArdkEventHandler _sessionFailed = args => {}; + + private ArdkEventHandler _ran = args => {}; + + private ArdkEventHandler _paused = args => {}; + + private IntPtr _newestFramePtr; + + [MonoPInvokeCallback(typeof(_ARSession_Frame_Callback))] + private static void _onDidUpdateFrameNative(IntPtr context, IntPtr framePtr) + { + ARLog._Debug("Got a frame from native", true); + var session = SafeGCHandle.TryGetInstance<_NativeARSession>(context); + if (session == null || session.IsDestroyed) + { + // session was deallocated + _NativeARFrame._ReleaseImmediate(framePtr); + ARLog._Debug("Native session surfaced a frame after the session was released", true); + return; + } + + var oldFramePtr = Interlocked.Exchange(ref session._newestFramePtr, framePtr); + if (oldFramePtr != IntPtr.Zero) + { + // We release the old frame, as now framePtr is stored as _newestFrame. + // The already scheduled callback queue will get our newestFrame to process. + _NativeARFrame._ReleaseImmediate(oldFramePtr); + ARLog._Debug("Releasing frame generated before prior one was processed.", true); + return; + } + + _CallbackQueue.QueueCallback + ( + () => + { + var newFramePtr = Interlocked.Exchange(ref session._newestFramePtr, IntPtr.Zero); + if (session.IsDestroyed) + { + // session was deallocated + _NativeARFrame._ReleaseImmediate(newFramePtr); + ARLog._Debug("Native session surfaced a frame after the session was released", true); + + return; + } + + var frame = new _NativeARFrame(newFramePtr, session.WorldScale); + + session.CurrentFrame = frame; + session.UpdateGenerators(frame); + + var handler = session._frameUpdated; + if (handler != null) + { + var args = new FrameUpdatedArgs(frame); + handler(args); + } + } + ); + } + + private void UpdateGenerators(IARFrame frame) + { + // There's a race condition here if a previous run (with IARWorldTrackingConfiguration) + // surfaces a frame, then the user re-runs the session with a non-IARWorldTrackingConfiguration + // before the frame is handled by the CallbackQueue. So we need to do a safe cast. + if (!(Configuration is IARWorldTrackingConfiguration worldConfig)) + return; + + if (!worldConfig.IsDepthPointCloudEnabled) + return; + + var depthBuffer = frame.Depth; + if (depthBuffer == null || !depthBuffer.IsKeyframe) + return; + + // Create a generator if needed + if (_depthPointCloudGen == null) + { + _depthPointCloudGen = new DepthPointCloudGenerator(); + ARLog._Debug("Created new depth point cloud generator"); + } + + // Generate the point cloud + var pointCloud = _depthPointCloudGen.GeneratePointCloud(frame.Depth, frame.Camera); + ARLog._Debug("Updated depth point cloud generator with new keyframe", true); + + // TODO : Add pooling + var arFrame = (_IARFrame)frame; + arFrame.DepthPointCloud = pointCloud; + } + + private static void DestroyFrame(IntPtr framePtr, float worldScale = 1f) + { + _NativeARFrame._ReleaseImmediate(framePtr); + } + + // Caches the anchors we already know of and should dispose in the future. + // Can only be accessed by the main thread. + private Dictionary _cachedAnchors = + new Dictionary(); + + [MonoPInvokeCallback(typeof(_ARSession_Anchor_Callback))] + private static void _onDidAddAnchorsNative + ( + IntPtr context, + IntPtr anchorsPtrs, + UInt64 anchorsCount + ) + { + var session = SafeGCHandle.TryGetInstance<_NativeARSession>(context); + if (session == null || session.IsDestroyed) + { + // session was deallocated + DestroyAnchors(anchorsPtrs, anchorsCount); + return; + } + + var anchors = new _NativeARAnchor[anchorsCount]; + + for (var i = 0; i < (int)anchorsCount; i++) + { + var nativeHandle = Marshal.ReadIntPtr(anchorsPtrs, i * IntPtr.Size); + anchors[i] = _ARAnchorFactory._FromNativeHandle(nativeHandle); + } + + _CallbackQueue.QueueCallback + ( + () => + { + if (session.IsDestroyed) + { + foreach (var anchor in anchors) + anchor.Dispose(); + + return; + } + + ARLog._Debug("Surfacing added anchors"); + + for (var i = 0; i < (int)anchorsCount; i++) + { + var anchor = anchors[i]; + + var id = anchor.Identifier; + + if (!session._cachedAnchors.ContainsKey(id)) + session._cachedAnchors.Add(id, anchor); + } + + var handler = session._anchorsAdded; + if (handler != null) + { + var args = new AnchorsArgs(anchors); + handler(args); + } + } + ); + } + + [MonoPInvokeCallback(typeof(_ARSession_Anchor_Callback))] + private static void _onDidUpdateAnchorsNative + ( + IntPtr context, + IntPtr anchorsPtrs, + UInt64 anchorsCount + ) + { + var session = SafeGCHandle.TryGetInstance<_NativeARSession>(context); + if (session == null || session.IsDestroyed) + { + // session was deallocated + DestroyAnchors(anchorsPtrs, anchorsCount); + return; + } + + var anchors = new _NativeARAnchor[anchorsCount]; + + for (var i = 0; i < (int)anchorsCount; i++) + { + var nativeHandle = Marshal.ReadIntPtr(anchorsPtrs, i * IntPtr.Size); + anchors[i] = _ARAnchorFactory._FromNativeHandle(nativeHandle); + } + + _CallbackQueue.QueueCallback + ( + () => + { + if (session.IsDestroyed) + { + foreach (var anchor in anchors) + anchor.Dispose(); + + return; + } + + foreach (var anchor in anchors) + { + var id = anchor.Identifier; + + if (!session._cachedAnchors.ContainsKey(id)) + { + ARLog._Warn("Updated anchor not found in session cache."); + + session._cachedAnchors.Add(id, anchor); + } + } + + var handler = session._anchorsUpdated; + if (handler != null) + { + var args = new AnchorsArgs(anchors); + handler(args); + } + } + ); + } + + [MonoPInvokeCallback(typeof(_ARSession_Anchor_Callback))] + private static void _onDidRemoveAnchorsNative + ( + IntPtr context, + IntPtr anchorsPtrs, + UInt64 anchorsCount + ) + { + var session = SafeGCHandle.TryGetInstance<_NativeARSession>(context); + if (session == null || session.IsDestroyed) + { + // session was deallocated + DestroyAnchors(anchorsPtrs, anchorsCount); + return; + } + + var anchors = new IARAnchor[anchorsCount]; + + for (var i = 0; i < (int)anchorsCount; i++) + { + var nativeHandle = Marshal.ReadIntPtr(anchorsPtrs, i * IntPtr.Size); + anchors[i] = _ARAnchorFactory._FromNativeHandle(nativeHandle); + } + + _CallbackQueue.QueueCallback + ( + () => + { + if (session.IsDestroyed) + { + for (var i = 0; i < (int)anchorsCount; i++) + anchors[i].Dispose(); + + return; + } + + ARLog._Debug("Surfacing removed anchors"); + + var handler = session._anchorsRemoved; + if (handler != null) + { + var args = new AnchorsArgs(anchors); + handler(args); + } + + foreach (var anchor in anchors) + { + // Anchor could have been removed by the MergeAnchor operation + if (anchor.IsDisposed()) + continue; + + var id = anchor.Identifier; + anchor.Dispose(); + session._cachedAnchors.Remove(id); + } + } + ); + } + + [StructLayout(LayoutKind.Sequential)] + private unsafe struct ArrayOfMergeInfo + { + public MergeInfo* array; + public UInt32 arraySize; + } + + [StructLayout(LayoutKind.Sequential)] + private unsafe struct MergeInfo + { + public IntPtr parent; + public IntPtr* children; + public UInt32 childrenSize; + } + + [MonoPInvokeCallback(typeof(_ARSession_Merge_Anchor_Callback))] + private unsafe static void _onDidMergeAnchorsNative + ( + IntPtr context, + ArrayOfMergeInfo* anchorsPtrs + ) + { + var session = SafeGCHandle.TryGetInstance<_NativeARSession>(context); + var parentCount = anchorsPtrs->arraySize; + MergeInfo* mergeInfoArray = anchorsPtrs->array; + if (session == null || session.IsDestroyed) + { + // session was deallocated + for (int i = 0; i < parentCount; i++) + { + var mergeInfo = mergeInfoArray[i]; + + var childrenSize = mergeInfo.childrenSize; + for (int j = 0; j < childrenSize; j++) + _NativeARAnchor._ReleaseImmediate(mergeInfo.children[j]); + + _NativeARAnchor._ReleaseImmediate(mergeInfo.parent); + } + + return; + } + + var mergedAnchors = new Dictionary(); + for (int i = 0; i < (int)parentCount; i++) + { + var mergeInfo = mergeInfoArray[i]; + IntPtr parentNativeHandle = mergeInfo.parent; + var childrenSize = mergeInfo.childrenSize; + IARPlaneAnchor[] childrenAsPlanes = new IARPlaneAnchor[childrenSize]; + + for (int j = 0; j < childrenSize; j++) + { + IntPtr childNativeHandle = mergeInfo.children[j]; + var child = _ARAnchorFactory._FromNativeHandle(childNativeHandle); + childrenAsPlanes[j] = (IARPlaneAnchor)child; + } + + var parent = _ARAnchorFactory._FromNativeHandle(parentNativeHandle); + mergedAnchors.Add((IARPlaneAnchor)parent, childrenAsPlanes); + } + + _CallbackQueue.QueueCallback + ( + () => + { + if (session.IsDestroyed) + { + foreach (var merge in mergedAnchors) + { + foreach (var child in merge.Value) + child.Dispose(); + + merge.Key.Dispose(); + } + + return; + } + + ARLog._Debug("Surfacing merged anchors"); + + var handler = session._anchorsMerged; + if (handler != null) + { + foreach (var pair in mergedAnchors) + { + // TODO ecomas: args should be a read only dictionary, so we can just invoke the event + // once. + var args = new AnchorsMergedArgs(pair.Key, pair.Value); + handler(args); + } + } + + foreach (var pair in mergedAnchors) + { + var childCollection = pair.Value; + foreach (var child in childCollection) + { + var id = child.Identifier; + child.Dispose(); + session._cachedAnchors.Remove(id); + } + } + } + ); + } + + /// + /// Destroys the list of anchors received from native without generating objects. + /// + /// List of native handles to anchors + /// Number of anchors in the list + private static void DestroyAnchors + ( + IntPtr anchorsPtrs, + UInt64 anchorsCount + ) + { + ARLog._DebugFormat + ( + "Releasing {0} native anchors directly, the session was released already", + false, + anchorsCount + ); + + for (var i = 0; i < (int)anchorsCount; i++) + { + var nativeHandle = Marshal.ReadIntPtr(anchorsPtrs, i * IntPtr.Size); + _NativeARAnchor._ReleaseImmediate(nativeHandle); + } + } + + [MonoPInvokeCallback(typeof(_ARSession_Map_Callback))] + private static void _onDidAddMapsNative + ( + IntPtr context, + IntPtr mapPtrs, + UInt64 mapsCount + ) + { + var session = SafeGCHandle.TryGetInstance<_NativeARSession>(context); + if (session == null || session.IsDestroyed) + { + // session was deallocated + DestroyMaps(mapPtrs, mapsCount); + return; + } + + var maps = new IARMap[mapsCount]; + + for (var i = 0; i < (int)mapsCount; i++) + { + var nativeHandle = Marshal.ReadIntPtr(mapPtrs, i * IntPtr.Size); + maps[i] = _NativeARMap._FromNativeHandle(nativeHandle, session.WorldScale); + } + + _CallbackQueue.QueueCallback + ( + () => + { + if (session.IsDestroyed) + { + // session was deallocated + for (var i = 0; i < (int)mapsCount; i++) + maps[i].Dispose(); + + return; + } + + ARLog._Debug("Surfacing added maps"); + var handler = session._mapsAdded; + if (handler != null) + { + var args = new MapsArgs(maps); + handler(args); + } + } + ); + } + + [MonoPInvokeCallback(typeof(_ARSession_Map_Callback))] + private static void _onDidUpdateMapsNative + ( + IntPtr context, + IntPtr mapPtrs, + UInt64 mapsCount + ) + { + var session = SafeGCHandle.TryGetInstance<_NativeARSession>(context); + if (session == null || session.IsDestroyed) + { + // session was deallocated + DestroyMaps(mapPtrs, mapsCount); + return; + } + + var maps = new IARMap[mapsCount]; + + for (var i = 0; i < (int)mapsCount; i++) + { + var nativeHandle = Marshal.ReadIntPtr(mapPtrs, i * IntPtr.Size); + maps[i] = _NativeARMap._FromNativeHandle(nativeHandle, session.WorldScale); + } + + _CallbackQueue.QueueCallback + ( + () => + { + if (session.IsDestroyed) + { + // session was deallocated + for (var i = 0; i < (int)mapsCount; i++) + maps[i].Dispose(); + + return; + } + + ARLog._Debug("Surfacing updated maps"); + var handler = session._mapsUpdated; + if (handler != null) + { + var args = new MapsArgs(maps); + handler(args); + } + } + ); + } + + private static void DestroyMaps(IntPtr mapPtrs, UInt64 mapsCount, float worldScale = 1f) + { + ARLog._DebugFormat + ( + "Releasing {0} maps directly, the session was released already", + false, + mapsCount + ); + + for (var i = 0; i < (int)mapsCount; i++) + { + var nativeHandle = Marshal.ReadIntPtr(mapPtrs, i * IntPtr.Size); + _NativeARMap._ReleaseImmediate(nativeHandle); + } + } + + [MonoPInvokeCallback(typeof(_ARSession_Mesh_Callback))] + private static void _onDidUpdateMeshNative(IntPtr context, IntPtr meshPtr) + { + var meshData = new _NativeARMeshData(meshPtr); + var session = SafeGCHandle.TryGetInstance<_NativeARSession>(context); + if (session == null || session.IsDestroyed) + { + // session was deallocated + meshData.Dispose(); + return; + } + + _CallbackQueue.QueueCallback + ( + () => + { + if (session.IsDestroyed) + { + // session was deallocated + meshData.Dispose(); + return; + } + + session._meshDataParser.ParseMesh(meshData); + meshData.Dispose(); + } + ); + } + + [MonoPInvokeCallback(typeof(_ARSession_Camera_Callback))] + private static void _onCameraDidChangeTrackingStateNative(IntPtr context, IntPtr cameraPtr) + { + var session = SafeGCHandle.TryGetInstance<_NativeARSession>(context); + if (session == null || session.IsDestroyed) + { + // session was deallocated + _NativeARCamera._ReleaseImmediate(cameraPtr); + return; + } + + _CallbackQueue.QueueCallback + ( + () => + { + if (session.IsDestroyed) + { + // session was deallocated + _NativeARCamera._ReleaseImmediate(cameraPtr); + return; + } + + // Using a constructor here instead of caching + reusing objects in _NativeARCamera._FromNativeHandle + // We are disposing the camera every frame to prevent a crash on exit. Reintroduce caching + // in a way that supports disposing. + var camera = new _NativeARCamera(cameraPtr, session.WorldScale); + + ARLog._DebugFormat("Surfacing camera tracking state: {0}", false, camera.TrackingState); + var handler = session._cameraTrackingStateChanged; + if (handler != null) + { + var args = new CameraTrackingStateChangedArgs(camera, camera.TrackingState); + handler(args); + } + } + ); + } + + [MonoPInvokeCallback(typeof(_ARSession_Void_Callback))] + private static void _onSessionWasInterruptedNative(IntPtr context) + { + var session = SafeGCHandle.TryGetInstance<_NativeARSession>(context); + if (session == null || session.IsDestroyed) + { + // session was deallocated + return; + } + + _CallbackQueue.QueueCallback + ( + () => + { + if (session.IsDestroyed) + { + // session was deallocated + return; + } + + ARLog._Debug("Surfacing session was interrupted"); + session._sessionInterrupted(new ARSessionInterruptedArgs()); + } + ); + } + + [MonoPInvokeCallback(typeof(_ARSession_Void_Callback))] + private static void _onSessionInterruptionEndedNative(IntPtr context) + { + var session = SafeGCHandle.TryGetInstance<_NativeARSession>(context); + if (session == null || session.IsDestroyed) + { + // session was deallocated + return; + } + + _CallbackQueue.QueueCallback + ( + () => + { + if (session.IsDestroyed) + { + // session was deallocated + return; + } + + ARLog._Debug("Surfacing session interruption ended"); + session._sessionInterruptionEnded(new ARSessionInterruptionEndedArgs()); + } + ); + } + + [MonoPInvokeCallback(typeof(_ARSession_Bool_Callback))] + private static bool _onSessionShouldAttemptRelocalizationNative(IntPtr context) + { + var session = SafeGCHandle.TryGetInstance<_NativeARSession>(context); + if (session == null || session.IsDestroyed) + { + // session was deallocated + return false; + } + + var handlers = session._queryingShouldSessionAttemptRelocalization; + if (handlers.Count == 0) + return false; + + var args = new QueryingShouldSessionAttemptRelocalizationArgs(); + foreach(var handler in handlers) + { + handler(args); + + ARLog._Debug("Surfacing session should attempt relocalization"); + if (args.ShouldSessionAttemptRelocalization) + return true; + } + + return false; + } + + [MonoPInvokeCallback(typeof(_ARSession_Failed_Callback))] + private static void _onSessionDidFailWithErrorNative(IntPtr context, UInt64 errorNo) + { + var session = SafeGCHandle.TryGetInstance<_NativeARSession>(context); + if (session == null || session.IsDestroyed) + { + // session was deallocated + return; + } + + var error = (ARError)errorNo; + + _CallbackQueue.QueueCallback + ( + () => + { + if (session.IsDestroyed) + { + // session was deallocated + return; + } + + session.State = ARSessionState.Failed; + ARLog._DebugFormat("Surfacing session failed with error: {0}", false, error); + var args = new ARSessionFailedArgs(error); + session._sessionFailed(args); + } + ); + } +#endregion +#endregion + +#region TestingShim + + internal static class _TestingShim + { + #pragma warning disable 0162 + // If the session has already been disposed, this method will incidentally recreate the + // session's _handle. To avoid this, use _GetHandle and the _InvokeDidReceiveFrame override + // that takes an IntPtr instead of a _NativeARSession. + internal static void _InvokeDidReceiveFrame(_NativeARSession session, IntPtr framePtr) + { + _InvokeDidReceiveFrame(session._handle, framePtr); + } + + internal static void _InvokeDidReceiveFrame(IntPtr sessionPtr, IntPtr framePtr) + { + if (NativeAccess.Mode == NativeAccess.ModeType.Testing) + _onDidUpdateFrameNative(sessionPtr, framePtr); + } + + internal static IntPtr _GetHandle(_NativeARSession session) + { + return session._handle; + } + #pragma warning restore 0162 + } + +#endregion + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NARSession_Init(byte[] stageIdentifier); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NARPlaybackSession_Init(byte[] stageIdentifier); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARSession_Release(IntPtr nativeSession); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARSession_Run + ( + IntPtr nativeSession, + IntPtr nativeConfig, + UInt64 options + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARSession_Pause(IntPtr nativeSession); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr GetRenderEventFunc(); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARSession_AddAnchor(IntPtr nativeSession, IntPtr nativeAnchor); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARSession_RemoveAnchor(IntPtr nativeSession, IntPtr nativeAnchor); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern UInt32 _NARSession_GetAwarenessFeaturesError(IntPtr nativeSession); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NARSession_GetAwarenessFeaturesErrorMessage(IntPtr nativeSession); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARSession_Set_didUpdateFrameCallback + ( + IntPtr applicationSession, + IntPtr platformSession, + _ARSession_Frame_Callback callback + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARSession_Set_didUpdateMeshCallback + ( + IntPtr applicationSession, + IntPtr platformSession, + _ARSession_Mesh_Callback callback + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARSession_Set_didAddAnchorsCallback + ( + IntPtr applicationSession, + IntPtr platformSession, + _ARSession_Anchor_Callback callback + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARSession_Set_didUpdateAnchorsCallback + ( + IntPtr applicationSession, + IntPtr platformSession, + _ARSession_Anchor_Callback callback + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARSession_Set_didRemoveAnchorsCallback + ( + IntPtr applicationSession, + IntPtr platformSession, + _ARSession_Anchor_Callback callback + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARSession_Set_didMergeAnchorsCallback + ( + IntPtr applicationSession, + IntPtr platformSession, + _ARSession_Merge_Anchor_Callback callback + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARSession_Set_didAddMapsCallback + ( + IntPtr applicationSession, + IntPtr platformSession, + _ARSession_Map_Callback callback + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARSession_Set_didUpdateMapsCallback + ( + IntPtr applicationSession, + IntPtr platformSession, + _ARSession_Map_Callback callback + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARSession_Set_cameraDidChangeTrackingStateCallback + ( + IntPtr applicationSession, + IntPtr platformSession, + _ARSession_Frame_Callback callback + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARSession_Set_wasInterruptedCallback + ( + IntPtr applicationSession, + IntPtr platformSession, + _ARSession_Void_Callback callback + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARSession_Set_interruptionEndedCallback + ( + IntPtr applicationSession, + IntPtr platformSession, + _ARSession_Void_Callback callback + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARSession_Set_shouldAttemptRelocalizationCallback + ( + IntPtr applicationSession, + IntPtr platformSession, + _ARSession_Bool_Callback callback + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARSession_Set_didFailWithErrorCallback + ( + IntPtr applicationSession, + IntPtr platformSession, + _ARSession_Failed_Callback callback + ); + + private delegate void _ARSession_Frame_Callback(IntPtr context, IntPtr frame); + + private delegate void _ARSession_Mesh_Callback(IntPtr context, IntPtr mesh); + + private delegate void _ARSession_Failed_Callback(IntPtr context, UInt64 error); + + private delegate void _ARSession_Void_Callback(IntPtr context); + + private delegate void _ARSession_Camera_Callback(IntPtr context, IntPtr camera); + + private unsafe delegate void _ARSession_Merge_Anchor_Callback + ( + IntPtr context, + ArrayOfMergeInfo* anchorsPtrs + ); + + private delegate void _ARSession_Anchor_Callback + ( + IntPtr context, + IntPtr nativeAnchor, + UInt64 anchorsCount + ); + + private delegate void _ARSession_Map_Callback + ( + IntPtr context, + IntPtr nativeMap, + UInt64 mapsCount + ); + + private delegate bool _ARSession_Bool_Callback(IntPtr context); + } +} diff --git a/Assets/ARDK/AR/_NativeARSession.cs.meta b/Assets/ARDK/AR/_NativeARSession.cs.meta new file mode 100644 index 0000000..1dca00d --- /dev/null +++ b/Assets/ARDK/AR/_NativeARSession.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 261ff4617f4944d89ae791fb9087b061 +timeCreated: 1547226717 +licenseType: Pro +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/AR/_SessionFrameSharedLogic.cs b/Assets/ARDK/AR/_SessionFrameSharedLogic.cs new file mode 100644 index 0000000..598bea8 --- /dev/null +++ b/Assets/ARDK/AR/_SessionFrameSharedLogic.cs @@ -0,0 +1,41 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +namespace Niantic.ARDK.AR +{ + internal static class _SessionFrameSharedLogic + { + internal static void _MakeSessionFrameBecomeNonCurrent(IARSession session) + { + var frame = session.CurrentFrame; + if (frame == null) + return; + + var nullableFrameDisposalPolicy = frame.DisposalPolicy; + + ARFrameDisposalPolicy frameDisposalPolicy; + if (nullableFrameDisposalPolicy.HasValue) + frameDisposalPolicy = nullableFrameDisposalPolicy.Value; + else + frameDisposalPolicy = session.DefaultFrameDisposalPolicy; + + switch (frameDisposalPolicy) + { + case ARFrameDisposalPolicy.DisposeOldFrames: + frame.Dispose(); + break; + + case ARFrameDisposalPolicy.ReleaseImageAndTexturesOfOldFrames: + frame.ReleaseImageAndTextures(); + break; + + case ARFrameDisposalPolicy.KeepOldFrames: + break; + + default: + throw new InvalidOperationException("Unknown ARFrameDisposalPolicy: " + frameDisposalPolicy); + } + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/AR/_SessionFrameSharedLogic.cs.meta b/Assets/ARDK/AR/_SessionFrameSharedLogic.cs.meta new file mode 100644 index 0000000..7cd995c --- /dev/null +++ b/Assets/ARDK/AR/_SessionFrameSharedLogic.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ef1e7de3fc194fa1b93225538bb87d18 +timeCreated: 1612503607 \ No newline at end of file diff --git a/Assets/ARDK/AR/_VideoStreamHelper.cs b/Assets/ARDK/AR/_VideoStreamHelper.cs new file mode 100644 index 0000000..c58e7a7 --- /dev/null +++ b/Assets/ARDK/AR/_VideoStreamHelper.cs @@ -0,0 +1,301 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Runtime.InteropServices; + +using Niantic.ARDK.AR.Image; +using Niantic.ARDK.Internals; + +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; + +using UnityEngine; + +namespace Niantic.ARDK.AR +{ + internal static unsafe class _VideoStreamHelper + { + private const int DEFAULT_ENCODING_IMAGE_WIDTH = 800; + private const int DEFAULT_ENCODING_IMAGE_HEIGHT = 600; + internal static Resolution _EncodingImageResolution { get; set; } = + new Resolution + { + width = DEFAULT_ENCODING_IMAGE_WIDTH, + height = DEFAULT_ENCODING_IMAGE_HEIGHT + }; + + internal static bool _SupportsCompressing() + { + #pragma warning disable 0429 + return (NativeAccess.Mode == NativeAccess.ModeType.Native) || + (Application.platform == RuntimePlatform.OSXEditor); + #pragma warning restore 0429 + } + + internal static bool _SupportsDecompressing() + { + return (Application.platform == RuntimePlatform.OSXEditor); + } + + internal static CompressedImage _CompressForVideo + ( + _SerializableImagePlanes planes, + ImageFormat imageFormat, + int compressionQuality + ) + { + if (!_SupportsCompressing()) + throw new Exception("This platform does not support compressing images"); + + var plane0 = planes[0]; + void* buffer; + UInt64 size; + + ROR_Encode_CameraFeed + ( + (UInt64)plane0.PixelWidth, + (UInt64)plane0.PixelHeight, + NativeArrayUnsafeUtility.GetUnsafePtr(plane0.Data), + NativeArrayUnsafeUtility.GetUnsafePtr(planes[1].Data), + &buffer, + &size, + (UInt64)compressionQuality, + (UInt32)imageFormat + ); + + var compressedImage = new CompressedImage(); + + compressedImage.CompressedData = new byte[size]; + Marshal.Copy(new IntPtr(buffer), compressedImage.CompressedData, 0, (int)size); + + return compressedImage; + } + + /// + /// Decompresses a compressed image into it's YUV NV12 plane representation. + /// + /// The compressed image to decompress. + internal static _SerializableImagePlanes _DecompressForVideo(CompressedImage compressedImage) + { + if (!_SupportsDecompressing()) + throw new Exception("This platform does not support decompressing images"); + + fixed (void* compressedPtr = compressedImage.CompressedData) + { + void* yPlane; + void* uvPlane; + UInt64 width; + UInt64 height; + ROR_Decode_CameraFeed + ( + compressedPtr, + (UInt64)compressedImage.CompressedData.LongLength, + &yPlane, + &uvPlane, + &width, + &height + ); + + var planes = new _SerializableImagePlane[2]; + + var yPlaneData = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray + (yPlane, (int)width * (int)height, Allocator.None); + + // UV has half width, but same data per row. + var uvPlaneData = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray + (uvPlane, ((int)width * (int)height) / 2, Allocator.None); +#if UNITY_EDITOR + AtomicSafetyHandle ySafetyHandle = AtomicSafetyHandle.Create(); + AtomicSafetyHandle uvSafetyHandle = AtomicSafetyHandle.Create(); + + NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref yPlaneData, ySafetyHandle); + NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref uvPlaneData, uvSafetyHandle); + + planes[0] = + new _SerializableImagePlane(yPlaneData, ySafetyHandle, (int)width, (int)height, (int)width, 1); + planes[1] = + new _SerializableImagePlane(uvPlaneData, uvSafetyHandle, (int)width / 2, (int)height / 2, (int)width, 2); +#else + planes[0] = + new _SerializableImagePlane(yPlaneData, (int)width, (int)height, (int)width, 1); + planes[1] = + new _SerializableImagePlane(uvPlaneData, (int)width / 2, (int)height / 2, (int)width, 2); +#endif + + return new _SerializableImagePlanes(planes); + } + } + + internal static CompressedImage _CompressForVideoWithScale + ( + _SerializableImagePlanes planes, + ImageFormat imageFormat, + int compressionQuality + ) + { + if (!_SupportsCompressing()) + throw new Exception("This platform does not support compressing images"); + + var plane0 = planes[0]; + void* buffer; + UInt64 size; + + ROR_Encode_Scale_CameraFeed + ( + (UInt64)plane0.PixelWidth, + (UInt64)plane0.PixelHeight, + NativeArrayUnsafeUtility.GetUnsafePtr(plane0.Data), + NativeArrayUnsafeUtility.GetUnsafePtr(planes[1].Data), + (UInt64)_EncodingImageResolution.width, + (UInt64)_EncodingImageResolution.height, + &buffer, + &size, + (UInt64)compressionQuality, + (UInt32)imageFormat + ); + + var compressedImage = new CompressedImage(); + + compressedImage.CompressedData = new byte[size]; + Marshal.Copy(new IntPtr(buffer), compressedImage.CompressedData, 0, (int)size); + + return compressedImage; + } + + internal static byte[] _CompressForDepthBuffer + ( + int width, + int height, + NativeArray depthBuf, + bool useJpegCompression, + int compressionQuality + ) + { + if (!_SupportsCompressing()) + throw new Exception("This platform does not support compressing images"); + + void* buffer; + UInt64 size; + + ROR_Encode_FloatBuffer + ( + (UInt64)width, + (UInt64)height, + (float*)NativeArrayUnsafeUtility.GetUnsafePtr(depthBuf), + &buffer, + &size, + useJpegCompression, + (UInt64)compressionQuality + ); + + var compressed = new byte[size]; + Marshal.Copy(new IntPtr(buffer), compressed, 0, (int)size); + + return compressed; + } + + internal static NativeArray _DecompressForDepthBuffer + ( + byte[] compressedDepthBuf, + bool useJpegCompression + ) + { + if (!_SupportsCompressing()) + throw new Exception("This platform does not support compressing images"); + + float* buffer; + UInt64 size; + + unsafe + { + fixed (byte* byteBuf = &compressedDepthBuf[0]) + { + ROR_Decode_FloatBuffer + ( + (void*)byteBuf, + (UInt64)compressedDepthBuf.Length, + &buffer, + &size, + useJpegCompression + ); + } + } + + var uncompressed = new NativeArray((int)size, Allocator.Persistent); + unsafe + { + for (var i=0; i<(int)size; i++) + { + uncompressed[i] = buffer[i]; + } + } + return uncompressed; + } + + + // This method only is supported when _SupportsCompressing is true. + [DllImport(_ARDKLibrary.libraryName)] + private static extern void ROR_Encode_CameraFeed + ( + UInt64 width, + UInt64 height, + void* yPlane, + void* uvPlane, + void** outBuffer, + UInt64* outSize, + UInt64 quality, + UInt32 imageFormat + ); + + // This method only is supported when _SupportsCompressing is false. + [DllImport(_ARDKLibrary.libraryName)] + public static extern void ROR_Decode_CameraFeed + ( + void* compressedData, + UInt64 compressedDataSize, + void** outYPlane, + void** outUVPlane, + UInt64* outWidth, + UInt64* outHeight + ); + + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void ROR_Encode_Scale_CameraFeed + ( + UInt64 width, + UInt64 height, + void* yPlane, + void* uvPlane, + UInt64 targetWidth, + UInt64 targetHeight, + void** outBuffer, + UInt64* outSize, + UInt64 quality, + UInt32 imageFormat + ); + + [DllImport(_ARDKLibrary.libraryName)] + public static extern void ROR_Encode_FloatBuffer + ( + UInt64 width, + UInt64 height, + float* inbuffer, + void** outBuffer, + UInt64* outSize, + bool useJpegCompression, + UInt64 quality + ); + + [DllImport(_ARDKLibrary.libraryName)] + public static extern void ROR_Decode_FloatBuffer + ( + void* compressedData, + UInt64 compressedDataSize, + float** outBuffer, + UInt64* outSize, + bool useJpegCompression + ); + + } +} diff --git a/Assets/ARDK/AR/_VideoStreamHelper.cs.meta b/Assets/ARDK/AR/_VideoStreamHelper.cs.meta new file mode 100644 index 0000000..0646d1b --- /dev/null +++ b/Assets/ARDK/AR/_VideoStreamHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8348a48d5427744bf88791c5c785d6ed +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/ARDK.asmdef b/Assets/ARDK/ARDK.asmdef new file mode 100644 index 0000000..e2e897d --- /dev/null +++ b/Assets/ARDK/ARDK.asmdef @@ -0,0 +1,34 @@ +{ + "name": "ARDK", + "rootNamespace": "", + "references": [ + "Unity.RenderPipelines.Universal.Runtime", + "Unity.InputSystem" + ], + "includePlatforms": [ + "Android", + "Editor", + "iOS", + "LinuxStandalone64", + "macOSStandalone", + "WindowsStandalone32", + "WindowsStandalone64" + ], + "excludePlatforms": [], + "allowUnsafeCode": true, + "overrideReferences": true, + "precompiledReferences": [ + "zxing.unity.dll", + "Niantic.Google.Protobuf.dll" + ], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [ + { + "name": "com.unity.render-pipelines.universal", + "expression": "7.0", + "define": "ARDK_HAS_URP" + } + ], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Assets/ARDK/ARDK.asmdef.meta b/Assets/ARDK/ARDK.asmdef.meta new file mode 100644 index 0000000..c6a211f --- /dev/null +++ b/Assets/ARDK/ARDK.asmdef.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: f3cc28278c88a4b43ae1ec99ea44ed56 +timeCreated: 1547164014 +licenseType: Pro +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Configuration.meta b/Assets/ARDK/Configuration.meta new file mode 100644 index 0000000..c903698 --- /dev/null +++ b/Assets/ARDK/Configuration.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1d0eaf04276e84930a703896fd9039a4 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Configuration/ArdkGlobalConfig.cs b/Assets/ARDK/Configuration/ArdkGlobalConfig.cs new file mode 100644 index 0000000..1f6dc55 --- /dev/null +++ b/Assets/ARDK/Configuration/ArdkGlobalConfig.cs @@ -0,0 +1,217 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Runtime.InteropServices; +using Niantic.ARDK.AR; +using Niantic.ARDK.Configuration.Internal; +using Niantic.ARDK.Networking; +using Niantic.ARDK.Utilities.Logging; + +namespace Niantic.ARDK.Configuration +{ + /// Global configuration class. + /// Allows developers to setup different configuration values during runtime. + /// This exists such that in a live production environment, you can obtain the configuration + /// settings remotely and set them before running the rest of the application. + public static class ArdkGlobalConfig + { + internal const string _DBOW_URL = "https://bowvocab.eng.nianticlabs.com/dbow_b50_l3.bin"; + internal const string _DEFAULT_AUTH_URL = "https://us-central1-ar-dev-portal-prod.cloudfunctions.net/auth_token"; + + static ArdkGlobalConfig() + { + var implementationType = _GetImplementationType(); + + switch (implementationType) + { + case _ImplementationType.Native: + _impl = new _NativeArdkConfig(); + ARLog._Debug("_NativeArdkConfigInternal"); + _Internal = new _NativeArdkConfigInternal(); + break; + + case _ImplementationType.Placeholder: + default: + _impl = new _PlaceholderArdkConfig(); + ARLog._Debug("_PlaceholderArdkConfigInternal"); + _Internal = new _PlaceholderArdkConfigInternal(); + break; + } + } + + private static _IArdkConfig _impl { get; } + + internal static _IArdkConfigInternal _Internal { get; } + + public static bool SetDbowUrl(string url) + { + return _impl.SetDbowUrl(url); + } + + public static string GetDbowUrl() + { + return _impl.GetDbowUrl(); + } + + public static string GetContextAwarenessUrl() + { + return _impl.GetContextAwarenessUrl(); + } + + public static bool SetContextAwarenessUrl(string url) + { + return _impl.SetContextAwarenessUrl(url); + } + + public static bool SetApiKey(string apiKey) + { + return _impl.SetApiKey(apiKey); + } + + public static string GetAuthenticationUrl() + { + return _impl.GetAuthenticationUrl(); + } + + /// Returns the clientId - a unique identifier generated for the user/device + /// in cases where a userId is not provided. + public static string GetClientId() + { + return _Internal.GetClientId(); + } + + public static bool SetAuthenticationUrl(string url) + { + return _impl.SetAuthenticationUrl(url); + } + + // returns the last good jwt token from API key validation + internal static string GetJwtToken() + { + if (_impl is _NativeArdkConfig nativeConfig) + { + var token = nativeConfig.GetJwtToken(); + + // if it is not populated, maybe no auth attempt has been made yet. make a blocking call here + // to attempt to get a token + if (string.IsNullOrEmpty(token)) + { + _VerifyApiKeyWithFeature("authentication", isAsync: false); + + token = nativeConfig.GetJwtToken(); + } + + return token; + } + + return null; + } + + /// Set the user id associated with the current user. + /// We strongly recommend generating and using User IDs. Accurate user information allows + /// Niantic to support you in maintaining data privacy best practices and allows you to + /// understand usage patterns of features among your users. + /// ARDK has no strict format or length requirements for User IDs, although the User ID string + /// must be a UTF8 string. We recommend avoiding using an ID that maps back directly to the + /// user. So, for example, don’t use email addresses, or login IDs. Instead, you should + /// generate a unique ID for each user. We recommend generating a GUID. + /// @param userId String containing the user id. + /// @returns True if set properly, false if not + public static bool SetUserIdOnLogin(string userId) + { + return _impl.SetUserIdOnLogin(userId); + } + + /// Clear the user id set by |SetUserIdOnLogin|. + /// @returns True if the user id is cleared properly, false if not + public static bool ClearUserIdOnLogout() + { + return _impl.SetUserIdOnLogin(""); + } + + internal static NetworkingErrorCode _VerifyApiKeyWithFeature(string feature, bool isAsync = true) + { + return _impl.VerifyApiKeyWithFeature(feature, isAsync: isAsync); + } + + private static bool IsM1Processor() + { + /* + * https://developer.apple.com/documentation/apple-silicon/about-the-rosetta-translation-environment + * From sysctl.proc_translated, + * Intel/iPhone => -1 + * Just M1 => 0 + * M1 with Rosetta => 1 + */ + int value; + var size = (IntPtr)4; + var param = "sysctl.proc_translated"; + var result = sysctlbyname(param, out value, ref size, IntPtr.Zero, (IntPtr)0); + + return result >= 0; + } + + private static _ImplementationType _GetImplementationType() + { + // Default to native unless you want to have more custom urls in which case, go for placeholder. + // Use Placeholder also if you are running windows or a M1 mac. + + // Note: We can create a _NativeFeaturePreloader without setting the AccessMode to Native, + // and then the preloader will download from default URLs instead of ones set in the ArdkGlobalConfig. + // There's currently no important use case where that's relevant though, so leaving the bug as known but unresolved. + + _ImplementationType typeToReturn = _ImplementationType.Native; + +#if (UNITY_IOS || UNITY_ANDROID) && !UNITY_EDITOR + // For IOS and Android, we always use the native implementation. + return typeToReturn; +#else // UNITY_EDITOR + var isNativeMode = NativeAccess.Mode == NativeAccess.ModeType.Native; + if(RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + // Android/Linux + if (!isNativeMode) + typeToReturn = _ImplementationType.Placeholder; + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + var isIntelMac = !IsM1Processor(); + var isArchitectureX64 = RuntimeInformation.OSArchitecture == Architecture.X64; + var isOSBigSurOrAbove = IsOperatingSystemBigSurAndAbove(); + var isTestingEnvironment = NativeAccess.Mode == NativeAccess.ModeType.Testing; + + if (!isArchitectureX64 || + !isIntelMac || + !isOSBigSurOrAbove || + isTestingEnvironment) + { + typeToReturn = _ImplementationType.Placeholder;; + } + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + typeToReturn = _ImplementationType.Placeholder; + } + return typeToReturn; +#endif + } + + private static bool IsOperatingSystemBigSurAndAbove() + { + // https://en.wikipedia.org/wiki/Darwin_%28operating_system%29#Release_history + // 20.0.0 Darwin is the first version of BigSur + Version minimumDarwinBigSurVersion = new Version(20, 0, 0); + + return Environment.OSVersion.Version >= minimumDarwinBigSurVersion; + } + + [DllImport("libSystem.dylib")] + private static extern int sysctlbyname ([MarshalAs(UnmanagedType.LPStr)]string name, out int int_val, ref IntPtr length, IntPtr newp, IntPtr newlen); + + private enum _ImplementationType + { + Native = 0, + Placeholder, + } + } +} diff --git a/Assets/ARDK/Configuration/ArdkGlobalConfig.cs.meta b/Assets/ARDK/Configuration/ArdkGlobalConfig.cs.meta new file mode 100644 index 0000000..50195f5 --- /dev/null +++ b/Assets/ARDK/Configuration/ArdkGlobalConfig.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 97f609ab1000d42f4a7f49602ec7c323 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Configuration/Authentication.meta b/Assets/ARDK/Configuration/Authentication.meta new file mode 100644 index 0000000..1454241 --- /dev/null +++ b/Assets/ARDK/Configuration/Authentication.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 412c4218cc4849caa21d72efdf0ea3b9 +timeCreated: 1619116341 \ No newline at end of file diff --git a/Assets/ARDK/Configuration/Authentication/ArdkAuthConfig.cs b/Assets/ARDK/Configuration/Authentication/ArdkAuthConfig.cs new file mode 100644 index 0000000..5316707 --- /dev/null +++ b/Assets/ARDK/Configuration/Authentication/ArdkAuthConfig.cs @@ -0,0 +1,23 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using UnityEngine; + +namespace Niantic.ARDK.Configuration.Authentication +{ + [CreateAssetMenu(fileName = "ArdkAuthConfig", menuName = "ARDK/ArdkAuthConfig", order = 1)] + public class ArdkAuthConfig : ScriptableObject + { + [SerializeField] + [Tooltip("Obtain an API key from your Lightship Account Dashboard and copy it in here.")] + private string _apiKey = ""; + + public string ApiKey { + get + { + return !string.IsNullOrEmpty(_overrideApiKey) ? _overrideApiKey : _apiKey; + } + } + + // Override API key for internal testing. You probably shouldn't touch this + private readonly string _overrideApiKey = string.Empty; + } +} diff --git a/Assets/ARDK/Configuration/Authentication/ArdkAuthConfig.cs.meta b/Assets/ARDK/Configuration/Authentication/ArdkAuthConfig.cs.meta new file mode 100644 index 0000000..ad27394 --- /dev/null +++ b/Assets/ARDK/Configuration/Authentication/ArdkAuthConfig.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3e818d7086440451e889be0511048aa6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Configuration/Internal.meta b/Assets/ARDK/Configuration/Internal.meta new file mode 100644 index 0000000..064f6e1 --- /dev/null +++ b/Assets/ARDK/Configuration/Internal.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 17cbbd9afd7d477881bac912d64b779d +timeCreated: 1648679246 \ No newline at end of file diff --git a/Assets/ARDK/Configuration/Internal/ArdkConfigInternalExtension.cs b/Assets/ARDK/Configuration/Internal/ArdkConfigInternalExtension.cs new file mode 100644 index 0000000..4102d4d --- /dev/null +++ b/Assets/ARDK/Configuration/Internal/ArdkConfigInternalExtension.cs @@ -0,0 +1,144 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; +using System.Collections.Generic; + +using Google.Protobuf; + +using Niantic.ARDK.AR.Protobuf; + +using UnityEditor; + +namespace Niantic.ARDK.Configuration.Internal +{ + internal static class ArdkConfigInternalExtension + { + public const string AuthorizationHeaderKey = "Authorization"; + public const string ClientIdHeaderKey = "x-ardk-clientid"; + public const string UserIdHeaderKey = "x-ardk-userid"; + + /// Get the common data envelope (client metadata protobuf) serialized into a Json string + public static string GetCommonDataEnvelopeAsJson(this _IArdkConfigInternal config) + { + // Cannot apply a null value to protobufs, so we need the null checks. + var proto = new ARCommonMetadata(); + PopulateProtoFields(proto, config); + var protoAsJson = JsonFormatter.Default.Format(proto); + + return protoAsJson; + } + + /// Get the common data envelope (client metadata protobuf) serialized into a Json string + /// Additionally populates the request_id field with a randomly generated UUID + public static string GetCommonDataEnvelopeWithRequestIdAsJson(this _IArdkConfigInternal config) + { + var proto = new ARCommonMetadata(); + PopulateProtoFields(proto, config); + proto.RequestId = Guid.NewGuid().ToString(); + var protoAsJson = JsonFormatter.Default.Format(proto); + + return protoAsJson; + } + + public static ARCommonMetadataStruct GetCommonDataEnvelopeWithRequestIdAsStruct(this _IArdkConfigInternal config) + { + var metadata = new ARCommonMetadataStruct + ( + config.GetApplicationId(), + config.GetPlatform(), + config.GetManufacturer(), + config.GetDeviceModel(), + config.GetUserId(), + config.GetClientId(), + config.GetArdkVersion(), + config.GetArdkAppInstanceId(), + Guid.NewGuid().ToString() + ); + + return metadata; + } + + public static Dictionary GetApiGatewayHeader(this _IArdkConfigInternal config) + { + Dictionary header = new Dictionary(); + + header.Add(AuthorizationHeaderKey, config.GetApiKey()); + header.Add(ClientIdHeaderKey, config.GetClientId()); + header.Add(UserIdHeaderKey, config.GetUserId()); + + return header; + } + + private static void PopulateProtoFields(ARCommonMetadata proto, _IArdkConfigInternal config) + { + var manufacturer = config.GetManufacturer(); + if (!string.IsNullOrEmpty(manufacturer)) + proto.Manufacturer = manufacturer; + + var appId = config.GetApplicationId(); + if (!string.IsNullOrEmpty(appId)) + proto.ApplicationId = appId; + + var appInstanceId = config.GetArdkAppInstanceId(); + if (!string.IsNullOrEmpty(appInstanceId)) + proto.ArdkAppInstanceId = appInstanceId; + + var ardkVersion = config.GetArdkVersion(); + if (!string.IsNullOrEmpty(ardkVersion)) + proto.ArdkVersion = ardkVersion; + + var clientId = config.GetClientId(); + if (!string.IsNullOrEmpty(clientId)) + proto.ClientId = clientId; + + var deviceModel = config.GetDeviceModel(); + if (!string.IsNullOrEmpty(deviceModel)) + proto.DeviceModel = deviceModel; + + var platform = config.GetPlatform(); + if (!string.IsNullOrEmpty(platform)) + proto.Platform = platform; + + var userId = config.GetUserId(); + if (!string.IsNullOrEmpty(userId)) + proto.UserId = userId; + } + } + + [Serializable] + public struct ARCommonMetadataStruct + { + public string application_id; + public string platform; + public string manufacturer; + public string device_model; + public string user_id; + public string client_id; + public string ardk_version; + public string ardk_app_instance_id; + public string request_id; + + public ARCommonMetadataStruct + ( + string applicationID, + string platform, + string manufacturer, + string deviceModel, + string userID, + string clientID, + string ardkVersion, + string ardkAppInstanceID, + string requestID + ) + { + application_id = applicationID; + this.platform = platform; + this.manufacturer = manufacturer; + device_model = deviceModel; + user_id = userID; + client_id = clientID; + ardk_version = ardkVersion; + ardk_app_instance_id = ardkAppInstanceID; + request_id = requestID; + } + } +} diff --git a/Assets/ARDK/Configuration/Internal/ArdkConfigInternalExtension.cs.meta b/Assets/ARDK/Configuration/Internal/ArdkConfigInternalExtension.cs.meta new file mode 100644 index 0000000..13e2d2b --- /dev/null +++ b/Assets/ARDK/Configuration/Internal/ArdkConfigInternalExtension.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 58861264cadd4df2866b091ce9c26887 +timeCreated: 1649979036 \ No newline at end of file diff --git a/Assets/ARDK/Configuration/Internal/_IArdkConfigInternal.cs b/Assets/ARDK/Configuration/Internal/_IArdkConfigInternal.cs new file mode 100644 index 0000000..4409813 --- /dev/null +++ b/Assets/ARDK/Configuration/Internal/_IArdkConfigInternal.cs @@ -0,0 +1,48 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; + +using Google.Protobuf; + +namespace Niantic.ARDK.Configuration.Internal +{ + internal interface _IArdkConfigInternal + { + // Bundle id (iOS) or package name (Android). For example, com.nianticlabs.ardkexamples + void SetApplicationId(string bundleId); + + // Guid encoded into a string. + // From C#, this is the hyphen-separated canonical representation + void SetArdkInstanceId(string instanceId); + + // Common metadata getters + + // Get the previously set application id + string GetApplicationId(); + + // Get the platform (OS) of the device. + // On iOS, this is formatted as "iOS ##.#" + // On Android, this is formatted as "Android ##" + string GetPlatform(); + + // Get the reported device manufacturer + string GetManufacturer(); + + // Get the reported device model + string GetDeviceModel(); + + // Get the native ardk version + string GetArdkVersion(); + + // Get the previously set user id (identity) + string GetUserId(); + + // Get the ARDK generated client id associated with this device + string GetClientId(); + + // Get the previously set ardk application instance id + string GetArdkAppInstanceId(); + + // Get the currently set Api Key, or an empty string if none has been set + string GetApiKey(); + } +} diff --git a/Assets/ARDK/Configuration/Internal/_IArdkConfigInternal.cs.meta b/Assets/ARDK/Configuration/Internal/_IArdkConfigInternal.cs.meta new file mode 100644 index 0000000..56a73d1 --- /dev/null +++ b/Assets/ARDK/Configuration/Internal/_IArdkConfigInternal.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 945e1a63c3f54e0cb21ea433a2502046 +timeCreated: 1648679428 \ No newline at end of file diff --git a/Assets/ARDK/Configuration/Internal/_NativeArdkConfigInternal.cs b/Assets/ARDK/Configuration/Internal/_NativeArdkConfigInternal.cs new file mode 100644 index 0000000..812ae40 --- /dev/null +++ b/Assets/ARDK/Configuration/Internal/_NativeArdkConfigInternal.cs @@ -0,0 +1,144 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; +using System.Runtime.InteropServices; +using System.Text; + +using Google.Protobuf; + +using Niantic.ARDK.Internals; +using Niantic.ARDK.Utilities.VersionUtilities; + +using UnityEngine; + +namespace Niantic.ARDK.Configuration.Internal +{ + internal sealed class _NativeArdkConfigInternal : + _IArdkConfigInternal + { + // Keep this synchronized with ardk_global_config_helper.hpp + private enum _ConfigDataField : uint + { + ApplicationId = 1, + Platform, + Manufacturer, + DeviceModel, + UserId, + ClientId, + DeveloperId, + ArdkVersion, + ArdkAppInstanceId + } + + public void SetApplicationId(string bundleId) + { + _NAR_ARDKGlobalConfigHelperInternal_SetDataField((uint)_ConfigDataField.ApplicationId, bundleId); + } + + public void SetArdkInstanceId(string instanceId) + { + _NAR_ARDKGlobalConfigHelperInternal_SetDataField((uint)_ConfigDataField.ArdkAppInstanceId, instanceId); + } + + public string GetApplicationId() + { + var stringBuilder = new StringBuilder(512); + _NAR_ARDKGlobalConfigHelper_GetDataField((uint)_ConfigDataField.ApplicationId, stringBuilder, (ulong)stringBuilder.Capacity); + + var result = stringBuilder.ToString(); + return result; + } + + public string GetPlatform() + { +#if UNITY_EDITOR + return Application.unityVersion; +#else + var stringBuilder = new StringBuilder(512); + _NAR_ARDKGlobalConfigHelper_GetDataField((uint)_ConfigDataField.Platform, stringBuilder, (ulong)stringBuilder.Capacity); + + var result = stringBuilder.ToString(); + return result; +#endif + } + + public string GetManufacturer() + { + var stringBuilder = new StringBuilder(512); + _NAR_ARDKGlobalConfigHelper_GetDataField((uint)_ConfigDataField.Manufacturer, stringBuilder, (ulong)stringBuilder.Capacity); + + var result = stringBuilder.ToString(); + return result; + } + + public string GetDeviceModel() + { +#if UNITY_EDITOR + return SystemInfo.operatingSystem; +#else + var stringBuilder = new StringBuilder(512); + _NAR_ARDKGlobalConfigHelper_GetDataField((uint)_ConfigDataField.DeviceModel, stringBuilder, (ulong)stringBuilder.Capacity); + + var result = stringBuilder.ToString(); + return result; +#endif + } + + public string GetArdkVersion() + { + return ARDKGlobalVersion.GetARDKVersion(); + } + + public string GetUserId() + { + var stringBuilder = new StringBuilder(512); + _NAR_ARDKGlobalConfigHelper_GetDataField((uint)_ConfigDataField.UserId, stringBuilder, (ulong)stringBuilder.Capacity); + + var result = stringBuilder.ToString(); + return result; + } + + public string GetClientId() + { + var stringBuilder = new StringBuilder(512); + _NAR_ARDKGlobalConfigHelper_GetDataField((uint)_ConfigDataField.ClientId, stringBuilder, (ulong)stringBuilder.Capacity); + + var result = stringBuilder.ToString(); + return result; + } + + public string GetArdkAppInstanceId() + { + var stringBuilder = new StringBuilder(512); + _NAR_ARDKGlobalConfigHelper_GetDataField((uint)_ConfigDataField.ArdkAppInstanceId, stringBuilder, (ulong)stringBuilder.Capacity); + + var result = stringBuilder.ToString(); + return result; + } + + public string GetApiKey() + { + var stringBuilder = new StringBuilder(512); + _NAR_ARDKGlobalConfigHelper_GetApiKey(stringBuilder, (ulong)stringBuilder.Capacity); + + var result = stringBuilder.ToString(); + return result; + } + + // Switch to using a protobuf to pass data back and forth when that is solidified. + // This is a bit fragile for now + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NAR_ARDKGlobalConfigHelperInternal_SetDataField(uint field, string data); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NAR_ARDKGlobalConfigHelper_GetApiKey(StringBuilder outKey, ulong maxKeySize); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NAR_ARDKGlobalConfigHelper_GetDataField + ( + uint field, + StringBuilder outData, + ulong maxDataSize + ); + } +} diff --git a/Assets/ARDK/Configuration/Internal/_NativeArdkConfigInternal.cs.meta b/Assets/ARDK/Configuration/Internal/_NativeArdkConfigInternal.cs.meta new file mode 100644 index 0000000..1868aa1 --- /dev/null +++ b/Assets/ARDK/Configuration/Internal/_NativeArdkConfigInternal.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 992696346fe2419ab27260eba9785899 +timeCreated: 1648682539 \ No newline at end of file diff --git a/Assets/ARDK/Configuration/Internal/_PlaceholderArdkConfigInternal.cs b/Assets/ARDK/Configuration/Internal/_PlaceholderArdkConfigInternal.cs new file mode 100644 index 0000000..4e1e37c --- /dev/null +++ b/Assets/ARDK/Configuration/Internal/_PlaceholderArdkConfigInternal.cs @@ -0,0 +1,72 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; +using System.Runtime.InteropServices; + +using Google.Protobuf; + +using Niantic.ARDK.AR.Protobuf; + +using UnityEngine; + +namespace Niantic.ARDK.Configuration.Internal +{ + internal sealed class _PlaceholderArdkConfigInternal : + _IArdkConfigInternal + { + private string _appId; + public void SetApplicationId(string bundleId) + { + _appId = bundleId; + } + public string GetApplicationId() + { + return _appId; + } + + private string _ardkInstanceId; + public void SetArdkInstanceId(string instanceId) + { + _ardkInstanceId = instanceId; + } + public string GetArdkAppInstanceId() + { + return _ardkInstanceId; + } + + public string GetPlatform() + { + return Application.unityVersion; + } + + public string GetManufacturer() + { + return null; + } + + public string GetDeviceModel() + { + return SystemInfo.operatingSystem; + } + + public string GetArdkVersion() + { + // This doesn't work without the native plugin :( + return null; + } + + public string GetUserId() + { + return _PlaceholderArdkConfig._userId; + } + + public string GetClientId() + { + return null; + } + + public string GetApiKey() + { + return _PlaceholderArdkConfig._apiKey; + } + } +} diff --git a/Assets/ARDK/Configuration/Internal/_PlaceholderArdkConfigInternal.cs.meta b/Assets/ARDK/Configuration/Internal/_PlaceholderArdkConfigInternal.cs.meta new file mode 100644 index 0000000..2f47f0f --- /dev/null +++ b/Assets/ARDK/Configuration/Internal/_PlaceholderArdkConfigInternal.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 0818d3dff1e2412384069d89f9c1c317 +timeCreated: 1648682573 \ No newline at end of file diff --git a/Assets/ARDK/Configuration/_IArdkConfig.cs b/Assets/ARDK/Configuration/_IArdkConfig.cs new file mode 100644 index 0000000..9a7c425 --- /dev/null +++ b/Assets/ARDK/Configuration/_IArdkConfig.cs @@ -0,0 +1,30 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Networking; + +namespace Niantic.ARDK.Configuration +{ + internal interface _IArdkConfig + { + /// Set the user id associated with the current user. + bool SetUserIdOnLogin(string userId); + + bool SetDbowUrl(string url); + + string GetDbowUrl(); + + string GetContextAwarenessUrl(); + + // This field needs to be able to take in string.Empty since it is required for a lower level to + // setup the correct url + bool SetContextAwarenessUrl(string url); + + bool SetApiKey(string key); + + string GetAuthenticationUrl(); + + bool SetAuthenticationUrl(string url); + + NetworkingErrorCode VerifyApiKeyWithFeature(string feature, bool isAsync = true); + } +} diff --git a/Assets/ARDK/Configuration/_IArdkConfig.cs.meta b/Assets/ARDK/Configuration/_IArdkConfig.cs.meta new file mode 100644 index 0000000..05cc5f3 --- /dev/null +++ b/Assets/ARDK/Configuration/_IArdkConfig.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: b1f0beaa7b824c08a2ed7483f10a1c09 +timeCreated: 1595438549 \ No newline at end of file diff --git a/Assets/ARDK/Configuration/_NativeArdkConfig.cs b/Assets/ARDK/Configuration/_NativeArdkConfig.cs new file mode 100644 index 0000000..6e8f7c4 --- /dev/null +++ b/Assets/ARDK/Configuration/_NativeArdkConfig.cs @@ -0,0 +1,180 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Runtime.InteropServices; +using System.Text; + +using Niantic.ARDK.AR; +using Niantic.ARDK.Internals; +using Niantic.ARDK.Networking; +using Niantic.ARDK.Utilities.Logging; + +namespace Niantic.ARDK.Configuration +{ + internal sealed class _NativeArdkConfig: + _IArdkConfig + { + private string _dbowUrl; + + public _NativeArdkConfig() + { + ARLog._Debug($"Using config: {nameof(_NativeArdkConfig)}"); + } + + public bool SetUserIdOnLogin(string userId) + { + if (!_NAR_ARDKGlobalConfigHelper_SetUserId(userId)) + { + ARLog._Warn("Failed to set the user Id"); + return false; + } + + return true; + } + + public bool SetDbowUrl(string url) + { + if (!_NAR_ARDKGlobalConfigHelper_SetDBoWUrl(url)) + { + ARLog._Warn("Failed to set the DBoW URL. It may have already been set."); + return false; + } + + // The C++ side actually changes the provided url to include some version information. + // So, here we just want to clear the cache. On a future get we will get the C++ provided + // value. + _dbowUrl = null; + return true; + } + + public string GetDbowUrl() + { + var result = _dbowUrl; + if (result != null) + return result; + + var stringBuilder = new StringBuilder(512); + _NAR_ARDKGlobalConfigHelper_GetDBoWUrl(stringBuilder, (ulong)stringBuilder.Capacity); + + result = stringBuilder.ToString(); + _dbowUrl = result; + return result; + } + + private string _contextAwarenessUrl; + public bool SetContextAwarenessUrl(string url) + { + if (!_NAR_ARDKGlobalConfigHelper_SetContextAwarenessUrl(url)) + { + ARLog._Warn("Failed to set the Context Awareness URL."); + return false; + } + + _contextAwarenessUrl = url; + return true; + } + public string GetContextAwarenessUrl() + { + /// For security reasons, we will not exposed the default URL + return _contextAwarenessUrl; + } + + public string GetAuthenticationUrl() + { + var stringBuilder = new StringBuilder(512); + _NAR_ARDKGlobalConfigHelper_GetAuthURL(stringBuilder, (ulong)stringBuilder.Capacity); + + var result = stringBuilder.ToString(); + return result; + } + + public bool SetAuthenticationUrl(string url) + { + if (!_NAR_ARDKGlobalConfigHelper_SetAuthURL(url)) + { + ARLog._Warn("Failed to set the Authentication URL."); + return false; + } + + return true; + } + + public NetworkingErrorCode VerifyApiKeyWithFeature(string feature, bool isAsync) + { + var error = + (NetworkingErrorCode) _NAR_ARDKGlobalConfigHelper_ValidateApiKeyWithFeature(feature, isAsync); + + return error; + } + + public bool SetApiKey(string key) + { + if (!_NAR_ARDKGlobalConfigHelper_SetApiKey(key)) + { + ARLog._Warn("Failed to set the API Key."); + return false; + } + + return true; + } + + // get the last good jwt token + internal string GetJwtToken() + { + var stringBuilder = new StringBuilder(512); + + _NAR_ARDKGlobalConfigHelper_GetJwtToken(stringBuilder, (ulong)stringBuilder.Capacity); + + var result = stringBuilder.ToString(); + return result; + } + + // Set DBoW URL + [DllImport(_ARDKLibrary.libraryName)] + private static extern bool _NAR_ARDKGlobalConfigHelper_SetDBoWUrl(string url); + + // Get DBoW URL + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NAR_ARDKGlobalConfigHelper_GetDBoWUrl + ( + StringBuilder outUrl, + ulong maxUrlSize + ); + + // Set ContextAwareness URL + [DllImport(_ARDKLibrary.libraryName)] + private static extern bool _NAR_ARDKGlobalConfigHelper_SetContextAwarenessUrl(string url); + + // Set Api Key + [DllImport(_ARDKLibrary.libraryName)] + private static extern bool _NAR_ARDKGlobalConfigHelper_SetApiKey(string key); + + // Set Auth URL + [DllImport(_ARDKLibrary.libraryName)] + private static extern bool _NAR_ARDKGlobalConfigHelper_SetAuthURL(string key); + + // Attempt to validate the specified feature, with a previously set Api Key. + [DllImport(_ARDKLibrary.libraryName)] + private static extern Int32 _NAR_ARDKGlobalConfigHelper_ValidateApiKeyWithFeature(string feature, bool isAsync); + + // Get Auth URL + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NAR_ARDKGlobalConfigHelper_GetAuthURL + ( + StringBuilder outKey, + ulong maxKeySize + ); + + // Get last known jwt token + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NAR_ARDKGlobalConfigHelper_GetJwtToken + ( + StringBuilder outToken, + ulong maxTokenSize + ); + + + [DllImport(_ARDKLibrary.libraryName)] + private static extern bool _NAR_ARDKGlobalConfigHelper_SetUserId(string userId); + } +} diff --git a/Assets/ARDK/Configuration/_NativeArdkConfig.cs.meta b/Assets/ARDK/Configuration/_NativeArdkConfig.cs.meta new file mode 100644 index 0000000..2ba2cb8 --- /dev/null +++ b/Assets/ARDK/Configuration/_NativeArdkConfig.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a83013520a3c74a3fadf048c47ba8d1c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Configuration/_PlaceholderARDKConfig.cs b/Assets/ARDK/Configuration/_PlaceholderARDKConfig.cs new file mode 100644 index 0000000..dca0c74 --- /dev/null +++ b/Assets/ARDK/Configuration/_PlaceholderARDKConfig.cs @@ -0,0 +1,88 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; + +using Niantic.ARDK.Networking; +using Niantic.ARDK.Utilities.Logging; + +namespace Niantic.ARDK.Configuration +{ + // + // Temporary ardk config class while proper support for other Operating Systems and architecture is being added. + // + internal sealed class _PlaceholderArdkConfig : + _IArdkConfig + { + private string _dbowUrl; + private string _contextAwarenessUrl; + private string _authenticationUrl; + internal static string _userId; + internal static string _apiKey; + + public _PlaceholderArdkConfig() + { + ARLog._Debug($"Using config: {nameof(_PlaceholderArdkConfig)}"); + } + + public bool SetUserIdOnLogin(string userId) + { + _userId = userId; + return true; + } + + public bool SetDbowUrl(string url) + { + if (string.IsNullOrWhiteSpace(url)) + throw new ArgumentException($"{nameof(url)} is null or whitespace."); + + _dbowUrl = url; + return true; + } + + public string GetDbowUrl() + { + return _dbowUrl ?? string.Empty; + } + + public string GetContextAwarenessUrl() + { + return _contextAwarenessUrl ?? string.Empty; + } + + public bool SetContextAwarenessUrl(string url) + { + if (url == null) + throw new ArgumentException($"{nameof(url)} is null."); + + _contextAwarenessUrl = url; + return true; + } + + public bool SetApiKey(string key) + { + if (string.IsNullOrWhiteSpace(key)) + throw new ArgumentException($"{nameof(key)} is null or whitespace."); + + _apiKey = key; + return true; + } + + public string GetAuthenticationUrl() + { + return _authenticationUrl ?? string.Empty; + } + + public bool SetAuthenticationUrl(string url) + { + if (string.IsNullOrWhiteSpace(url)) + throw new ArgumentException($"{nameof(url)} is null or whitespace."); + + _authenticationUrl = url; + return true; + } + + public NetworkingErrorCode VerifyApiKeyWithFeature(string feature, bool isAsync) + { + return NetworkingErrorCode.Ok; + } + } +} diff --git a/Assets/ARDK/Configuration/_PlaceholderARDKConfig.cs.meta b/Assets/ARDK/Configuration/_PlaceholderARDKConfig.cs.meta new file mode 100644 index 0000000..746ceff --- /dev/null +++ b/Assets/ARDK/Configuration/_PlaceholderARDKConfig.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4e9d6b2b6d94440db23f635aa65993ab +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Configuration/_SerializeableArdkConfig.cs b/Assets/ARDK/Configuration/_SerializeableArdkConfig.cs new file mode 100644 index 0000000..55b702d --- /dev/null +++ b/Assets/ARDK/Configuration/_SerializeableArdkConfig.cs @@ -0,0 +1,79 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.Networking; +using Niantic.ARDK.Utilities.Logging; + +namespace Niantic.ARDK.Configuration +{ + internal sealed class _SerializeableArdkConfig: + _IArdkConfig + { + private string _dbowUrl; + private string _apiKey; + private string _contextAwarenessUrl = ""; + private string _authenticationUrl = ""; + internal static string _userId; + + public _SerializeableArdkConfig() + { + ARLog._Debug($"Using config: {nameof(_SerializeableArdkConfig)}"); + } + + public bool SetUserIdOnLogin(string userId) + { + _userId = userId; + return true; + } + + public bool SetDbowUrl(string url) + { + _dbowUrl = url; + + return true; + } + + public string GetDbowUrl() + { + return _dbowUrl; + } + + public bool SetContextAwarenessUrl(string url) + { + _contextAwarenessUrl = url; + + return true; + } + + public string GetContextAwarenessUrl() + { + return _contextAwarenessUrl; + } + + public bool SetApiKey(string apiKey) + { + _apiKey = apiKey; + return true; + } + + public string GetAuthenticationUrl() + { + return _authenticationUrl; + } + + public bool SetAuthenticationUrl(string url) + { + _authenticationUrl = url; + return true; + } + + public NetworkingErrorCode VerifyApiKeyWithFeature(string feature, bool isAsync) + { + if (String.IsNullOrEmpty(_apiKey)) + return NetworkingErrorCode.ApiKeyNotSet; + + return NetworkingErrorCode.Ok; + } + } +} diff --git a/Assets/ARDK/Configuration/_SerializeableArdkConfig.cs.meta b/Assets/ARDK/Configuration/_SerializeableArdkConfig.cs.meta new file mode 100644 index 0000000..96e3957 --- /dev/null +++ b/Assets/ARDK/Configuration/_SerializeableArdkConfig.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a6b5cec44f9c347e9ba90161d7ce11e7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Editor.meta b/Assets/ARDK/Editor.meta new file mode 100644 index 0000000..f02ae84 --- /dev/null +++ b/Assets/ARDK/Editor.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 128ea4212cce647019f6ed55789e17d6 +folderAsset: yes +timeCreated: 1525206365 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Editor/ARDK-Editor.asmdef b/Assets/ARDK/Editor/ARDK-Editor.asmdef new file mode 100644 index 0000000..2ab7325 --- /dev/null +++ b/Assets/ARDK/Editor/ARDK-Editor.asmdef @@ -0,0 +1,10 @@ +{ + "name": "ARDK-Editor", + "references": [ + "ARDK" + ], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [] +} \ No newline at end of file diff --git a/Assets/ARDK/Editor/ARDK-Editor.asmdef.meta b/Assets/ARDK/Editor/ARDK-Editor.asmdef.meta new file mode 100644 index 0000000..a1b5bf4 --- /dev/null +++ b/Assets/ARDK/Editor/ARDK-Editor.asmdef.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: cb3367e27d5c740089bcadc6ab9be726 +timeCreated: 1547225527 +licenseType: Pro +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Editor/Extensions.meta b/Assets/ARDK/Editor/Extensions.meta new file mode 100644 index 0000000..639e3eb --- /dev/null +++ b/Assets/ARDK/Editor/Extensions.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7f46307b52a854a559014bf4e2f7952e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Editor/Extensions/Depth.meta b/Assets/ARDK/Editor/Extensions/Depth.meta new file mode 100644 index 0000000..0e71181 --- /dev/null +++ b/Assets/ARDK/Editor/Extensions/Depth.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 98d2084ce40bb473e8842f387c16ab39 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Editor/Extensions/Depth/ARDepthManagerInspector.cs b/Assets/ARDK/Editor/Extensions/Depth/ARDepthManagerInspector.cs new file mode 100644 index 0000000..62cbe3a --- /dev/null +++ b/Assets/ARDK/Editor/Extensions/Depth/ARDepthManagerInspector.cs @@ -0,0 +1,96 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using Niantic.ARDK.AR; +using Niantic.ARDK.Extensions; + +using UnityEditor; + +using UnityEngine; + +namespace ARDK.Editor.Extensions.Depth +{ + [CustomEditor(typeof(ARDepthManager))] + public class ARDepthManagerInspector + : UnityEditor.Editor + { + private SerializedProperty _occlusionModeProperty; + private SerializedProperty _textureFilterModeProperty; + private SerializedProperty _interpolationProperty; + private SerializedProperty _interpolationPreferenceProperty; + + + private void OnEnable() + { + _occlusionModeProperty = serializedObject.FindProperty("_occlusionMode"); + _textureFilterModeProperty = serializedObject.FindProperty("_textureFilterMode"); + _interpolationProperty = serializedObject.FindProperty("_interpolation"); + _interpolationPreferenceProperty = serializedObject.FindProperty("_interpolationPreference"); + } + + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + serializedObject.Update(); + + if (_occlusionModeProperty.enumValueIndex == (int)ARDepthManager.OcclusionMode.Auto || + _occlusionModeProperty.enumValueIndex == (int)ARDepthManager.OcclusionMode.DepthBuffer) + { + var useLinear = EditorGUILayout.Toggle + ( + "Prefer Smooth Edges", + _textureFilterModeProperty.enumValueIndex != (int)FilterMode.Point + ); + + _textureFilterModeProperty.enumValueIndex = + useLinear + ? (int)FilterMode.Bilinear + : (int)FilterMode.Point; + } + else + { + // Default to point filtering when using the screen space mesh technique + _textureFilterModeProperty.enumValueIndex = (int)FilterMode.Point; + } + + _interpolationProperty.enumValueIndex = (int)((InterpolationMode)EditorGUILayout.EnumPopup + ("Interpolation", (InterpolationMode)_interpolationProperty.enumValueIndex)); + + var interpolationAdapter = + ((ARDepthManager)target).GetComponent(); + + var isInterpolationAdapterPresentAndEnabled = + interpolationAdapter != null && interpolationAdapter.enabled; + + if (_interpolationProperty.enumValueIndex > 0) + { + if (!isInterpolationAdapterPresentAndEnabled) + { + _interpolationPreferenceProperty.floatValue = EditorGUILayout.Slider + ("Interpolation Preference", _interpolationPreferenceProperty.floatValue, 0.1f, 1.0f); + + EditorGUILayout.HelpBox + ( + "When in motion, the interpolation preference sets whether to align depth pixels " + + "with closer (0.1) or distant (1.0) pixels in the color image.", + MessageType.None + ); + } + else + EditorGUILayout.HelpBox("Using interpolation preference adapter.", MessageType.None); + } + + serializedObject.ApplyModifiedProperties(); + + var isRenderingManagerPresent = + ((ARDepthManager)target).GetComponent() != null; + if (!isRenderingManagerPresent) + { + EditorGUILayout.HelpBox + ( + "Missing AR Rendering Manager component. To inject depth information to the rendering pipeline, " + + "please make sure to add this AR Depth Manager to the renderer manually.", + MessageType.Warning + ); + } + } + } +} diff --git a/Assets/ARDK/Editor/Extensions/Depth/ARDepthManagerInspector.cs.meta b/Assets/ARDK/Editor/Extensions/Depth/ARDepthManagerInspector.cs.meta new file mode 100644 index 0000000..5b3a9fc --- /dev/null +++ b/Assets/ARDK/Editor/Extensions/Depth/ARDepthManagerInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 97066939ca15f46e787aecf4e0837101 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Editor/Extensions/Rendering.meta b/Assets/ARDK/Editor/Extensions/Rendering.meta new file mode 100644 index 0000000..f436d86 --- /dev/null +++ b/Assets/ARDK/Editor/Extensions/Rendering.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d807fd54853774447bcc6f66b4de3fa7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Editor/Extensions/Rendering/ARRenderingManagerInspector.cs b/Assets/ARDK/Editor/Extensions/Rendering/ARRenderingManagerInspector.cs new file mode 100644 index 0000000..a222574 --- /dev/null +++ b/Assets/ARDK/Editor/Extensions/Rendering/ARRenderingManagerInspector.cs @@ -0,0 +1,80 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using Niantic.ARDK.Extensions; + +using UnityEditor; + +using UnityEngine; + +namespace ARDK.Editor.Extensions.Rendering +{ + [CustomEditor(typeof(ARRenderingManager))] + public class ARRenderingManagerInspector + : UnityEditor.Editor + { + private enum Target + { + Camera = 0, + Texture = 1 + } + + private SerializedProperty _renderTargetIdProperty; + private SerializedProperty _cameraProperty; + private SerializedProperty _textureProperty; + private SerializedProperty _nearProperty; + private SerializedProperty _farProperty; + + private void OnEnable() + { + _renderTargetIdProperty = serializedObject.FindProperty("_renderTargetId"); + _cameraProperty = serializedObject.FindProperty("_camera"); + _textureProperty = serializedObject.FindProperty("_targetTexture"); + _nearProperty = serializedObject.FindProperty("_nearClippingPlane"); + _farProperty = serializedObject.FindProperty("_farClippingPlane"); + } + + public override void OnInspectorGUI() + { + serializedObject.Update(); + + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PrefixLabel("Render Target"); + _renderTargetIdProperty.intValue = (int)((Target)EditorGUILayout.EnumPopup + ((Target)_renderTargetIdProperty.intValue)); + EditorGUILayout.EndHorizontal(); + + if (_renderTargetIdProperty.intValue == 0) + { + _cameraProperty.objectReferenceValue = EditorGUILayout.ObjectField + ("Camera", _cameraProperty.objectReferenceValue, typeof(Camera), true); + + // Autofill camera + if (_cameraProperty.objectReferenceValue == null) + _cameraProperty.objectReferenceValue = ((ARRenderingManager)target).GetComponent(); + } + + _textureProperty.objectReferenceValue = _renderTargetIdProperty.intValue > 0 + ? EditorGUILayout.ObjectField + ("Texture", _textureProperty.objectReferenceValue, typeof(RenderTexture), false) + : null; + + // Only require clipping plane distances when targeting a render texture. + // Otherwise, these values are copied from the target camera. + if (_renderTargetIdProperty.intValue > 0) + { + _nearProperty.floatValue = EditorGUILayout.FloatField("Near Clip Plane", _nearProperty.floatValue); + _farProperty.floatValue = EditorGUILayout.FloatField("Far Clip Plane", _farProperty.floatValue); + } + + if (_renderTargetIdProperty.intValue > 0 && _textureProperty.objectReferenceValue == null) + { + EditorGUILayout.HelpBox + ( + "If the target texture is not set, it will be automatically created.", + MessageType.Info + ); + } + + serializedObject.ApplyModifiedProperties(); + } + } +} diff --git a/Assets/ARDK/Editor/Extensions/Rendering/ARRenderingManagerInspector.cs.meta b/Assets/ARDK/Editor/Extensions/Rendering/ARRenderingManagerInspector.cs.meta new file mode 100644 index 0000000..b10e37f --- /dev/null +++ b/Assets/ARDK/Editor/Extensions/Rendering/ARRenderingManagerInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: aab7167765a7d4857839524af1ed92f6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Editor/Extensions/Semantics.meta b/Assets/ARDK/Editor/Extensions/Semantics.meta new file mode 100644 index 0000000..cbf2787 --- /dev/null +++ b/Assets/ARDK/Editor/Extensions/Semantics.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5498e20ab0ba7441faf44f5e1847b4ad +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Editor/Extensions/Semantics/ARSemanticSegmentationManagerInspector.cs b/Assets/ARDK/Editor/Extensions/Semantics/ARSemanticSegmentationManagerInspector.cs new file mode 100644 index 0000000..f00ee53 --- /dev/null +++ b/Assets/ARDK/Editor/Extensions/Semantics/ARSemanticSegmentationManagerInspector.cs @@ -0,0 +1,101 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using Niantic.ARDK.AR; +using Niantic.ARDK.Extensions; + +using UnityEditor; + +using UnityEngine; + +namespace ARDK.Editor.Extensions.Semantics +{ + [CustomEditor(typeof(ARSemanticSegmentationManager))] + public class ARSemanticSegmentationManagerInspector + : UnityEditor.Editor + { + private SerializedProperty _interpolationProperty; + private SerializedProperty _interpolationPreferenceProperty; + private SerializedProperty _suppressionChannelsProperty; + + private void OnEnable() + { + _interpolationProperty = serializedObject.FindProperty("_interpolation"); + _interpolationPreferenceProperty = serializedObject.FindProperty("_interpolationPreference"); + _suppressionChannelsProperty = serializedObject.FindProperty("_depthSuppressionChannels"); + } + + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + serializedObject.Update(); + + _suppressionChannelsProperty.isExpanded = EditorGUILayout.Foldout + (_suppressionChannelsProperty.isExpanded, "Depth Suppression Channels"); + + if (_suppressionChannelsProperty.isExpanded) + { + EditorGUI.indentLevel++; + + _suppressionChannelsProperty.arraySize = EditorGUILayout.IntField + ( + "Number of Channels", + _suppressionChannelsProperty.arraySize + ); + + for (var i = 0; i < _suppressionChannelsProperty.arraySize; i++) + { + var item = _suppressionChannelsProperty.GetArrayElementAtIndex(i); + EditorGUILayout.PropertyField(item, new GUIContent($"Element {i}")); + } + + if (_suppressionChannelsProperty.arraySize > 0) + { + if (((ARSemanticSegmentationManager)target).GetComponent() == null) + EditorGUILayout.HelpBox("Please add an AR Depth Manager component to enable this feature.", MessageType.Error); + } + + EditorGUI.indentLevel--; + } + + _interpolationProperty.enumValueIndex = (int)((InterpolationMode)EditorGUILayout.EnumPopup + ("Interpolation", (InterpolationMode)_interpolationProperty.enumValueIndex)); + + var semanticsManager = (ARSemanticSegmentationManager)target; + var depthManager = semanticsManager.GetComponent(); + var isDepthManagerPresentAndEnabled = depthManager != null && depthManager.enabled; + + if (_interpolationProperty.enumValueIndex > 0) + { + if (!isDepthManagerPresentAndEnabled) + { + _interpolationPreferenceProperty.floatValue = EditorGUILayout.Slider + ("Interpolation Preference", _interpolationPreferenceProperty.floatValue, 0.1f, 1.0f); + + EditorGUILayout.HelpBox + ( + "When in motion, the interpolation preference sets whether to align semantic pixels " + + "with closer (0.1) or distant (1.0) pixels in the color image.", + MessageType.None + ); + } + else + { + EditorGUILayout.HelpBox + ("Interpolation preference is driven by AR Depth Manager.", MessageType.Info); + } + } + + serializedObject.ApplyModifiedProperties(); + + var isRenderingManagerPresent = semanticsManager.GetComponent() != null; + if (!isRenderingManagerPresent) + { + EditorGUILayout.HelpBox + ( + "Missing AR Rendering Manager component. To inject semantics information to the rendering pipeline, " + + "please make sure to add this AR Semantic Segmentation Manager to the renderer manually.", + MessageType.Warning + ); + } + } + } +} diff --git a/Assets/ARDK/Editor/Extensions/Semantics/ARSemanticSegmentationManagerInspector.cs.meta b/Assets/ARDK/Editor/Extensions/Semantics/ARSemanticSegmentationManagerInspector.cs.meta new file mode 100644 index 0000000..df91242 --- /dev/null +++ b/Assets/ARDK/Editor/Extensions/Semantics/ARSemanticSegmentationManagerInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 58e325d7fc00a493e927195c26f01564 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Editor/PostBuildProcess.cs b/Assets/ARDK/Editor/PostBuildProcess.cs new file mode 100644 index 0000000..6524b3b --- /dev/null +++ b/Assets/ARDK/Editor/PostBuildProcess.cs @@ -0,0 +1,81 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using UnityEngine; + +using UnityEditor; +using UnityEditor.Callbacks; + +using System.IO; +using System.Collections; +#if UNITY_IOS && UNITY_EDITOR_OSX +using UnityEditor.iOS.Xcode; + +public class PostBuildProcess: MonoBehaviour +{ + [PostProcessBuild] + public static void OnPostProcessBuild(BuildTarget buildTarget, string path) + { + if (buildTarget == BuildTarget.iOS) + BuildForiOS(path); + } + + private static void BuildForiOS(string path) + { + string projectPath = path + "/Unity-iPhone.xcodeproj/project.pbxproj"; + + PBXProject project = new PBXProject(); + var file = File.ReadAllText(projectPath); + project.ReadFromString(file); + +#if UNITY_2019_3_OR_NEWER + string appTarget = project.GetUnityMainTargetGuid(); +#else + string appTarget = project.TargetGuidByName("Unity-iPhone"); +#endif + + // TODO, have this be generated, we already do this with a lot of other + // properties anyway + project.SetBuildProperty(appTarget, "ENABLE_BITCODE", "NO"); + project.SetBuildProperty(project.ProjectGuid(), "ENABLE_BITCODE", "NO"); + + project.AddFrameworkToProject(appTarget, "ARKit.framework", false); + project.AddFrameworkToProject(appTarget, "Metal.framework", false); + project.AddFrameworkToProject(appTarget, "Vision.framework", false); + project.AddFrameworkToProject(appTarget, "CoreML.framework", false); + project.AddFrameworkToProject(appTarget, "CoreImage.framework", false); + + // https://issuetracker.unity3d.com/issues/ios-unityframework-with-3rd-party-plugins-triggers-watchdog-termination-after-launch +#if UNITY_2019_4_OR_NEWER + project.AddFrameworkToProject(project.GetUnityMainTargetGuid(), "UnityFramework.framework", false); +#endif + + // Not sure why unity likes to make a dependency with a framework called + // 'null.framework' but this works around that nonsense + +#if UNITY_2019_3_OR_NEWER + var unityTarget = project.GetUnityFrameworkTargetGuid(); +#else + var unityTarget = appTarget; +#endif + + if (project.ContainsFramework(unityTarget, "null.framework")) + project.RemoveFrameworkFromProject(unityTarget, "null.framework"); + + File.WriteAllText(projectPath, project.WriteToString()); + + // Get the plist + string plistPath = path + "/Info.plist"; + PlistDocument plist = new PlistDocument(); + plist.ReadFromString(File.ReadAllText(plistPath)); + + PlistElementDict rootDict = plist.root; + + // Set key and value for NSMotionUsageDescription. + rootDict.SetString("NSMotionUsageDescription", "Required for Augmented Reality"); + + // Write edited plist to file + File.WriteAllText(plistPath, plist.WriteToString()); + } +} + +#endif diff --git a/Assets/ARDK/Editor/PostBuildProcess.cs.meta b/Assets/ARDK/Editor/PostBuildProcess.cs.meta new file mode 100644 index 0000000..0df9e88 --- /dev/null +++ b/Assets/ARDK/Editor/PostBuildProcess.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: e2c5882305f294d9f922ddd68c0dfa19 +timeCreated: 1525206602 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Editor/VirtualStudio.meta b/Assets/ARDK/Editor/VirtualStudio.meta new file mode 100644 index 0000000..4f71c71 --- /dev/null +++ b/Assets/ARDK/Editor/VirtualStudio.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 8dd50dac01234bfda538d619a70dbd9e +timeCreated: 1643909901 \ No newline at end of file diff --git a/Assets/ARDK/Editor/VirtualStudio/VirtualStudioConfigurationEditor.cs b/Assets/ARDK/Editor/VirtualStudio/VirtualStudioConfigurationEditor.cs new file mode 100644 index 0000000..385ec8e --- /dev/null +++ b/Assets/ARDK/Editor/VirtualStudio/VirtualStudioConfigurationEditor.cs @@ -0,0 +1,167 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.Linq; +using System.Text; + +using Niantic.ARDK.VirtualStudio.AR; +using Niantic.ARDK.AR.Configuration; +using Niantic.ARDK.Networking; +using Niantic.ARDK.Utilities.Logging; +using Niantic.ARDK.VirtualStudio.AR.Mock; +using Niantic.ARDK.VirtualStudio.Networking; +using Niantic.ARDK.VirtualStudio.Networking.Mock; + +using UnityEditor; + +using UnityEngine; + +namespace Niantic.ARDK.VirtualStudio.Editor +{ + public sealed class VirtualStudioConfigurationEditor : EditorWindow + { + private const string VS_MODE_KEY = "ARDK_VirtualStudio_Mode"; + + private int _vsModeSelection; + private RuntimeEnvironment _selectedARInfoSource; + + [SerializeField] + private _RemoteConfigurationEditor _remoteConfigEditor; + + [SerializeField] + private _MockPlayConfigurationEditor _mockPlayConfigEditor; + + private static GUIStyle _headerStyle; + + internal static GUIStyle _HeaderStyle + { + get + { + if (_headerStyle == null) + { + _headerStyle = new GUIStyle(EditorStyles.boldLabel); + _headerStyle.fontSize = 18; + _headerStyle.fixedHeight = 36; + } + + return _headerStyle; + } + } + + private static GUIStyle _subHeadingStyle; + + internal static GUIStyle _SubHeadingStyle + { + get + { + if (_subHeadingStyle == null) + { + _subHeadingStyle = new GUIStyle(EditorStyles.boldLabel); + _subHeadingStyle.fontSize = 14; + _subHeadingStyle.fixedHeight = 28; + } + + return _subHeadingStyle; + } + } + + private static GUIStyle _lineBreakStyle; + internal static GUIStyle _LineBreakStyle + { + get + { + if (_lineBreakStyle == null) + { + _lineBreakStyle = new GUIStyle(EditorStyles.label); + _lineBreakStyle.wordWrap = false; + } + + return _lineBreakStyle; + } + } + + private Vector2 scrollPos = Vector2.zero; + + [MenuItem("Lightship/ARDK/Virtual Studio")] + public static void Init() + { + var window = GetWindow(false, "Virtual Studio"); + window.Show(); + + window._mockPlayConfigEditor = new _MockPlayConfigurationEditor(); + window._remoteConfigEditor = new _RemoteConfigurationEditor(); + + window.LoadPreferences(); + } + + private void LoadPreferences() + { + // Valid ARInfoSource values start at 1 + _vsModeSelection = PlayerPrefs.GetInt(VS_MODE_KEY, 0); + _selectedARInfoSource = (RuntimeEnvironment) _vsModeSelection + 1; + + _remoteConfigEditor.OnSelectionChange(_selectedARInfoSource == RuntimeEnvironment.Remote); + _mockPlayConfigEditor.OnSelectionChange(_selectedARInfoSource == RuntimeEnvironment.Mock); + + switch (_selectedARInfoSource) + { + case RuntimeEnvironment.Mock: + _mockPlayConfigEditor.LoadPreferences(); + break; + case RuntimeEnvironment.Remote: + _remoteConfigEditor.LoadPreferences(); + break; + } + } + + private void OnGUI() + { + using (var scrollView = new EditorGUILayout.ScrollViewScope(scrollPos)) + { + scrollPos = scrollView.scrollPosition; + + EditorGUILayout.Space(); + + EditorGUI.BeginDisabledGroup(Application.isPlaying); + DrawEnabledGUI(); + EditorGUI.EndDisabledGroup(); + + GUILayout.Space(50); + + switch (_selectedARInfoSource) + { + case RuntimeEnvironment.Remote: + EditorGUILayout.LabelField("Remote Connection", _HeaderStyle); + GUILayout.Space(10); + _remoteConfigEditor.DrawGUI(); + break; + + case RuntimeEnvironment.Mock: + EditorGUILayout.LabelField("Mock Play Configuration", _HeaderStyle); + GUILayout.Space(10); + _mockPlayConfigEditor.DrawGUI(); + break; + } + } + } + + private static readonly string[] _modeSelectionGridStrings = { "None", "Remote", "Mock" }; + private void DrawEnabledGUI() + { + var newModeSelection = + GUI.SelectionGrid + ( + new Rect(10, 20, 300, 20), + _vsModeSelection, + _modeSelectionGridStrings, + 3 + ); + + if (newModeSelection != _vsModeSelection) + { + _vsModeSelection = newModeSelection; + PlayerPrefs.SetInt(VS_MODE_KEY, _vsModeSelection); + LoadPreferences(); + } + } + } +} diff --git a/Assets/ARDK/Editor/VirtualStudio/VirtualStudioConfigurationEditor.cs.meta b/Assets/ARDK/Editor/VirtualStudio/VirtualStudioConfigurationEditor.cs.meta new file mode 100644 index 0000000..eb67096 --- /dev/null +++ b/Assets/ARDK/Editor/VirtualStudio/VirtualStudioConfigurationEditor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ca1c8a8ffe1a4c60aa88796935a935bd +timeCreated: 1613059161 \ No newline at end of file diff --git a/Assets/ARDK/Editor/VirtualStudio/_MockPlayConfigurationEditor.cs b/Assets/ARDK/Editor/VirtualStudio/_MockPlayConfigurationEditor.cs new file mode 100644 index 0000000..e86e4eb --- /dev/null +++ b/Assets/ARDK/Editor/VirtualStudio/_MockPlayConfigurationEditor.cs @@ -0,0 +1,506 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; +using System.Collections.Generic; +using System.Text; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.Networking; +using Niantic.ARDK.Networking; +using Niantic.ARDK.Networking.MultipeerNetworkingEventArgs; +using Niantic.ARDK.Utilities.Extensions; +using Niantic.ARDK.Utilities.Logging; +using Niantic.ARDK.VirtualStudio.AR; +using Niantic.ARDK.VirtualStudio.AR.Mock; +using Niantic.ARDK.VirtualStudio.Networking.Mock; + +using UnityEditor; +using UnityEngine; + +namespace Niantic.ARDK.VirtualStudio.Editor +{ + [Serializable] + internal sealed class _MockPlayConfigurationEditor + { + private const string PLAY_CONFIGURATION_KEY = "ARDK_PlayConfiguration"; + private const string INPUT_SESSION_ID_KEY = "ARDK_Input_Session_Identifier"; + private const string MOCK_SCENE_KEY = "ARDK_Mock_Scene_Guid"; + + [SerializeField] + private MockPlayConfiguration _playConfiguration; + + [SerializeField] + private string _inputSessionIdentifier; + + private byte[] _detectedSessionMetadata; + + [SerializeField] + private int _fps; + + [SerializeField] + private float _moveSpeed; + + [SerializeField] + private int _lookSpeed; + + [SerializeField] + private bool _scrollDirection; + + private Dictionary _foldoutStates = new Dictionary(); + + private bool _listeningForJoin; + private bool _isSelected; + + private string[] _mockSceneGuids; + private string[] _mockSceneNames; + private int _selectedMockSceneIndex; + private string _sceneGuid; + + public _MockPlayConfigurationEditor() + { + if (_playConfiguration != null) + _playConfiguration._Initialize(); + + EditorApplication.playModeStateChanged += OnEditorPlayModeStateChanged; + ListenForInitialize(); + _detectedSessionMetadata = null; + } + + ~_MockPlayConfigurationEditor () + { + EditorApplication.playModeStateChanged -= OnEditorPlayModeStateChanged; + MultipeerNetworkingFactory.NetworkingInitialized -= ListenForJoin; + _listeningForJoin = false; + _detectedSessionMetadata = null; + } + + private void OnEditorPlayModeStateChanged(PlayModeStateChange stateChange) + { + _detectedSessionMetadata = null; + + if (!_isSelected) + return; + + switch (stateChange) + { + case PlayModeStateChange.EnteredPlayMode: + ListenForInitialize(); + + var existingConfig = _VirtualStudioManager.Instance.PlayConfiguration; + if (existingConfig == null) + { + if (_playConfiguration != null) + _playConfiguration._Initialize(); + } + else + { + _playConfiguration = existingConfig; + } + + if (string.IsNullOrEmpty(_sceneGuid)) + break; + + var path = AssetDatabase.GUIDToAssetPath(_sceneGuid); + var scenePrefab = AssetDatabase.LoadMainAssetAtPath(path); + if (scenePrefab == null) + { + ARLog._Error("Could not load selected mock scene."); + break; + } + + GameObject.Instantiate(scenePrefab); + + break; + + case PlayModeStateChange.ExitingPlayMode: + MultipeerNetworkingFactory.NetworkingInitialized -= ListenForJoin; + _listeningForJoin = false; + break; + } + } + + private void ListenForInitialize() + { + if (!_listeningForJoin) + { + MultipeerNetworkingFactory.NetworkingInitialized += ListenForJoin; + _listeningForJoin = true; + } + } + + private void ListenForJoin(AnyMultipeerNetworkingInitializedArgs args) + { + args.Networking.Connected += + connectedArgs => + { + if (args.Networking is _MockMultipeerNetworking mockNetworking) + _detectedSessionMetadata = mockNetworking.JoinedSessionMetadata; + }; + } + + public void LoadPreferences() + { + var playConfigurationName = PlayerPrefs.GetString(PLAY_CONFIGURATION_KEY, null); + + if (!string.IsNullOrEmpty(playConfigurationName)) + _playConfiguration = GetPlayConfiguration(playConfigurationName); + + _inputSessionIdentifier = PlayerPrefs.GetString(INPUT_SESSION_ID_KEY, "ABC"); + + _fps = _MockCameraConfiguration.FPS; + _moveSpeed = _MockCameraConfiguration.MoveSpeed; + _lookSpeed = _MockCameraConfiguration.LookSpeed; + _scrollDirection = _MockCameraConfiguration.ScrollDirection == -1; + + _sceneGuid = PlayerPrefs.GetString(MOCK_SCENE_KEY, ""); + LoadMockScenes(); + } + + private void LoadMockScenes() + { + var mockPrefabs = + _AssetDatabaseExtension.FindPrefabsWithComponent + ( + new[] { "Assets" } + ); + + _mockSceneGuids = new string[mockPrefabs.Length]; + + _mockSceneNames = new string[mockPrefabs.Length + 1]; + _mockSceneNames[0] = "None"; + + for (var i = 0; i < mockPrefabs.Length; i++) + { + var guid = mockPrefabs[i].Guid; + _mockSceneGuids[i] = guid; + _mockSceneNames[i + 1] = mockPrefabs[i].Name; + + if (_sceneGuid == guid) + _selectedMockSceneIndex = i + 1; + } + } + + public void OnSelectionChange(bool isSelected) + { + _isSelected = isSelected; + } + + private static MockPlayConfiguration GetPlayConfiguration(string name) + { + var filter = string.Format("{0} t:MockPlayConfiguration", name); + var guids = AssetDatabase.FindAssets(filter); + + if (guids.Length == 0) + { + ARLog._WarnFormat("Could not load MockPlayConfiguration named: {0}", objs: name); + return null; + } + + var assetPath = AssetDatabase.GUIDToAssetPath(guids[0]); + var asset = AssetDatabase.LoadAssetAtPath(assetPath, typeof(MockPlayConfiguration)); + + ARLog._DebugFormat("Loaded MockPlayConfiguration named: {0}", objs: name); + return asset as MockPlayConfiguration; + } + + public void DrawGUI() + { + EditorGUILayout.LabelField("AR", VirtualStudioConfigurationEditor._HeaderStyle); + GUILayout.Space(10); + + DrawMockSceneGUI(); + + DrawCameraConfigurationGUI(); + + GUILayout.Space(20); + + EditorGUILayout.LabelField("Multiplayer", VirtualStudioConfigurationEditor._HeaderStyle); + GUILayout.Space(10); + + DrawPlayConfigurationSelector(); + DrawSessionMetadataGUI(); + + GUILayout.Space(20); + + DrawPlayers(); + } + + const char refreshArrow = '\u21bb'; + + private void DrawMockSceneGUI() + { + EditorGUILayout.BeginHorizontal(); + + var newMockSceneIndex = EditorGUILayout.Popup + ("Mock Scene: ", _selectedMockSceneIndex, _mockSceneNames); + + if (newMockSceneIndex != _selectedMockSceneIndex) + { + _selectedMockSceneIndex = newMockSceneIndex; + + var guid = _selectedMockSceneIndex >= 1 ? _mockSceneGuids[_selectedMockSceneIndex - 1] : ""; + _sceneGuid = guid; + PlayerPrefs.SetString(MOCK_SCENE_KEY, guid); + } + + if (GUILayout.Button(refreshArrow.ToString(), GUILayout.Width(50))) + { + LoadMockScenes(); + } + + EditorGUILayout.EndHorizontal(); + } + + private void DrawCameraConfigurationGUI() + { + EditorGUILayout.LabelField("Camera Controls", VirtualStudioConfigurationEditor._SubHeadingStyle); + GUILayout.Space(10); + + EditorGUI.BeginDisabledGroup(Application.isPlaying); + + var newFps = EditorGUILayout.IntField("FPS", _fps); + if (newFps != _fps) + { + _fps = newFps; + _MockCameraConfiguration.FPS = _fps; + } + + EditorGUI.EndDisabledGroup(); + + var newMovespeed = EditorGUILayout.Slider("Move Speed", _moveSpeed, 0.1f, 10f); + if (newMovespeed != _moveSpeed) + { + _moveSpeed = newMovespeed; + _MockCameraConfiguration.MoveSpeed = _moveSpeed; + } + + var newLookSpeed = EditorGUILayout.IntSlider("Look Speed", _lookSpeed, 1, 180); + if (newLookSpeed != _lookSpeed) + { + _lookSpeed = newLookSpeed; + _MockCameraConfiguration.LookSpeed = _lookSpeed; + } + + var newScrollDirection = EditorGUILayout.Toggle("Scroll Direction: Natural", _scrollDirection); + if (newScrollDirection != _scrollDirection) + { + _scrollDirection = newScrollDirection; + _MockCameraConfiguration.ScrollDirection = _scrollDirection ? -1 : 1; + } + } + + private void DrawPlayConfigurationSelector() + { + var newPlayConfiguration = + (MockPlayConfiguration) EditorGUILayout.ObjectField + ( + "Play Configuration", + _playConfiguration, + typeof(MockPlayConfiguration), + false + ); + + if (_playConfiguration != newPlayConfiguration) + { + _playConfiguration = newPlayConfiguration; + PlayerPrefs.SetString + ( + PLAY_CONFIGURATION_KEY, + _playConfiguration == null ? null : _playConfiguration.name + ); + } + } + + private void DrawPlayers() + { + EditorGUILayout.LabelField("Players", VirtualStudioConfigurationEditor._SubHeadingStyle); + GUILayout.Space(10); + DrawLocalPlayer(); + + EditorGUI.BeginDisabledGroup(_playConfiguration == null); + + EditorGUI.BeginDisabledGroup(!Application.isPlaying); + if (GUILayout.Button("Connect and Run All", GUILayout.Width(200))) + { + _playConfiguration.ConnectAllPlayersNetworkings(GetSessionMetadata()); + _playConfiguration.RunAllPlayersARSessions(); + } + + EditorGUI.EndDisabledGroup(); + + if (_playConfiguration != null) + { + foreach (var profile in _playConfiguration.Profiles) + { + DrawPlayerProfile(profile); + GUILayout.Space(10); + } + } + + EditorGUI.EndDisabledGroup(); + } + + private void DrawLocalPlayer() + { + var localName = _VirtualStudioManager.LOCAL_PLAYER_NAME; + if (!_foldoutStates.ContainsKey(localName)) + _foldoutStates.Add(localName, true); + + var showFoldout = EditorGUILayout.Foldout(_foldoutStates[localName], localName); + _foldoutStates[localName] = showFoldout; + + if (Application.isPlaying) + { + var localPlayer = _VirtualStudioManager.Instance.LocalPlayer; + if (localPlayer == null) + return; + + var arNetworking = localPlayer.ARNetworking; + if (arNetworking != null && arNetworking.Networking.IsConnected) + { + var currState = arNetworking.LocalPeerState; + var newState = (PeerState)EditorGUILayout.EnumPopup(currState); + if (newState != currState) + localPlayer.SetPeerState(newState); + } + } + } + + private void DrawPlayerProfile(MockArdkPlayerProfile profile) + { + var playerName = profile.PlayerName; + if (!_foldoutStates.ContainsKey(playerName)) + _foldoutStates.Add(playerName, true); + + var showFoldout = EditorGUILayout.Foldout(_foldoutStates[playerName], playerName); + _foldoutStates[playerName] = showFoldout; + + if (!showFoldout) + return; + + using (var horizontal = new EditorGUILayout.HorizontalScope(GUILayout.MaxWidth(300))) + { + GUILayout.Space(20); + + EditorGUI.BeginDisabledGroup(Application.isPlaying); + using (var col1 = new GUILayout.VerticalScope()) + { + var style = new GUILayoutOption[] + { + GUILayout.Width(150) + }; + + if (EditorGUILayout.ToggleLeft("Active", profile.IsActive, style) != profile.IsActive) + profile.IsActive = !profile.IsActive; + + if (EditorGUILayout.ToggleLeft("Create AR", profile.UsingAR, style) != profile.UsingAR) + profile.UsingAR = !profile.UsingAR; + + var newUsingNetworking = + EditorGUILayout.ToggleLeft("Create Network", profile.UsingNetwork, style); + + if (newUsingNetworking != profile.UsingNetwork) + profile.UsingNetwork = newUsingNetworking; + + var newUsingARNetworking = + EditorGUILayout.ToggleLeft("Create ARNetworking", profile.UsingARNetworking, style); + + if (newUsingARNetworking != profile.UsingARNetworking) + profile.UsingARNetworking = newUsingARNetworking; + } + EditorGUI.EndDisabledGroup(); + + GUILayout.Space(20); + + if (!Application.isPlaying || !_playConfiguration._Initialized || !profile.IsActive) + return; + + using (var col2 = new EditorGUILayout.VerticalScope()) + { + var style = new[] { GUILayout.Width(100) }; + + GUILayout.Space(18); + EditorGUI.BeginDisabledGroup(!profile.UsingAR); + + var player = profile.GetPlayer(); + + var arSession = player.ARSession; + if (arSession != null && arSession.State == ARSessionState.Running) + { + if (GUILayout.Button("Dispose", style)) + arSession.Dispose(); + } + else + { + if (GUILayout.Button("Run", style)) + arSession.Run(_playConfiguration.GetARConfiguration(profile)); + } + + EditorGUI.EndDisabledGroup(); + + GUILayout.Space(2); + EditorGUI.BeginDisabledGroup(!profile.UsingNetwork); + var networking = player.Networking; + if (networking != null && networking.IsConnected) + { + if (GUILayout.Button("Dispose", style)) + networking.Dispose(); + } + else + { + if (GUILayout.Button("Join", style)) + networking.Join(GetSessionMetadata()); + } + + GUILayout.Space(2); + var arNetworking = player.ARNetworking; + if (arNetworking != null && arNetworking.Networking.IsConnected) + { + var currState = arNetworking.LocalPeerState; + var newState = (PeerState)EditorGUILayout.EnumPopup(currState); + if (newState != currState) + player.SetPeerState(newState); + } + + EditorGUI.EndDisabledGroup(); + } + } + } + + private void DrawSessionMetadataGUI() + { + if (_detectedSessionMetadata != null && _detectedSessionMetadata.Length > 0) + { + EditorGUILayout.LabelField("Session Identifier", "Detected"); + return; + } + + var newInputSessionIdentifier = + EditorGUILayout.TextField("Session Identifier", _inputSessionIdentifier); + + if (_inputSessionIdentifier != newInputSessionIdentifier) + { + _inputSessionIdentifier = newInputSessionIdentifier; + PlayerPrefs.SetString(INPUT_SESSION_ID_KEY, _inputSessionIdentifier); + } + } + + private byte[] GetSessionMetadata() + { + if (_detectedSessionMetadata != null) + return _detectedSessionMetadata; + + if (string.IsNullOrWhiteSpace(_inputSessionIdentifier)) + { + ARLog._Error + ( + "Must enter a non-empty session identifier in the Virtual Studio window " + + "in order to join a networking session." + ); + + return null; + } + + return Encoding.UTF8.GetBytes(_inputSessionIdentifier); + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/Editor/VirtualStudio/_MockPlayConfigurationEditor.cs.meta b/Assets/ARDK/Editor/VirtualStudio/_MockPlayConfigurationEditor.cs.meta new file mode 100644 index 0000000..78a1a00 --- /dev/null +++ b/Assets/ARDK/Editor/VirtualStudio/_MockPlayConfigurationEditor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ea57fcf9c3034dd58d63da6a5f79a005 +timeCreated: 1586214378 \ No newline at end of file diff --git a/Assets/ARDK/Editor/VirtualStudio/_RemoteConfigurationEditor.cs b/Assets/ARDK/Editor/VirtualStudio/_RemoteConfigurationEditor.cs new file mode 100644 index 0000000..0a45745 --- /dev/null +++ b/Assets/ARDK/Editor/VirtualStudio/_RemoteConfigurationEditor.cs @@ -0,0 +1,188 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Text.RegularExpressions; + +using Niantic.ARDK.Utilities.Logging; +using Niantic.ARDK.VirtualStudio.Remote; + +using UnityEditor; +using UnityEngine; + +namespace Niantic.ARDK.VirtualStudio.Editor +{ + // UI for connecting to the ARDK Remote Feed app + [Serializable] + internal sealed class _RemoteConfigurationEditor + { + private const string REMOTE_METHOD = "ARDK_Connection_Method"; + private const string REMOTE_PIN = "ARDK_Pin"; + + [SerializeField] + private _RemoteConnection.ConnectionMethod _connectionMethod; + + [SerializeField] + private string _pin; + + [SerializeField] + private int _imageCompression; + + [SerializeField] + private int _imageFramerate; + + [SerializeField] + private int _awarenessFramerate; + + [SerializeField] + private int _featurePointFramerate; + + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + private static void Startup() + { + if (!_RemoteConnection.IsEnabled) + return; + + if (Application.isPlaying) + { + var pin = PlayerPrefs.GetString(REMOTE_PIN, "").ToUpper(); + var connectionMethod = + (_RemoteConnection.ConnectionMethod) PlayerPrefs.GetInt + ( + REMOTE_METHOD, + (int)_RemoteConnection.ConnectionMethod.Internet + ); + + var pinExistsAndIsValid = (!string.IsNullOrEmpty(pin) && Regex.IsMatch(pin, @"^[a-zA-Z]{6}$")); + if (pinExistsAndIsValid || connectionMethod == _RemoteConnection.ConnectionMethod.USB) + { + _RemoteConnection.InitIfNone(connectionMethod); + _RemoteConnection.Connect(pin); + } + else + { + ARLog._Release("Unable to create remote connection: No pin entered for Internet connection"); + } + } + } + + public void LoadPreferences() + { + _pin = PlayerPrefs.GetString(REMOTE_PIN, ""); + + _connectionMethod = + (_RemoteConnection.ConnectionMethod)PlayerPrefs.GetInt + ( + REMOTE_METHOD, + (int)_RemoteConnection.ConnectionMethod.Internet + ); + + _imageCompression = _RemoteBufferConfiguration.ImageCompression; + _imageFramerate = _RemoteBufferConfiguration.ImageFramerate; + _awarenessFramerate = _RemoteBufferConfiguration.AwarenessFramerate; + _featurePointFramerate = _RemoteBufferConfiguration.FeaturePointFramerate; + + } + + public void OnSelectionChange(bool isSelected) + { + _RemoteConnection.IsEnabled = isSelected; + } + + public void DrawGUI() + { + EditorGUI.BeginDisabledGroup(Application.isPlaying); + + var newConnectionMethod = + (_RemoteConnection.ConnectionMethod) EditorGUILayout.EnumPopup("Method:", _connectionMethod); + + if (newConnectionMethod != _connectionMethod) + { + _connectionMethod = newConnectionMethod; + PlayerPrefs.SetInt(REMOTE_METHOD, (int)_connectionMethod); + } + + var newPin = EditorGUILayout.TextField("PIN:", _pin); + var newPinIsValid = Regex.IsMatch(newPin, @"^[a-zA-Z]{6}$"); + if (!newPinIsValid) + { + EditorGUILayout.HelpBox("Pin must be a string of 6 letters ", MessageType.Warning); + } + + if (newPin != _pin) + { + _pin = newPin; + PlayerPrefs.SetString(REMOTE_PIN, newPin); + } + + var newImageCompression = EditorGUILayout.IntField("Image Compression:", _imageCompression); + if (newImageCompression != _imageCompression) + { + _imageCompression = newImageCompression; + _RemoteBufferConfiguration.ImageCompression = newImageCompression; + } + + var newImageFramerate = EditorGUILayout.IntField("Image Framerate:", _imageFramerate); + if (newImageFramerate != _imageFramerate) + { + _imageFramerate = newImageFramerate; + _RemoteBufferConfiguration.ImageFramerate = newImageFramerate; + } + + var newAwarenessFramerate = EditorGUILayout.IntField("Awareness Framerate:", _awarenessFramerate); + if (newAwarenessFramerate != _imageFramerate) + { + _awarenessFramerate = newAwarenessFramerate; + _RemoteBufferConfiguration.AwarenessFramerate = newAwarenessFramerate; + } + + var newFeaturePointFramerate = EditorGUILayout.IntField("Feature Point Framerate:", _featurePointFramerate); + if (newFeaturePointFramerate != _imageFramerate) + { + _featurePointFramerate = newFeaturePointFramerate; + _RemoteBufferConfiguration.FeaturePointFramerate = newFeaturePointFramerate; + } + + EditorGUI.EndDisabledGroup(); + + GUIStyle s = new GUIStyle(EditorStyles.largeLabel); + s.fontSize = 20; + s.fixedHeight = 30; + + if (Application.isPlaying) + { + EditorGUILayout.LabelField(_RemoteConnection.CurrentConnectionMethod.ToString()); + + if (!_RemoteConnection.IsReady) + { + if (_RemoteConnection.IsEnabled) + { + s.normal.textColor = Color.magenta; + EditorGUILayout.LabelField("Waiting for Remote Connection to be ready...", s); + } + else + { + s.normal.textColor = Color.gray; + EditorGUILayout.LabelField("Not active...", s); + } + } + else if (!_RemoteConnection.IsConnected) + { + s.normal.textColor = Color.blue; + EditorGUILayout.LabelField("Waiting for remote device to connect...", s); + } + else + { + s.normal.textColor = Color.green; + EditorGUILayout.LabelField("Connected!", s); + } + } + else + { + if (_RemoteConnection.IsEnabled) + EditorGUILayout.LabelField("Waiting for play mode...", s); + else + EditorGUILayout.LabelField("Not using remote...", s); + } + } + } +} diff --git a/Assets/ARDK/Editor/VirtualStudio/_RemoteConfigurationEditor.cs.meta b/Assets/ARDK/Editor/VirtualStudio/_RemoteConfigurationEditor.cs.meta new file mode 100644 index 0000000..cebc09d --- /dev/null +++ b/Assets/ARDK/Editor/VirtualStudio/_RemoteConfigurationEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8685c628e6e2244a1965d7ba58c8f9e7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions.meta b/Assets/ARDK/Extensions.meta new file mode 100644 index 0000000..d7bd894 --- /dev/null +++ b/Assets/ARDK/Extensions.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: f73b53aaf635c4d4fb291cbd3cf15823 +folderAsset: yes +timeCreated: 1525206343 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/ARCameraPositionHelper.cs b/Assets/ARDK/Extensions/ARCameraPositionHelper.cs new file mode 100644 index 0000000..43ec791 --- /dev/null +++ b/Assets/ARDK/Extensions/ARCameraPositionHelper.cs @@ -0,0 +1,73 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.ARSessionEventArgs; +using Niantic.ARDK.AR.Frame; +using Niantic.ARDK.Internals.EditorUtilities; +using Niantic.ARDK.Utilities; + +using UnityEngine; +using UnityEngine.Serialization; + +namespace Niantic.ARDK.Extensions +{ + /// A helper component to automatically position the scene rendering AR content and transform its output + public class ARCameraPositionHelper: MonoBehaviour + { + [FormerlySerializedAs("Camera")] + [SerializeField] + [_Autofill] + [Tooltip("The scene camera used to render AR content.")] + private Camera _camera; + + /// Returns a reference to the scene camera used to render AR content, if present. + public Camera Camera + { + get => _camera; + set => _camera = value; + } + + private IARSession _session; + + private void Start() + { + ARSessionFactory.SessionInitialized += _OnSessionInitialized; + } + + private void OnDestroy() + { + ARSessionFactory.SessionInitialized -= _OnSessionInitialized; + + var session = _session; + if (session != null) + session.FrameUpdated -= _FrameUpdated; + } + + private void _OnSessionInitialized(AnyARSessionInitializedArgs args) + { + var oldSession = _session; + if (oldSession != null) + oldSession.FrameUpdated -= _FrameUpdated; + + var newSession = args.Session; + _session = newSession; + newSession.FrameUpdated += _FrameUpdated; + } + + private void _FrameUpdated(FrameUpdatedArgs args) + { + var localCamera = Camera; + if (localCamera == null) + return; + + var session = _session; + if (session == null) + return; + + // Set the camera's position. + var worldTransform = args.Frame.Camera.GetViewMatrix(Screen.orientation).inverse; + localCamera.transform.position = worldTransform.ToPosition(); + localCamera.transform.rotation = worldTransform.ToRotation(); + } + } +} diff --git a/Assets/ARDK/Extensions/ARCameraPositionHelper.cs.meta b/Assets/ARDK/Extensions/ARCameraPositionHelper.cs.meta new file mode 100644 index 0000000..4ea846e --- /dev/null +++ b/Assets/ARDK/Extensions/ARCameraPositionHelper.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: da5ec3a3669946bf90ad10bf4ffab8a8 +timeCreated: 1548209138 \ No newline at end of file diff --git a/Assets/ARDK/Extensions/ARCameraPositionHistoryHelper.cs b/Assets/ARDK/Extensions/ARCameraPositionHistoryHelper.cs new file mode 100644 index 0000000..ba27d90 --- /dev/null +++ b/Assets/ARDK/Extensions/ARCameraPositionHistoryHelper.cs @@ -0,0 +1,113 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.ARSessionEventArgs; +using Niantic.ARDK.Utilities; + +using UnityEngine; + +#pragma warning disable 0649 + +namespace Niantic.ARDK.Extensions +{ + /// This helper can be placed in a scene to help visualize the position history of the camera as + /// a colored line, for debug purposes. The history is not truncated, and this helpers renders a + /// line going back to the beginning of the ARSession, or the last call to Clear, whichever + /// is most recent. + /// All data is expected to come from ARSession. + [RequireComponent(typeof(LineRenderer))] + public class ARCameraPositionHistoryHelper : MonoBehaviour + { + private IARSession _session; + + [SerializeField] + /// How often (in seconds) a point should be added to the position history. + private float _updateInterval = 0.5f; + private float _lastUpdate = 0; + private LineRenderer _lineRenderer; + + public bool Visible + { + get + { + return _lineRenderer && _lineRenderer.enabled; + } + set + { + if (_lineRenderer) + _lineRenderer.enabled = value; + } + } + + private void Awake() + { + _lineRenderer = GetComponent(); + } + + private void Start() + { + ARSessionFactory.SessionInitialized += OnSessionInitialized; + } + + private void OnDestroy() + { + ARSessionFactory.SessionInitialized -= OnSessionInitialized; + Teardown(); + } + + private void OnSessionInitialized(AnyARSessionInitializedArgs args) + { + if (_session != null) + return; + + _session = args.Session; + _session.Deinitialized += OnDeinitialized; + _session.FrameUpdated += OnFrameUpdated; + } + + private void OnDeinitialized(ARSessionDeinitializedArgs args) + { + Teardown(); + } + + private void Teardown() + { + if (_session != null) + { + _session.Deinitialized -= OnDeinitialized; + _session.FrameUpdated -= OnFrameUpdated; + _session = null; + } + + Clear(); + } + + private void OnFrameUpdated(FrameUpdatedArgs args) + { + if (args.Frame.Camera.TrackingState == TrackingState.Normal) + { + var worldTransform = args.Frame.Camera.GetViewMatrix(Screen.orientation).inverse; + UpdateCameraPosition(worldTransform.ToPosition()); + } + } + + private void UpdateCameraPosition(Vector3 position) + { + var now = Time.time; + if (now > _lastUpdate + _updateInterval) + { + _lineRenderer.positionCount = _lineRenderer.positionCount + 1; + _lineRenderer.SetPosition(_lineRenderer.positionCount - 1, position); + _lastUpdate = now; + } + } + + public void Clear() + { + _lastUpdate = 0; + _lineRenderer.positionCount = 0; + } + } +} + +#pragma warning restore 0649 diff --git a/Assets/ARDK/Extensions/ARCameraPositionHistoryHelper.cs.meta b/Assets/ARDK/Extensions/ARCameraPositionHistoryHelper.cs.meta new file mode 100644 index 0000000..dab4926 --- /dev/null +++ b/Assets/ARDK/Extensions/ARCameraPositionHistoryHelper.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 71dba49f71604f6f938280a32784fe29 +timeCreated: 1601424125 \ No newline at end of file diff --git a/Assets/ARDK/Extensions/ARConfigChanger.cs b/Assets/ARDK/Extensions/ARConfigChanger.cs new file mode 100644 index 0000000..b22b41e --- /dev/null +++ b/Assets/ARDK/Extensions/ARConfigChanger.cs @@ -0,0 +1,69 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.ARSessionEventArgs; +using Niantic.ARDK.AR.Configuration; + +namespace Niantic.ARDK.Extensions +{ + /// Extension for UnityLifecycleDriver that allows inheritors to modify the ARSession's + /// configuration, through the use of ARSessionChangesCollector. Configuration info + /// is asked for by the ARSession whenever it runs, and this class may additionally be used + /// to update the configuration after the session has already ran. + public abstract class ARConfigChanger: + UnityLifecycleDriver + { + private ARSessionChangesCollector _changesCollector; + + internal event Action _ConfigurationChanged; + + /// Inheritors should override this to modify session configuration settings based + /// on their script's needs. + /// + /// @note This is executed as a result of the ARSession being run, which may or may not be + /// triggered by a call to RaiseConfigurationChanged(). + public abstract void ApplyARConfigurationChange + ( + ARSessionChangesCollector.ARSessionRunProperties properties + ); + + /// Inheritors should call this function to alert the session that the configuration + /// has changed, and will result in ApplyARConfigurationChange() being called. + protected void RaiseConfigurationChanged() + { + _ConfigurationChanged?.Invoke(); + } + + protected override void InitializeImpl() + { + base.InitializeImpl(); + + ARSessionFactory.SessionInitialized += SetConfigChangesCollector; + } + + protected override void DeinitializeImpl() + { + base.DeinitializeImpl(); + + ARSessionFactory.SessionInitialized -= SetConfigChangesCollector; + _changesCollector?.Unregister(this); + } + + private void SetConfigChangesCollector(AnyARSessionInitializedArgs args) + { + var arSession = (_IARSession) args.Session; + _changesCollector = arSession.ARSessionChangesCollector; + _changesCollector.Register(this); + + // The session's ARSessionChangesCollector is destroyed when the session is disposed. + arSession.Deinitialized += + _ => + { + _changesCollector?.Unregister(this); + _changesCollector = null; + }; + } + } +} diff --git a/Assets/ARDK/Extensions/ARConfigChanger.cs.meta b/Assets/ARDK/Extensions/ARConfigChanger.cs.meta new file mode 100644 index 0000000..4460d6a --- /dev/null +++ b/Assets/ARDK/Extensions/ARConfigChanger.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 8ff7ab77533348d6850e87ca19d2923c +timeCreated: 1614022195 \ No newline at end of file diff --git a/Assets/ARDK/Extensions/ARFeaturePointRenderer.cs b/Assets/ARDK/Extensions/ARFeaturePointRenderer.cs new file mode 100644 index 0000000..be857d1 --- /dev/null +++ b/Assets/ARDK/Extensions/ARFeaturePointRenderer.cs @@ -0,0 +1,116 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.ARSessionEventArgs; +using Niantic.ARDK.Utilities.Extensions; + +using UnityEngine; + +namespace Niantic.ARDK.Extensions +{ + //! A helper script that visualizes feature points + /// + /// A sample class that can be added to a scene to visual feature points found in each frame. + /// On each frame, the list of current feature points will be queried, and the first + /// 'MaxFeaturePoints' amount will be instantiated into the scene. + /// + public class ARFeaturePointRenderer: + MonoBehaviour + { + /// The object used to represent the feature points. + public GameObject FeaturePointsObjectPf; + + public int MaxFeaturePoints; + + private Dictionary _existingPoints; + + private IARSession _session; + + private void Start() + { + _existingPoints = new Dictionary(MaxFeaturePoints); + + ARSessionFactory.SessionInitialized += _SessionInitialized; + } + + private void OnDestroy() + { + ARSessionFactory.SessionInitialized -= _SessionInitialized; + + var oldSession = _session; + if (oldSession != null) + oldSession.FrameUpdated -= _FrameUpdated; + + ClearObjects(); + } + + private void ClearObjects() + { + foreach (var point in _existingPoints) + Destroy(point.Value); + + _existingPoints.Clear(); + } + + private void _SessionInitialized(AnyARSessionInitializedArgs args) + { + var oldSession = _session; + if (oldSession != null) + oldSession.FrameUpdated -= _FrameUpdated; + + var newSession = args.Session; + _session = newSession; + newSession.FrameUpdated += _FrameUpdated; + newSession.Deinitialized += _OnDeinitialized; + } + + private void _OnDeinitialized(ARSessionDeinitializedArgs args) + { + ClearObjects(); + } + + private void _FrameUpdated(FrameUpdatedArgs args) + { + var frame = args.Frame; + if (frame.RawFeaturePoints == null) + return; + + var points = frame.RawFeaturePoints.Points; + + var i = 0; + for (; i < points.Count && i < MaxFeaturePoints; i++) + { + var fp = GetFeaturePoint(i); + fp.transform.position = points[i]; + fp.SetActive(true); + } + + for (; i < MaxFeaturePoints; i++) + { + var fp = _existingPoints.GetOrDefault(i); + + if (fp) + fp.SetActive(false); + } + } + + private GameObject GetFeaturePoint(int index) + { + return + _existingPoints.GetOrInsert + ( + index, + () => Instantiate + ( + FeaturePointsObjectPf, + Vector3.zero, + Quaternion.identity, + null + ) + ); + } + } +} diff --git a/Assets/ARDK/Extensions/ARFeaturePointRenderer.cs.meta b/Assets/ARDK/Extensions/ARFeaturePointRenderer.cs.meta new file mode 100644 index 0000000..a7b1668 --- /dev/null +++ b/Assets/ARDK/Extensions/ARFeaturePointRenderer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 62f551a2c0a84886a603ea0265849e9e +timeCreated: 1544654263 \ No newline at end of file diff --git a/Assets/ARDK/Extensions/ARImageDetectionManager.cs b/Assets/ARDK/Extensions/ARImageDetectionManager.cs new file mode 100644 index 0000000..0484739 --- /dev/null +++ b/Assets/ARDK/Extensions/ARImageDetectionManager.cs @@ -0,0 +1,127 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; +using System.Collections.Generic; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.Configuration; +using Niantic.ARDK.AR.ReferenceImage; +using Niantic.ARDK.Extensions; +using Niantic.ARDK.Utilities.Collections; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; +using UnityEngine.Serialization; + +namespace Niantic.ARDK.Extensions +{ + public class ARImageDetectionManager + : ARConfigChanger + { + [Serializable] + private struct InspectorImage + { + [Tooltip("The jpeg image as a bytes TextAsset. This should be a jpg file with a .bytes file extension.")] + [SerializeField] + public TextAsset _imageAsBytes; + + [Tooltip("A unique name for the image, which will be the IARReferenceImage's name.")] + [SerializeField] + public string _name; + + [Tooltip("The width of the physical image in meters.")] + [SerializeField] + public float _physicalWidth; + } + + [Tooltip("Images that will be added to the set of images to be detected when this is initialized.")] + [SerializeField] + private InspectorImage[] _images; + + /// Images that will be used in the ARSession's configuration when it is next run, if this + /// manager is enabled. + public IReadOnlyCollection RuntimeImages + { + get + { + return _readOnlyRuntimeImages; + } + } + + private readonly HashSet _runtimeImages = new HashSet(); + private ARDKReadOnlyCollection _readOnlyRuntimeImages; + + /// Adds an image to RuntimeImages and, if this manager is enabled, request that the session be + /// re-run. + public void AddImage(IARReferenceImage newImage) + { + _runtimeImages.Add(newImage); + if (AreFeaturesEnabled) + RaiseConfigurationChanged(); + } + + /// Removes an image from RuntimeImages and, if this manager is enabled, request that the + /// session be re-run. + public void RemoveImage(IARReferenceImage badImage) + { + if (_runtimeImages.Remove(badImage)) + { + if (AreFeaturesEnabled) + RaiseConfigurationChanged(); + } + else + { + ARLog._Warn("Attempting to remove an image that isn't there."); + } + } + + protected override void InitializeImpl() + { + base.InitializeImpl(); + + _readOnlyRuntimeImages = _runtimeImages.AsArdkReadOnly(); + + if (_images != null) + { + foreach (var image in _images) + { + AddImage + ( + ARReferenceImageFactory.Create + ( + image._name, + image._imageAsBytes.bytes, + image._imageAsBytes.bytes.Length, + image._physicalWidth + ) + ); + } + } + } + + protected override void EnableFeaturesImpl() + { + base.EnableFeaturesImpl(); + + RaiseConfigurationChanged(); + } + + protected override void DisableFeaturesImpl() + { + base.DisableFeaturesImpl(); + + RaiseConfigurationChanged(); + } + + public override void ApplyARConfigurationChange + ( + ARSessionChangesCollector.ARSessionRunProperties properties + ) + { + if (!AreFeaturesEnabled) + return; + + if (properties.ARConfiguration is IARWorldTrackingConfiguration worldConfig) + worldConfig.DetectionImages = _runtimeImages; + } + } +} diff --git a/Assets/ARDK/Extensions/ARImageDetectionManager.cs.meta b/Assets/ARDK/Extensions/ARImageDetectionManager.cs.meta new file mode 100644 index 0000000..0f6dadf --- /dev/null +++ b/Assets/ARDK/Extensions/ARImageDetectionManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c2117a09859c4796937159d2d7c3bd55 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/ARNetworkingManager.cs b/Assets/ARDK/Extensions/ARNetworkingManager.cs new file mode 100644 index 0000000..3ef125e --- /dev/null +++ b/Assets/ARDK/Extensions/ARNetworkingManager.cs @@ -0,0 +1,193 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.ARSessionEventArgs; +using Niantic.ARDK.AR.Configuration; +using Niantic.ARDK.AR.Networking; +using Niantic.ARDK.Networking; +using Niantic.ARDK.Networking.MultipeerNetworkingEventArgs; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; + +namespace Niantic.ARDK.Extensions +{ + /// A Unity component that manages an ARNetworking's lifetime. The session can either be started + /// automatically through Unity lifecycle events, or can be controlled programatically. + /// Any outstanding sessions are always cleaned up on destruction. Integrates with the + /// ARSessionManager and NetworkSessionManager to make sure all components are set up correctly. + /// + /// If ManageUsingUnityLifecycle is true: + /// OnAwake(): + /// An ARNetworking (and the component ARSession and MultipeerNetworking objects) + /// will be initialized + /// OnEnable(): + /// The ARSession will be run and the MultipeerNetworking will join a session + /// OnDisable(): + /// The ARSession will be paused and the MultipeerNetworking will leave the session + /// OnDestroy(): + /// The ARNetworking (and the component ARSession and MultipeerNetworking objects) + /// will be disposed + /// Else: + /// Call Initialize to: + /// Initialize an ARNetworking (and the component ARSession and MultipeerNetworking objects) + /// Call EnableFeatures to: + /// Run the ARSession and join the MultipeerNetworking + /// Call DisableFeatures to: + /// Pause the ARSession and leave the MultipeerNetworking session + /// Call Destroy to: + /// Dispose the ARNetworking (and the component ARSession and MultipeerNetworking objects) + /// + /// @note + /// Because the CapabilityChecker's method for checking device support is async, the above + /// events (i.e. initialization of ARNetworking) may not happen on the exact frame as + /// the method (OnAwake or Initialize) is invoked. + [RequireComponent(typeof(ARSessionManager))] + [RequireComponent(typeof(NetworkSessionManager))] + [DisallowMultipleComponent] + public class ARNetworkingManager: ARConfigChanger + { + private IARNetworking _arNetworking; + private ARSessionManager _arSessionManager; + private NetworkSessionManager _networkSessionManager; + + private bool _shouldBeRunning; + private bool _needToRecreate; + + /// @warning + /// Underlying object will change if this component is enabled (connected), disabled (disconnected), + /// and then connected again (reconnected). If subscribing to IARNetworking events, + /// you should listen to the ARNetworkingFactory.ARNetworkingInitialized event + /// and add your IARNetworking event subscriptions to the latest initialized networking object. + public IARNetworking ARNetworking + { + get { return _arNetworking; } + } + + public ARSessionManager ARSessionManager + { + get { return _arSessionManager; } + } + + public NetworkSessionManager NetworkSessionManager + { + get { return _networkSessionManager; } + } + + protected override bool _CanReinitialize + { + get { return true; } + } + + protected override void InitializeImpl() + { + base.InitializeImpl(); + + ARSessionFactory.SessionInitialized += CreateOnARSessionInitialized; + + _arSessionManager = GetComponent(); + _arSessionManager.Initialize(); + + _networkSessionManager = GetComponent(); + } + + private void CreateOnARSessionInitialized(AnyARSessionInitializedArgs args) + { + var arSession = args.Session; + + if (_arNetworking != null) + { + ARLog._Error("Failed to create an ARNetworking session because one already exists."); + return; + } + + _networkSessionManager._InitializeWithIdentifier(arSession.StageIdentifier); + _arNetworking = ARNetworkingFactory.Create(arSession, _networkSessionManager.Networking); + + ARLog._DebugFormat + ( + "Created {0} ARNetworking: {1}.", + false, + _arNetworking.ARSession.RuntimeEnvironment, + _arNetworking.ARSession.StageIdentifier + ); + + // Networking is recreated when it disconnects and reconnects, so the ARNetworking must + // be recreated too. + _arNetworking.Networking.Connected += _ => _needToRecreate = true; + + // Just in case the dev disposes the ARNetworking themselves instead of through this manager + _arNetworking.Deinitialized += + _ => + { + _arNetworking = null; + _needToRecreate = false; + }; + + if (_shouldBeRunning) + EnableSessionManagers(); + } + + protected override void DeinitializeImpl() + { + base.DeinitializeImpl(); + + ARSessionFactory.SessionInitialized -= CreateOnARSessionInitialized; + + if (_arNetworking == null) + return; + + _arNetworking.Dispose(); + _arNetworking = null; + + _arSessionManager.Deinitialize(); + _networkSessionManager.Deinitialize(); + } + + protected override void EnableFeaturesImpl() + { + // A networking, once left, is useless because it cannot be used to join/re-join a session. + // So _arNetworking.Networking will be destroyed by the NetworkSessionManager.DisableFeatures + // call, meaning if this component is enabled again, a new ARNetworking instance has to be + // created + if (_arNetworking != null && _needToRecreate) + { + _arNetworking.Dispose(); + _arNetworking = null; + } + + // Call base here so the backup Initialize call creates the new objects + base.EnableFeaturesImpl(); + + _shouldBeRunning = true; + + if (ARSessionManager.ARSession != null) + EnableSessionManagers(); + } + + protected override void DisableFeaturesImpl() + { + base.DisableFeaturesImpl(); + + _shouldBeRunning = false; + + _arSessionManager.DisableFeatures(); + _networkSessionManager.DisableFeatures(); + } + + private void EnableSessionManagers() + { + _arSessionManager.EnableFeatures(); + _networkSessionManager.EnableFeatures(); + } + + public override void ApplyARConfigurationChange + ( + ARSessionChangesCollector.ARSessionRunProperties properties + ) + { + if (properties.ARConfiguration is IARWorldTrackingConfiguration worldConfig) + worldConfig.IsSharedExperienceEnabled = AreFeaturesEnabled; + } + } +} diff --git a/Assets/ARDK/Extensions/ARNetworkingManager.cs.meta b/Assets/ARDK/Extensions/ARNetworkingManager.cs.meta new file mode 100644 index 0000000..1a0b851 --- /dev/null +++ b/Assets/ARDK/Extensions/ARNetworkingManager.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: bfedfd6646c94b53b5ae944005ee7e76 +timeCreated: 1617973801 \ No newline at end of file diff --git a/Assets/ARDK/Extensions/ARNetworkingStateVisualizer.cs b/Assets/ARDK/Extensions/ARNetworkingStateVisualizer.cs new file mode 100644 index 0000000..b5d4cc3 --- /dev/null +++ b/Assets/ARDK/Extensions/ARNetworkingStateVisualizer.cs @@ -0,0 +1,86 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.ComponentModel; + +using Niantic.ARDK.AR.Networking; +using Niantic.ARDK.AR.Networking.ARNetworkingEventArgs; + +using UnityEngine; +using UnityEngine.UI; + +namespace Niantic.ARDK.Extensions +{ + /// A helper class to quickly visualize the Peer state of the local peer via color. + /// - PeerState.Unknown = Gray + /// - PeerState.Synchronizing = Red + /// - PeerState.Synchronized = Green + public class ARNetworkingStateVisualizer: + MonoBehaviour + { + /// The image of whose color will be set depending upon the local peer's state. + public Image SyncIndicator; + + private IARNetworking _networking; + + private void Awake() + { + ARNetworkingFactory.ARNetworkingInitialized += _OnNetworkingInitialized; + } + + private void OnDestroy() + { + ARNetworkingFactory.ARNetworkingInitialized -= _OnNetworkingInitialized; + + var oldNetworking = _networking; + if (oldNetworking != null) + oldNetworking.PeerStateReceived -= _PeerStateReceived; + } + + private void _OnNetworkingInitialized(AnyARNetworkingInitializedArgs args) + { + var oldNetworking = _networking; + if (oldNetworking != null) + oldNetworking.PeerStateReceived -= _PeerStateReceived; + + _networking = args.ARNetworking; + _networking.PeerStateReceived += _PeerStateReceived; + } + + private void _PeerStateReceived(PeerStateReceivedArgs args) + { + var networking = _networking; + if (networking == null || !args.Peer.Equals(networking.Networking.Self)) + return; + + switch (args.State) + { + case PeerState.WaitingForLocalizationData: + SyncIndicator.color = Color.yellow; + break; + + case PeerState.Localizing: + SyncIndicator.color = Color.blue; + break; + + case PeerState.Stabilizing: + SyncIndicator.color = Color.magenta; + break; + + case PeerState.Failed: + SyncIndicator.color = Color.red; + break; + + case PeerState.Stable: + SyncIndicator.color = Color.green; + break; + + case PeerState.Unknown: + SyncIndicator.color = Color.gray; + break; + + default: + throw new InvalidEnumArgumentException("state", (int)args.State, typeof(PeerState)); + } + } + } +} diff --git a/Assets/ARDK/Extensions/ARNetworkingStateVisualizer.cs.meta b/Assets/ARDK/Extensions/ARNetworkingStateVisualizer.cs.meta new file mode 100644 index 0000000..e49136a --- /dev/null +++ b/Assets/ARDK/Extensions/ARNetworkingStateVisualizer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a771b00e6f244acf89eb7c306a18e75b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/ARRenderingManager.cs b/Assets/ARDK/Extensions/ARRenderingManager.cs new file mode 100644 index 0000000..a7317b8 --- /dev/null +++ b/Assets/ARDK/Extensions/ARRenderingManager.cs @@ -0,0 +1,376 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.ARSessionEventArgs; +using Niantic.ARDK.Internals.EditorUtilities; +using Niantic.ARDK.Rendering; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Logging; +using Niantic.ARDK.VirtualStudio.AR.Mock; + +using UnityEngine; + +namespace Niantic.ARDK.Extensions +{ + [DisallowMultipleComponent] + public class ARRenderingManager: + UnityLifecycleDriver + { + [SerializeField] + [HideInInspector] + private int _renderTargetId; + + [SerializeField] + [_Autofill] + private Camera _camera = null; + + [SerializeField] + private RenderTexture _targetTexture = null; + + /// Event for when the underlying frame renderer initialized. + public event ArdkEventHandler RendererInitialized; + + /// Prevents us from writing back the values _we_ set in case we accidentally set the + /// previous rates twice, + /// i.e. we set the application's previous frame rate and sleep timeout in + /// `SetupRendering`, next time it gets called (users can call Run multiple times) we then + /// set the frame rate and sleep _again_ except this time it's not truly the applications's, + /// it's the ones we set last time. + private SavedRenderingSettings _savedRenderingSettings; + + private IARSession _session; + private ARFrameRenderer _renderer; + + // Lazily allocated textures for snapshot images + private RenderTexture _gpuTexture; + private Texture2D _cpuTexture; + + // The texture properties can be accessed multiple times during a frame. + // We only render a new snapshot if the main render target has + // been updated. If not, we just return the most recent snapshot. + private bool _isGPUTextureDirty = true; + private bool _isCPUTextureDirty = true; + private bool _isFrameDirty = true; + private bool _releaseTargetTexture = false; + + public Camera Camera + { + get => _camera; + set + { + if (Initialized) + throw new InvalidOperationException("Cannot set this property after this component is initialized."); + + _camera = value; + } + } + + /// Returns the renderer instance used by this manager + public IARFrameRenderer Renderer + { + get => _renderer; + } + + /// A GPU texture of the latest AR background. + /// This texture is aligned (cropped, rotated) to the render target. + /// If the renderer is set to target a render texture, this property + /// will return that texture. Otherwise, a new render texture will be + /// allocated and updated lazily. It is guaranteed that no more than + /// a single Blit command will be issued during the same ARFrame. + public RenderTexture GPUTexture + { + get + { + if (_renderer == null) + return null; + + // If the renderer is already targeting a texture + if (_renderer.Target.IsTargetingTexture) + return _targetTexture; + + if (_isGPUTextureDirty) + { + // We only allow blitting a new frame, if the renderer is actively being + // updated to make sure its internal state reflects the latest ARFrame. + if (!isActiveAndEnabled) + return null; + + // Allocate the GPU texture if this is the first time the property is called + if (_gpuTexture == null) + { + _gpuTexture = new RenderTexture + ( + _renderer.Resolution.width, + _renderer.Resolution.height, + 24, + RenderTextureFormat.ARGB32, + RenderTextureReadWrite.Default + ); + + _gpuTexture.Create(); + } + + // Blit the current render state to the GPU texture + _renderer.BlitToTexture(ref _gpuTexture); + _isGPUTextureDirty = false; + } + + return _gpuTexture; + } + } + + /// A CPU texture of the latest AR background. + /// This texture is aligned (cropped, rotated) to the render + /// target. It is guaranteed that only a single ReadPixels call + /// will be performed during the same ARFrame. + /// @note This is a fairly expensive call. + public Texture2D CPUTexture + { + get + { + if (!_isCPUTextureDirty) + return _cpuTexture; + + // Acquire a new GPU snapshot + var source = GPUTexture; + if (source == null) + return null; + + // Push active target + var activeRenderTexture = RenderTexture.active; + RenderTexture.active = source; + + // Copy GPU snapshot to the CPU texture + if (_cpuTexture == null) + _cpuTexture = new Texture2D(source.width, source.height, TextureFormat.RGB24, true); + + _cpuTexture.ReadPixels(new Rect(0, 0, source.width, source.height), 0, 0); + _cpuTexture.Apply(false); + + // Pop active target + RenderTexture.active = activeRenderTexture; + _isCPUTextureDirty = false; + + return _cpuTexture; + } + } + + protected override void InitializeImpl() + { + base.InitializeImpl(); + + if (_camera != null) + { + +#if UNITY_EDITOR + // Attempt to disable the layer all mock objects are on so "real" objects aren't doubly rendered + // by the mock device camera and the scene camera. + _MockFrameBufferProvider.RemoveMockFromCullingMask(_camera); +#endif + } + + // Assign the current session + ARSessionFactory.SessionInitialized += ARSessionFactory_SessionInitialized; + } + + protected override void DeinitializeImpl() + { + base.DeinitializeImpl(); + ARSessionFactory.SessionInitialized -= ARSessionFactory_SessionInitialized; + + // Release the renderer + _renderer?.Dispose(); + _renderer = null; + + // Release textures + if (_gpuTexture != null) + Destroy(_gpuTexture); + + if (_cpuTexture != null) + Destroy(_cpuTexture); + + if (_releaseTargetTexture && _targetTexture != null) + Destroy(_targetTexture); + } + + protected override void EnableFeaturesImpl() + { + base.EnableFeaturesImpl(); + if (_renderer == null) + return; + + _renderer.Enable(); + AdjustFrameRate(_renderer); + } + + protected override void DisableFeaturesImpl() + { + base.DisableFeaturesImpl(); + _renderer?.Disable(); + + // Revert application settings + _savedRenderingSettings?.Apply(); + _savedRenderingSettings = null; + } + + // We drive rendering from late update, to + // wait for render state providers to update + private void LateUpdate() + { + if (!_isFrameDirty) + return; + + if (_renderer == null) + return; + + var frame = _session?.CurrentFrame; + if (frame == null) + return; + + _renderer.UpdateState(withFrame: frame); + + // Invalidate snapshot textures + _isCPUTextureDirty = true; + _isGPUTextureDirty = true; + + // Validate frame + _isFrameDirty = false; + } + + private void ARSessionFactory_SessionInitialized(AnyARSessionInitializedArgs args) + { + if (_session != null) + { + _session.FrameUpdated -= InvalidateFrame; + _session.Ran -= OnSessionRan; + _session.Paused -= OnSessionPaused; + _session.Deinitialized -= OnSessionDeinitialized; + } + + _session = args.Session; + _session.FrameUpdated += InvalidateFrame; + _session.Ran += OnSessionRan; + _session.Paused += OnSessionPaused; + _session.Deinitialized += OnSessionDeinitialized; + } + + private void OnSessionRan(ARSessionRanArgs args) + { + if (_renderer != null) + { + // If the renderer is already created, and this is enabled, enable the renderer. + if (AreFeaturesEnabled) + EnableFeaturesImpl(); + + return; + } + + // Create the renderer + _renderer = CreateRenderer(_session.RuntimeEnvironment); + if (_renderer == null) + { + ARLog._Error("Failed to create a renderer for the running platform."); + return; + } + + // Initialize the renderer + _renderer.Initialize(); + + // Propagate the initialization of the renderer + RendererInitialized?.Invoke(new FrameRenderedArgs(_renderer)); + + // Attach any render state providers + var stateProviders = GetComponents(); + foreach (var provider in stateProviders) + _renderer.AddFeatureProvider(provider); + + // Enable renderer + if (AreFeaturesEnabled) + { + _renderer.Enable(); + AdjustFrameRate(_renderer); + } + } + + private void AdjustFrameRate(IARFrameRenderer withRenderer) + { + // Push application settings + _savedRenderingSettings = new SavedRenderingSettings + ( + Application.targetFrameRate, + Screen.sleepTimeout, + QualitySettings.vSyncCount + ); + + // Configure target frame rate + QualitySettings.vSyncCount = 0; + Application.targetFrameRate = withRenderer.RecommendedFrameRate; + } + + private void InvalidateFrame(FrameUpdatedArgs arg) + { + _isFrameDirty = true; + } + + private ARFrameRenderer CreateRenderer(RuntimeEnvironment environment) + { + // Is the render target set to the screen backbuffer or to a texture? + var isOffscreen = _renderTargetId > 0; + + // In case the target texture was not provided + if (isOffscreen && _targetTexture == null) + { + // Allocate a new render texture + _targetTexture = new RenderTexture(Screen.width, Screen.height, depth: 24) + { + useMipMap = false, autoGenerateMips = false, filterMode = FilterMode.Point, anisoLevel = 0 + }; + + _targetTexture.Create(); + + // The rendering manager owns the target texture and needs to release it + _releaseTargetTexture = true; + } + + var renderTarget = isOffscreen + ? new RenderTarget(_targetTexture) + : new RenderTarget(_camera); + + ARFrameRenderer result; + var nearClippingPlane = _camera.nearClipPlane; + var farClippingPlane = _camera.farClipPlane; + if (((_IARSession) _session).IsPlayback) + result = ARFrameRendererFactory._CreatePlayback(renderTarget, nearClippingPlane, farClippingPlane); + else + result = ARFrameRendererFactory.Create(renderTarget, environment, nearClippingPlane, farClippingPlane); + + if (result != null) + result.IsOrientationLocked = false; + + return result; + } + + private void OnSessionPaused(ARSessionPausedArgs args) + { + DisableFeaturesImpl(); + } + + private void OnSessionDeinitialized(ARSessionDeinitializedArgs args) + { + if (_session != null) + { + _session.FrameUpdated -= InvalidateFrame; + _session.Ran -= OnSessionRan; + _session.Paused -= OnSessionPaused; + _session.Deinitialized -= OnSessionDeinitialized; + _session = null; + } + + _renderer?.Dispose(); + _renderer = null; + + DisableFeaturesImpl(); + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/Extensions/ARRenderingManager.cs.meta b/Assets/ARDK/Extensions/ARRenderingManager.cs.meta new file mode 100644 index 0000000..d087b14 --- /dev/null +++ b/Assets/ARDK/Extensions/ARRenderingManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5d39c0b3c66c44c10b52d0b316fcdea5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/ARSemanticSegmentationManager.cs b/Assets/ARDK/Extensions/ARSemanticSegmentationManager.cs new file mode 100644 index 0000000..ae3b8e3 --- /dev/null +++ b/Assets/ARDK/Extensions/ARSemanticSegmentationManager.cs @@ -0,0 +1,320 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Linq; + +using Niantic.ARDK.AR; + +using Niantic.ARDK.AR.Awareness; +using Niantic.ARDK.AR.Awareness.Semantics; +using Niantic.ARDK.AR.Configuration; +using Niantic.ARDK.Internals.EditorUtilities; +using Niantic.ARDK.Rendering; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; +using UnityEngine.Serialization; + +namespace Niantic.ARDK.Extensions +{ + [DisallowMultipleComponent] + public sealed class ARSemanticSegmentationManager: + ARRenderFeatureProvider + { + [FormerlySerializedAs("_arCamera")] + [SerializeField] + [_Autofill] + [Tooltip("The scene camera used to render AR content.")] + private Camera _camera; + + [SerializeField] + [Range(0, 60)] + [Tooltip("How many times the semantic segmentation routine should target running per second.")] + private uint _keyFrameFrequency = 20; + + [SerializeField] + [HideInInspector] + private string[] _depthSuppressionChannels; + + [SerializeField] + [HideInInspector] + [Tooltip("Whether the semantics buffer should synchronize with the camera pose.")] + private InterpolationMode _interpolation = InterpolationMode.Smooth; + + [SerializeField] + [HideInInspector] + [Range(0.0f, 1.0f)] + [Tooltip + ( + "Sets whether to align semantics pixels with closer (0.1) or distant (1.0) pixels " + + "in the color image (aka the back-projection distance)." + ) + ] + private float _interpolationPreference = AwarenessParameters.DefaultBackProjectionDistance; + + /// Returns a reference to the scene camera used to render AR content, if present. + public Camera Camera + { + get => _camera; + set + { + if (Initialized) + throw new InvalidOperationException("Cannot set this property after this component is initialized."); + + _camera = value; + } + } + + /// The value specifying the how many times the semantic segmentation routine + /// should target running per second. + public uint KeyFrameFrequency + { + get => _keyFrameFrequency; + set + { + if (value != _keyFrameFrequency) + { + _keyFrameFrequency = value; + RaiseConfigurationChanged(); + } + } + } + + /// The value specifying whether the semantics buffer should synchronize with the camera pose. + public InterpolationMode Interpolation + { + get => _interpolation; + set + { + if (Initialized) + throw new InvalidOperationException("Cannot set this property after this component is initialized."); + + _interpolation = value; + } + } + + /// The value specifying whether to align semantics pixels with closer (0.1) + /// or distant (1.0) pixels in the color image (aka the back-projection distance). + public float InterpolationPreference + { + get => _interpolationPreference; + set + { + if (Initialized) + throw new InvalidOperationException("Cannot set this property after this component is initialized."); + + if (value < 0f && value > 1f) + { + throw new ArgumentOutOfRangeException + ( + nameof(value), + "InterpolationPreference value must be between 0 and 1." + ); + } + + _interpolationPreference = value; + } + } + + /// Sets the depth suppression channels. If there is an existing set of channels, calling + /// this method will override them. + public void SetDepthSuppressionChannels(params string[] channelNames) + { + if (GetComponent() == null) + { + throw new InvalidOperationException + ( + "An AR Depth Manager component is required to add depth suppression channels." + ); + } + + if (_depthSuppressionChannels != null && _depthSuppressionChannels.Length > 0) + ARLog._Debug("Overriding existing depth suppression channels."); + + _depthSuppressionChannels = channelNames; + } + + /// Returns a reference to the depth suppression mask texture, if present. + /// If the suppression feature is disabled, this returns null. + public Texture DepthSuppressionTexture + { + get => _suppressionTexture; + } + + public ISemanticBufferProcessor SemanticBufferProcessor + { + get => _GetOrCreateProcessor(); + } + + /// Event for when the first semantics buffer is received. + public event ArdkEventHandler> SemanticBufferInitialized; + + /// Event for when the contents of the semantic buffer or its affine transform was updated. + public event + ArdkEventHandler> SemanticBufferUpdated; + + private SemanticBufferProcessor _semanticBufferProcessor; + private SemanticBufferProcessor _GetOrCreateProcessor() + { + if (_semanticBufferProcessor == null) + { + _semanticBufferProcessor = new SemanticBufferProcessor(_camera) + { + InterpolationMode = _interpolation, + InterpolationPreference = _interpolationPreference + }; + } + + return _semanticBufferProcessor; + } + + private Texture2D _suppressionTexture; + private int[] _suppressionChannelIndices; + + protected override void InitializeImpl() + { + if (_camera == null) + { + var warning = + "The Camera field was not set on the ARSemanticSegmentationManager before use. " + + "Will default to use Unity's Camera.main"; + + ARLog._Warn(warning); + _camera = Camera.main; + } + + _GetOrCreateProcessor(); + + base.InitializeImpl(); + } + + protected override void DeinitializeImpl() + { + // Release the semantics processor + _semanticBufferProcessor?.Dispose(); + + if (_suppressionTexture != null) + Destroy(_suppressionTexture); + + base.DeinitializeImpl(); + } + + protected override void EnableFeaturesImpl() + { + base.EnableFeaturesImpl(); + _semanticBufferProcessor.AwarenessStreamBegan += OnSemanticBufferInitialized; + _semanticBufferProcessor.AwarenessStreamUpdated += OnSemanticBufferUpdated; + } + + protected override void DisableFeaturesImpl() + { + base.DisableFeaturesImpl(); + + if (_suppressionTexture != null) + Destroy(_suppressionTexture); + + _semanticBufferProcessor.AwarenessStreamBegan -= OnSemanticBufferInitialized; + _semanticBufferProcessor.AwarenessStreamUpdated -= OnSemanticBufferUpdated; + } + + public override void ApplyARConfigurationChange + ( + ARSessionChangesCollector.ARSessionRunProperties properties + ) + { + if (properties.ARConfiguration is IARWorldTrackingConfiguration worldConfig) + { + worldConfig.IsSemanticSegmentationEnabled = AreFeaturesEnabled; + worldConfig.SemanticTargetFrameRate = _keyFrameFrequency; + } + } + + /// Invoked when this component is asked about the render features + /// it is may be responsible for. + /// @note: The implementation needs to include all features that is + /// possible to manipulate with this component. + protected override HashSet OnAcquireFeatureSet() + { + return new HashSet + { + FeatureBindings.DepthSuppression + }; + } + + /// Invoked when it is time to calculate the actual features + /// that this component currently manages. + protected override RenderFeatureConfiguration OnEvaluateConfiguration() + { + // If the semantics manager is not active, all features are disabled + if (!AreFeaturesEnabled) + return new RenderFeatureConfiguration(null, featuresDisabled: Features); + + var enabledFeatures = new List(); + + // Is depth suppression enabled? + if (_depthSuppressionChannels.Length > 0) + enabledFeatures.Add(FeatureBindings.DepthSuppression); + + // All other features are considered disabled + var disabledFeatures = new HashSet(Features); + disabledFeatures.ExceptWith(enabledFeatures); + return new RenderFeatureConfiguration(enabledFeatures, disabledFeatures); + } + + protected override void OnRenderTargetChanged(RenderTarget? target) + { + _GetOrCreateProcessor().AssignViewport(target ?? _camera); + } + + /// Called when it is time to copy the current render state to the main rendering material. + /// @param material Material used to render the frame. + public override void UpdateRenderState(Material material) + { + if (_depthSuppressionChannels.Length == 0) + return; + + material.SetTexture(PropertyBindings.DepthSuppressionMask, _suppressionTexture); + material.SetMatrix(PropertyBindings.SemanticsTransform, _semanticBufferProcessor.SamplerTransform); + } + + private void OnSemanticBufferInitialized(ContextAwarenessArgs args) + { + // Currently just a pass-through + SemanticBufferInitialized?.Invoke(args); + } + + private void OnSemanticBufferUpdated(ContextAwarenessStreamUpdatedArgs args) + { + // Avoid generating a suppression texture if suppression isn't enabled + if (_depthSuppressionChannels.Length != 0) + { + // Acquire the typed buffer + var semanticBuffer = args.Sender.AwarenessBuffer; + + // Determine whether we should update the list + // of channels that are used to suppress depth + var shouldUpdateSuppressionIndices = _suppressionChannelIndices == null || + _suppressionChannelIndices.Length != _depthSuppressionChannels.Length; + + // Update channel list + if (shouldUpdateSuppressionIndices) + _suppressionChannelIndices = _depthSuppressionChannels + .Select(channel => semanticBuffer.GetChannelIndex(channel)) + .ToArray(); + + // Update semantics on the GPU + if (args.IsKeyFrame) + semanticBuffer.CreateOrUpdateTextureARGB32 + ( + ref _suppressionTexture, + _suppressionChannelIndices + ); + } + + // Finally, let users know the manager has finished updating. + SemanticBufferUpdated?.Invoke(args); + } + } +} diff --git a/Assets/ARDK/Extensions/ARSemanticSegmentationManager.cs.meta b/Assets/ARDK/Extensions/ARSemanticSegmentationManager.cs.meta new file mode 100644 index 0000000..8bc1b8a --- /dev/null +++ b/Assets/ARDK/Extensions/ARSemanticSegmentationManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 37099b8137a84eb8b60b463785dd9d5e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/ARSessionListener.cs b/Assets/ARDK/Extensions/ARSessionListener.cs new file mode 100644 index 0000000..882566a --- /dev/null +++ b/Assets/ARDK/Extensions/ARSessionListener.cs @@ -0,0 +1,89 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.ARSessionEventArgs; + +namespace Niantic.ARDK.Extensions +{ + /// Helper for UnityLifecycleDrivers that need to listen to ARSession events. + /// Callbacks needed to be added to the IARSession instance whenever: + /// The IARSession is initialized + /// AND + /// The UnityLifecycleDriver is enabled + /// And the callbacks need to be removed whenever the UnityLifecycleDriver is disabled (but not + /// when the session is deinitialized, because that automatically cleans up the callbacks on its + /// own). + /// Implement ListenToSession to add callbacks to events, and StopListeningToSession to remove the + /// callbacks. Both guarantee that ARSession will be a valid non-null ARSession. + public abstract class ARSessionListener: + ARConfigChanger + { + /// The latest initialized ARSession, reset to null whenever the session is deinitialized. + /// It is not necessarily running. + protected IARSession ARSession { get; private set; } = null; + + /// Implement this method to add callbacks to ARSession. + protected abstract void ListenToSession(); + /// Implement this method to remove any callbacks added to ARSession in ListenToSession. + protected abstract void StopListeningToSession(); + /// Override this method with any cleanup behaviour for session deinitialization. + protected virtual void OnSessionDeinitialized() {} + + protected override void InitializeImpl() + { + ARSessionFactory.SessionInitialized += OnSessionInitialized; + + base.InitializeImpl(); + } + + protected override void DeinitializeImpl() + { + if (AreFeaturesEnabled && ARSession != null) + StopListeningToSession(); + + ARSessionFactory.SessionInitialized -= OnSessionInitialized; + if(ARSession != null) + ARSession.Deinitialized -= _OnSessionDeinitialized; + + ARSession = null; + + base.DeinitializeImpl(); + } + + private void OnSessionInitialized(AnyARSessionInitializedArgs args) + { + if (ARSession != null) + ARSession.Deinitialized -= _OnSessionDeinitialized; + + ARSession = args.Session; + ARSession.Deinitialized += _OnSessionDeinitialized; + + // ARSession is guaranteed to not be null, so check the other condition. + if (AreFeaturesEnabled) + ListenToSession(); + } + + private void _OnSessionDeinitialized(ARSessionDeinitializedArgs args) + { + OnSessionDeinitialized(); + ARSession = null; + } + + protected override void EnableFeaturesImpl() + { + base.EnableFeaturesImpl(); + + // Features are guaranteed to be enabled, so check the other condition. + if (ARSession != null) + ListenToSession(); + } + + protected override void DisableFeaturesImpl() + { + base.DisableFeaturesImpl(); + + if (ARSession != null) + StopListeningToSession(); + } + } +} diff --git a/Assets/ARDK/Extensions/ARSessionListener.cs.meta b/Assets/ARDK/Extensions/ARSessionListener.cs.meta new file mode 100644 index 0000000..e7d2a3e --- /dev/null +++ b/Assets/ARDK/Extensions/ARSessionListener.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e0a5764595054fdf8256299a190faa53 +timeCreated: 1617394563 \ No newline at end of file diff --git a/Assets/ARDK/Extensions/ARSessionManager.cs b/Assets/ARDK/Extensions/ARSessionManager.cs new file mode 100644 index 0000000..9cb94c2 --- /dev/null +++ b/Assets/ARDK/Extensions/ARSessionManager.cs @@ -0,0 +1,319 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.ARSessionEventArgs; +using Niantic.ARDK.AR.Configuration; +using Niantic.ARDK.Networking; +using Niantic.ARDK.Networking.MultipeerNetworkingEventArgs; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Logging; +using Niantic.ARDK.Utilities.Permissions; + +using UnityEngine; + +namespace Niantic.ARDK.Extensions +{ + /// A Unity component that manages an ARSession's lifetime. The session can either be created and + /// run automatically through Unity lifecycle events, or can be controlled programatically. + /// Any outstanding sessions are always cleaned up on destruction. Integrates with the + /// CapabilityChecker to ensure the device supports AR. + /// + /// If ManageUsingUnityLifecycle is true: + /// OnAwake(): an ARSession will be initialized + /// OnEnable(): the ARSession will be run + /// OnDisable(): the ARSession will be paused + /// OnDestroy(): the ARSession will be disposed + /// Else: + /// Call Initialize() to initialize an ARSession + /// Call EnableFeatures() to run the ARSession + /// Call DisableFeatures() to pause the ARSession + /// Call Deinitialize() to dispose the ARSession + /// + /// @note + /// Because the CapabilityChecker's method for checking device support and the + /// PermissionRequester's method to get camera permissions are async, the above + /// events (i.e. initialization of an ARSession) may not happen on the exact frame as + /// the method (OnAwake or Initialize) is invoked. + [DisallowMultipleComponent] + [RequireComponent(typeof(CapabilityChecker))] + public class ARSessionManager: + ARConfigChanger + { + /// If unspecified, will default to trying to create a live device session, then remote, then mock. + /// If specified, will throw an exception if the source is not supported on the current platform. + [SerializeField] + private RuntimeEnvironment RuntimeEnvironment = RuntimeEnvironment.Default; + + /// Options used to transition the AR session's current state if you re-run it. + [SerializeField] + private ARSessionRunOptions _runOptions = ARSessionRunOptions.None; + + /// Should be true if this ARSessionManager is being used in conjunction with an ARNetworkingManager. + [SerializeField] + private bool _useWithARNetworkingSession; + + [SerializeField] + [Tooltip("A boolean specifying whether or not camera images are analyzed to estimate scene lighting.")] + private bool _isLightEstimationEnabled = false; + + [SerializeField] + [Tooltip("A value specifying whether the camera should use autofocus or not when running.")] + private bool _isAutoFocusEnabled = false; + + [SerializeField] + [Tooltip("An iOS-only value specifying how the session maps the real-world device motion into a coordinate system.")] + private WorldAlignment _worldAlignment = WorldAlignment.Gravity; + + private CapabilityChecker _capabilityChecker; + + // Variables used to track when their Inspector-public counterparts are changed in OnValidate + private bool _prevLightEstimationEnabled; + private bool _prevAutoFocusEnabled; + private WorldAlignment _prevWorldAlignment; + + private Guid _stageIdentifier = default; + + private IARSession _arSession; + private bool _shouldBeRunning; + + public IARSession ARSession + { + get + { + return _arSession; + } + } + + public ARSessionRunOptions RunOptions + { + get => _runOptions; + set => _runOptions = value; + } + + public bool IsLightEstimationEnabled + { + get + { + return _isLightEstimationEnabled; + } + set + { + if (value != _isLightEstimationEnabled) + { + _isLightEstimationEnabled = value; + RaiseConfigurationChanged(); + } + } + } + + public bool IsAutoFocusEnabled + { + get + { + return _isAutoFocusEnabled; + } + set + { + if (value != _isAutoFocusEnabled) + { + _isAutoFocusEnabled = value; + RaiseConfigurationChanged(); + } + } + } + + public WorldAlignment WorldAlignment + { + get + { + return _worldAlignment; + } + set + { + if (value != _worldAlignment) + { + _worldAlignment = value; + RaiseConfigurationChanged(); + } + } + } + + protected override bool _CanReinitialize + { + get { return true; } + } + + protected override void InitializeImpl() + { + base.InitializeImpl(); + + _prevLightEstimationEnabled = _isLightEstimationEnabled; + _prevAutoFocusEnabled = _isAutoFocusEnabled; + _prevWorldAlignment = _worldAlignment; + + _capabilityChecker = GetComponent(); + + if (_useWithARNetworkingSession) + MultipeerNetworkingFactory.NetworkingInitialized += ListenForStage; + + if (_capabilityChecker.HasSucceeded) + ScheduleCreateAndRunOnNextUpdate(); + else + _capabilityChecker.Success.AddListener(ScheduleCreateAndRunOnNextUpdate); + } + + // Queues a callback to create an ARSession and, if AreFeaturesEnabled is true, run the session + // on the next Unity Update tick + private void ScheduleCreateAndRunOnNextUpdate() + { + ARSessionManager manager = this; + + _CallbackQueue.QueueCallback + ( + () => + { + if (manager != null && manager.Initialized) + { + manager.CreateAndRun(); + } + } + ); + } + + protected override void DeinitializeImpl() + { + base.DeinitializeImpl(); + + MultipeerNetworkingFactory.NetworkingInitialized -= ListenForStage; + + if (_arSession == null) + return; + + _arSession.Dispose(); + _arSession = null; + } + + private void ListenForStage(AnyMultipeerNetworkingInitializedArgs args) + { + // If multiple networkings were created, the ARSessionManager will use the stage of the + // most recently created networking. + _stageIdentifier = args.Networking.StageIdentifier; + } + + protected override void EnableFeaturesImpl() + { + base.EnableFeaturesImpl(); + + _shouldBeRunning = true; + + if (_arSession != null) + Run(); + } + + protected override void DisableFeaturesImpl() + { + base.DisableFeaturesImpl(); + + _shouldBeRunning = false; + _capabilityChecker.Success.RemoveListener(CreateAndRun); + + if (_arSession != null) + _arSession.Pause(); + } + + /// Creates the session so that Run can be called later. + /// This will only create the session if the capability checker was successful. + private void Create() + { + if (_arSession != null) + { + ARLog._Warn("Did not create an ARSession because one already exists."); + return; + } + + if (!_capabilityChecker.HasSucceeded) + { + ARLog._Error("Failed to initialize ARSession because capability check has not yet passed."); + return; + } + + if (_useWithARNetworkingSession && _stageIdentifier != Guid.Empty) + _arSession = ARSessionFactory.Create(RuntimeEnvironment, _stageIdentifier); + else + _arSession = ARSessionFactory.Create(RuntimeEnvironment); + + ARLog._DebugFormat("Created {0} ARSession: {1}.", false, _arSession.RuntimeEnvironment, _arSession.StageIdentifier); + + // Just in case the dev disposes the ARSession themselves instead of through this manager + _arSession.Deinitialized += (_) => _arSession = null; + } + + /// Runs an already created session with the provided options. + private void Run() + { + if (_arSession == null) + { + ARLog._Error("Failed to run ARSession because one was not initialized."); + return; + } + + // Config changes are made later in the ApplyARConfigurationChange method. That way, + // this class is able to intercept and alter the ARConfiguration every ARSession is run with, + // even if the session is run outside of this method. + var worldConfig = ARWorldTrackingConfigurationFactory.Create(); + _arSession.Run(worldConfig, _runOptions); + } + + /// Initializes and runs the session. + private void CreateAndRun() + { + Create(); + + if (_shouldBeRunning) + Run(); + } + + public override void ApplyARConfigurationChange + ( + ARSessionChangesCollector.ARSessionRunProperties properties + ) + { + var config = properties.ARConfiguration; + + config.IsLightEstimationEnabled = _isLightEstimationEnabled; + config.WorldAlignment = _worldAlignment; + properties.RunOptions |= _runOptions; + + if (config is IARWorldTrackingConfiguration worldConfig) + worldConfig.IsAutoFocusEnabled = _isAutoFocusEnabled; + } + + private void OnValidate() + { + var configChanged = false; + + if (_isLightEstimationEnabled != _prevLightEstimationEnabled) + { + _prevLightEstimationEnabled = _isLightEstimationEnabled; + configChanged = true; + } + + if (_isAutoFocusEnabled != _prevAutoFocusEnabled) + { + _prevAutoFocusEnabled = _isAutoFocusEnabled; + configChanged = true; + } + + if (_worldAlignment != _prevWorldAlignment) + { + _prevWorldAlignment = _worldAlignment; + configChanged = true; + } + + if (configChanged) + RaiseConfigurationChanged(); + } + } +} diff --git a/Assets/ARDK/Extensions/ARSessionManager.cs.meta b/Assets/ARDK/Extensions/ARSessionManager.cs.meta new file mode 100644 index 0000000..a22904f --- /dev/null +++ b/Assets/ARDK/Extensions/ARSessionManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 00203f13141804260a205f7c8a71dc60 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/ARVideoFeed.cs b/Assets/ARDK/Extensions/ARVideoFeed.cs new file mode 100644 index 0000000..8a36c80 --- /dev/null +++ b/Assets/ARDK/Extensions/ARVideoFeed.cs @@ -0,0 +1,201 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.ARSessionEventArgs; +using Niantic.ARDK.Rendering; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; + +using Object = UnityEngine.Object; + +namespace Niantic.ARDK.Extensions +{ + /// Event args for when the AR video feed gets updated. + public sealed class VideoFeedUpdatedArgs: IArdkEventArgs + { + /// The renderer. + public readonly IARFrameRenderer Renderer; + + /// The AR background image. + public readonly RenderTexture Texture; + + public VideoFeedUpdatedArgs(IARFrameRenderer renderer, RenderTexture texture) + { + Renderer = renderer; + Texture = texture; + } + } + + /// AR background video feed. It is designed to set up + /// continuous rendering to an offscreen texture. + public sealed class ARVideoFeed: IDisposable + { + private ARFrameRenderer _renderer; + private readonly IARSession _session; + + /// The renderer component used by this feed + public IARFrameRenderer Renderer + { + get => _renderer; + } + + /// The rendered AR background texture. + public RenderTexture GPUTexture { get; } + + /// Prevents us from writing back the values _we_ set in case we accidentally set the + /// previous rates twice, + /// i.e. we set the application's previous frame rate and sleep timeout in + /// `SetupRendering`, next time it gets called (users can call Run multiple times) we then + /// set the frame rate and sleep _again_ except this time it's not truly the applications's, + /// it's the ones we set last time. + private SavedRenderingSettings _savedRenderingSettings; + + /// Event for when the target texture had been updated. + public event ArdkEventHandler FeedUpdated; + + public ARVideoFeed + ( + IARSession session, + Resolution resolution, + float near = 0.1f, + float far = 100.0f, + bool canRotate = true, + bool autoDispose = true + ): this(session, resolution, false, near, far, canRotate, autoDispose) + { + + } + + internal ARVideoFeed + ( + IARSession session, + Resolution resolution, + bool isPlayback, + float near = 0.1f, + float far = 100.0f, + bool canRotate = true, + bool autoDispose = true + ) + { + // Allocate the GPU texture + GPUTexture = new RenderTexture + ( + resolution.width, + resolution.height, + 24, + RenderTextureFormat.ARGB32 + ); + + // Set up the renderer + _renderer = CreateRenderer + ( + GPUTexture, + session.RuntimeEnvironment, + near, + far, + !canRotate, + isPlayback + ); + + if (_renderer == null) + { + ARLog._Error("Failed to create a renderer for the running platform."); + return; + } + + _renderer.Initialize(); + + // Rendering is tied to whether the session is running + _session = session; + _session.Ran += Session_Ran; + _session.Paused += Session_Paused; + + if (autoDispose) + _session.Deinitialized += args => Dispose(); + } + + private void UpdateLoop_OnLateTick() + { + _renderer.UpdateState(_session.CurrentFrame); + } + + private void Session_Ran(ARSessionRanArgs args) + { + // Push application settings + _savedRenderingSettings = new SavedRenderingSettings + ( + Application.targetFrameRate, + Screen.sleepTimeout, + QualitySettings.vSyncCount + ); + + // Configure target frame rate + QualitySettings.vSyncCount = 0; + Application.targetFrameRate = _renderer.RecommendedFrameRate; + + _renderer.Enable(); + _renderer.FrameRendered += OnFrameRendered; + _UpdateLoop.LateTick += UpdateLoop_OnLateTick; + } + + private void Session_Paused(ARSessionPausedArgs args) + { + // Revert application settings + _savedRenderingSettings?.Apply(); + _savedRenderingSettings = null; + + _renderer.Disable(); + _renderer.FrameRendered -= OnFrameRendered; + _UpdateLoop.LateTick -= UpdateLoop_OnLateTick; + } + + private void OnFrameRendered(FrameRenderedArgs args) + { + var arguments = new VideoFeedUpdatedArgs(args.Renderer, GPUTexture); + FeedUpdated?.Invoke(arguments); + } + + private static ARFrameRenderer CreateRenderer + ( + RenderTarget target, + RuntimeEnvironment env, + float near, + float far, + bool lockOrientation, + bool isPlayback + ) + { + ARFrameRenderer result; + if (isPlayback) + result = ARFrameRendererFactory._CreatePlayback(target, near, far); + else + result = ARFrameRendererFactory.Create(target, env, near, far); + + result.IsOrientationLocked = lockOrientation; + return result; + } + + public void Dispose() + { + // Remove renderer + if (_renderer.IsEnabled) + _UpdateLoop.LateTick -= UpdateLoop_OnLateTick; + + _renderer.Dispose(); + _renderer = null; + + // Remove session + if (_session != null) + { + _session.Ran -= Session_Ran; + _session.Paused -= Session_Paused; + } + + // Release target texture + Object.Destroy(GPUTexture); + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/Extensions/ARVideoFeed.cs.meta b/Assets/ARDK/Extensions/ARVideoFeed.cs.meta new file mode 100644 index 0000000..f3a4450 --- /dev/null +++ b/Assets/ARDK/Extensions/ARVideoFeed.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 968195da08e0f4879b692f96fac940eb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/CapabilityChecker.cs b/Assets/ARDK/Extensions/CapabilityChecker.cs new file mode 100644 index 0000000..3f7c906 --- /dev/null +++ b/Assets/ARDK/Extensions/CapabilityChecker.cs @@ -0,0 +1,314 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.AR.Configuration; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; +using UnityEngine.Events; + +namespace Niantic.ARDK.Extensions +{ + [DisallowMultipleComponent] + public class CapabilityChecker: UnityLifecycleDriver + { + public bool HasSucceeded { get; private set; } + + [Serializable] + public enum FailureType + { + Error, + DeviceIncapable, + Timeout, + DeviceNotUpToDate, + ErrorDuringInstallation, + UserRejectedInstallation, + } + + [Serializable] + public struct FailureReason + { + public FailureType type; + public string message; + } + + [Serializable] + public class FailureEvent: UnityEvent {} + + [Serializable] + public class SuccessEvent: UnityEvent {} + + public SuccessEvent Success = new SuccessEvent(); + public FailureEvent Failure = new FailureEvent(); + + private void Succeed() + { + ARLog._Debug("Capability check succeeded "); + HasSucceeded = true; + Success.Invoke(); + } + + private void Fail(FailureType type, string message) + { + ARLog._Debug(message); + var reason = + new FailureReason + { + type = type, + message = message, + }; + + Failure.Invoke(reason); + } + + protected override void InitializeImpl() + { + base.InitializeImpl(); + + ValidateSuccessListeners(); + } + + protected override void EnableFeaturesImpl() + { + base.EnableFeaturesImpl(); + + if (!HasSucceeded) + CheckCapability(); + } + + /// Asynchronously checks whether the device is AR-capable. Reports the result through either + /// the Success or Failure event and the HasSucceeded property. + public void CheckCapability() + { + ARWorldTrackingConfigurationFactory.CheckCapabilityAndSupport + ( + (hardwareCapability, softwareSupport) => + { + switch (hardwareCapability) + { + case ARHardwareCapability.NotCapable: + Fail + ( + FailureType.DeviceIncapable, + "ARDK: Device not capable of world tracking!" + ); + + return; + + case ARHardwareCapability.CheckFailedWithError: + Fail + ( + FailureType.Error, + "ARDK: Unable to check for compatibility due to some error! Check logs for ARCore issues." + ); + + return; + + case ARHardwareCapability.CheckFailedWithTimeout: + Fail + ( + FailureType.Timeout, + "ARDK: Unable to check for compatibility due to network timeout! Make sure you are connected to the Internet and try again later!" + ); + + return; + + case ARHardwareCapability.Capable: + // We're good! + break; + + default: + throw new ArgumentOutOfRangeException + ( + nameof(hardwareCapability), + hardwareCapability, + null + ); + } + + // We know now that our hardware is capable! Time to check the software + switch (softwareSupport) + { + case ARSoftwareSupport.NotSupported: + string message; +#if UNITY_IOS + message = + "ARDK: Your current iOS version is not supported! Please upgrade to at least iOS 11 to enjoy this feature."; +#elif UNITY_ANDROID + message = + "ARDK: Your current Android system version is not supported! Please upgrade to a version supported by ArCore."; +#else + message = + "ARDK: Your current system is not supported! AR features are only supported on iOS/Android"; +#endif + Fail + ( + FailureType.DeviceIncapable, + message + ); + + return; + + case ARSoftwareSupport.SupportedNeedsUpdate: +#if UNITY_IOS + Fail + ( + FailureType.DeviceNotUpToDate, + "ARDK: Your current iOS version is out of date! Please update to enjoy this feature." + ); +#elif UNITY_ANDROID + InstallARCore(); +#endif + return; + + case ARSoftwareSupport.Supported: + // We're good! + break; + + default: + throw new ArgumentOutOfRangeException(nameof(softwareSupport), softwareSupport, null); + } + + Succeed(); + } + ); + } + + private void InstallARCore() + { + var installationResult = ARCoreInstaller.RequestInstallARCore + ( + true, + ARCoreInstaller.InstallBehavior.Optional, + ARCoreInstaller.InstallMessageType.Application + ); + + switch (installationResult) + { + case ARCoreInstaller.InstallResult.Failed: + { + Fail + ( + FailureType.ErrorDuringInstallation, + "Failed to install ARCore." + ); + + break; + } + + case ARCoreInstaller.InstallResult.Installed: + { + Fail + ( + FailureType.ErrorDuringInstallation, + "ARCore installation needed, but ARCore is already installed." + ); + + break; + } + + case ARCoreInstaller.InstallResult.RejectedByUser: + { + Fail + ( + FailureType.UserRejectedInstallation, + "User refused to install ARCore." + ); + + break; + } + + case ARCoreInstaller.InstallResult.PromptingUserToUpdate: + { + Debug.Log("Sending the user to the ARCore installation popup."); + _havePromptedTheUserToInstallARCore = true; + break; + } + } + } + + private bool _havePromptedTheUserToInstallARCore = false; + + private void OnApplicationPause(bool pauseStatus) + { + if (_havePromptedTheUserToInstallARCore && !pauseStatus) + { + var installationResult = ARCoreInstaller.RequestInstallARCore + ( + true, + ARCoreInstaller.InstallBehavior.Optional, + ARCoreInstaller.InstallMessageType.Application + ); + + switch (installationResult) + { + case ARCoreInstaller.InstallResult.Failed: + { + Fail + ( + FailureType.ErrorDuringInstallation, + "Failed to install ARCore." + ); + + return; + } + + case ARCoreInstaller.InstallResult.Installed: + { + break; + } + + case ARCoreInstaller.InstallResult.RejectedByUser: + { + Fail + ( + FailureType.UserRejectedInstallation, + "User refused to install ARCore." + ); + + return; + } + + case ARCoreInstaller.InstallResult.PromptingUserToUpdate: + { + Fail + ( + FailureType.ErrorDuringInstallation, + "Somehow re-prompting the user about installing ARCore." + ); + + return; + } + } + + Succeed(); + } + } + + private int _successListenersCount = 0; + private void OnValidate() + { + if (Success.GetPersistentEventCount() > _successListenersCount) + { + ValidateSuccessListeners(); + } + } + + private void ValidateSuccessListeners() + { + for (var i = 0; i < Success.GetPersistentEventCount(); i++) + { + var target = Success.GetPersistentTarget(i); + if (target.GetType() == typeof(ARSessionManager)) + { + ARLog._Error + ( + "ARSessionManager is set up to create an ARSession after the capability check passes, " + + "and should not be subscribed to the CapabilityChecker.Success event separately." + ); + } + } + } + } +} diff --git a/Assets/ARDK/Extensions/CapabilityChecker.cs.meta b/Assets/ARDK/Extensions/CapabilityChecker.cs.meta new file mode 100644 index 0000000..81ced2d --- /dev/null +++ b/Assets/ARDK/Extensions/CapabilityChecker.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 043ecbfe80cd44fca08dc8e0ee10100e +timeCreated: 1603170306 \ No newline at end of file diff --git a/Assets/ARDK/Extensions/Depth.meta b/Assets/ARDK/Extensions/Depth.meta new file mode 100644 index 0000000..7224a8b --- /dev/null +++ b/Assets/ARDK/Extensions/Depth.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d73fecf689ffd4bbda776d2965adffe2 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Depth/ARDepthInterpolationAdapter.cs b/Assets/ARDK/Extensions/Depth/ARDepthInterpolationAdapter.cs new file mode 100644 index 0000000..b38856b --- /dev/null +++ b/Assets/ARDK/Extensions/Depth/ARDepthInterpolationAdapter.cs @@ -0,0 +1,233 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.Awareness; +using Niantic.ARDK.AR.Awareness.Depth; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; + +namespace Niantic.ARDK.Extensions +{ + /// + /// A component that allows for dynamically setting the interpolation preference (whether to + /// apply interpolation that prefers near or far depths). + /// Allows users to specify whether to track a particular virtual object (_occludee) to align + /// interpolation for, or the average depths of the entire depth buffer. + /// + [RequireComponent(typeof(Camera))] + [RequireComponent(typeof(ARDepthManager))] + public class ARDepthInterpolationAdapter : MonoBehaviour + { + public enum AdaptionMode + { + /// Take a few samples of the full buffer to + /// determine the closest occluder on the screen. + SampleFullScreen = 0, + + // Sample the sub-region of the buffer that is directly over + // the main CG object, to determine the distance of its occluder + // in the world. + TrackOccludee = 1 + } + + private Camera _camera; + private ARDepthManager _depthManager; + + [SerializeField] + private AdaptionMode _mode = AdaptionMode.SampleFullScreen; + + public AdaptionMode Mode + { + get => _mode; + set => _mode = value; + } + + [SerializeField] + private Renderer _occludee; + + private void Awake() + { + _camera = GetComponent(); + _depthManager = GetComponent(); + + if (_mode == AdaptionMode.TrackOccludee && _occludee == null) + { + ARLog._Error("Missing occludee renderer to track."); + _mode = AdaptionMode.SampleFullScreen; + } + } + + private void OnEnable() + { + _depthManager.DepthBufferUpdated += OnDepthBufferUpdated; + } + + private void OnDisable() + { + _depthManager.DepthBufferUpdated -= OnDepthBufferUpdated; + } + + /// Sets the main occludee used to adjust interpolation preference for. + /// @note This method changes the adaption mode setting. + public void TrackOccludee(Renderer occludee) + { + if (occludee != null) + { + _occludee = occludee; + _mode = AdaptionMode.TrackOccludee; + } + } + + private void OnDepthBufferUpdated(ContextAwarenessStreamUpdatedArgs args) + { + if (!args.IsKeyFrame) + return; + + var processor = args.Sender; + var depthBuffer = processor.AwarenessBuffer; + var samplerTransform = processor.SamplerTransform; + + Vector2 center, extents; + if (_mode == AdaptionMode.SampleFullScreen) + { + center = new Vector2(0.5f, 0.5f); + extents = new Vector2(0.4f, 0.4f); + } + else + CalculateViewportRectangle(_occludee, _camera, out center, out extents); + + var depth = GetClosestDepth + ( + depthBuffer, + samplerTransform, + center, + extents + ); + + // Depth to non-linear + processor.InterpolationPreference = + (1.0f - depth * AwarenessParameters.ZBufferParams.w) / + (depth * AwarenessParameters.ZBufferParams.z); + } + + /// Calculates the normalized bounds that encloses + /// the provided renderer's pixels on the viewport. + private static void CalculateViewportRectangle + ( + Renderer forRenderer, + Camera usingCamera, + out Vector2 center, + out Vector2 extents + ) + { + var bounds = forRenderer.bounds; + var inCenter = bounds.center; + var inExtents = bounds.extents; + + Vector3[] points = + { + usingCamera.WorldToScreenPoint + ( + new Vector3(inCenter.x + inExtents.x, inCenter.y + inExtents.y, inCenter.z + inExtents.z) + ), + usingCamera.WorldToScreenPoint + ( + new Vector3(inCenter.x + inExtents.x, inCenter.y + inExtents.y, inCenter.z - inExtents.z) + ), + usingCamera.WorldToScreenPoint + ( + new Vector3(inCenter.x + inExtents.x, inCenter.y - inExtents.y, inCenter.z + inExtents.z) + ), + usingCamera.WorldToScreenPoint + ( + new Vector3(inCenter.x + inExtents.x, inCenter.y - inExtents.y, inCenter.z - inExtents.z) + ), + usingCamera.WorldToScreenPoint + ( + new Vector3(inCenter.x - inExtents.x, inCenter.y + inExtents.y, inCenter.z + inExtents.z) + ), + usingCamera.WorldToScreenPoint + ( + new Vector3(inCenter.x - inExtents.x, inCenter.y + inExtents.y, inCenter.z - inExtents.z) + ), + usingCamera.WorldToScreenPoint + ( + new Vector3(inCenter.x - inExtents.x, inCenter.y - inExtents.y, inCenter.z + inExtents.z) + ), + usingCamera.WorldToScreenPoint + ( + new Vector3(inCenter.x - inExtents.x, inCenter.y - inExtents.y, inCenter.z - inExtents.z) + ), + }; + + var xMin = float.MaxValue; + var yMin = float.MaxValue; + var xMax = float.MinValue; + var yMax = float.MinValue; + + for (int i = 0; i < points.Length; i++) + { + var point = points[i]; + + if (point.x < xMin) + xMin = point.x; + + if (point.x > xMax) + xMax = point.x; + + if (point.y < yMin) + yMin = point.y; + + if (point.y > yMax) + yMax = point.y; + } + + var widthNormalized = (xMax - xMin) / Screen.width; + var heightNormalized = (yMax - yMin) / Screen.height; + extents = new Vector2(widthNormalized / 2.0f, heightNormalized / 2.0f); + center = new Vector2 + ( + (xMin / Screen.width) + extents.x, + (yMin / Screen.height) + extents.y + ); + } + + /// Sparsely samples the specified subregion for the closest depth value. + private static float GetClosestDepth + ( + IDepthBuffer depthBuffer, + Matrix4x4 transform, + Vector2 center, + Vector2 extents + ) + { + float depth = float.MaxValue; + + var startX = center.x - extents.x; + var endX = center.x + extents.x; + var stepX = extents.x * 0.2f; + var horizontal = new Vector2(0.0f, center.y); + + for (horizontal.x = startX; horizontal.x <= endX; horizontal.x += stepX) + { + var sample = depthBuffer.Sample(horizontal, transform); + if (sample < depth) + depth = sample; + } + + var startY = center.y - extents.y; + var endY = center.y + extents.y; + var stepY = extents.y * 0.2f; + var vertical = new Vector2(center.x, 0.0f); + + for (vertical.y = startY; vertical.y <= endY; vertical.y += stepY) + { + var sample = depthBuffer.Sample(vertical, transform); + if (sample < depth) + depth = sample; + } + + return depth; + } + } +} diff --git a/Assets/ARDK/Extensions/Depth/ARDepthInterpolationAdapter.cs.meta b/Assets/ARDK/Extensions/Depth/ARDepthInterpolationAdapter.cs.meta new file mode 100644 index 0000000..3ba7581 --- /dev/null +++ b/Assets/ARDK/Extensions/Depth/ARDepthInterpolationAdapter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fd672b3e02db49ab85146648ba1651e1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Depth/ARDepthManager.cs b/Assets/ARDK/Extensions/Depth/ARDepthManager.cs new file mode 100644 index 0000000..55f2c6a --- /dev/null +++ b/Assets/ARDK/Extensions/Depth/ARDepthManager.cs @@ -0,0 +1,603 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; +using System.Collections.Generic; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.Awareness; +using Niantic.ARDK.AR.Awareness.Depth; +using Niantic.ARDK.AR.Awareness.Semantics; +using Niantic.ARDK.AR.Configuration; +using Niantic.ARDK.AR.Depth.Effects; +using Niantic.ARDK.Internals.EditorUtilities; +using Niantic.ARDK.Rendering; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; +using UnityEngine.Rendering; +using UnityEngine.Serialization; + +namespace Niantic.ARDK.Extensions +{ + [DisallowMultipleComponent] + public class ARDepthManager: + ARRenderFeatureProvider + { + /// Event for when the first depth buffer is received. + public event ArdkEventHandler> DepthBufferInitialized; + + /// Event for when the contents of the depth buffer or its affine transform was updated. + public event + ArdkEventHandler> DepthBufferUpdated; + + public enum OcclusionMode + { + /// No occlusions. + None = 0, + + /// The depth of an ARFrame is written to the target's z-buffer. + DepthBuffer = 1, + + /// Screen space mesh with its vertices pushed out to corresponding depth values. + ScreenSpaceMesh = 2, + + /// Uses the depth buffer on capable hardware, falls back to a screen space mesh occluder otherwise. + Auto = 3 + } + + [FormerlySerializedAs("_arCamera")] + [SerializeField] + [_Autofill] + [Tooltip("The scene camera used to render AR content.")] + private Camera _camera; + + [SerializeField] + [Range(1, 60)] + private uint _keyFrameFrequency = 20; + + [SerializeField] + [HideInInspector] + [Tooltip("Whether the depth buffer should synchronize with the camera pose.")] + private InterpolationMode _interpolation = InterpolationMode.Smooth; + + [SerializeField] + [HideInInspector] + [Range(0.0f, 1.0f)] + [Tooltip + ( + "Sets whether to align depth pixels with closer (0.1) or distant (1.0) pixels " + + "in the color image (aka the back-projection distance)." + ) + ] + private float _interpolationPreference = AwarenessParameters.DefaultBackProjectionDistance; + + [SerializeField] + private OcclusionMode _occlusionMode = OcclusionMode.Auto; + + [SerializeField] + [HideInInspector] + private FilterMode _textureFilterMode = FilterMode.Point; + + /// Returns a reference to the scene camera used to render AR content, if present. + public Camera Camera + { + get => _camera; + set + { + if (Initialized) + throw new InvalidOperationException("Cannot set this property after this component is initialized."); + + _camera = value; + } + } + + /// The value specifying how many times the depth generation routine + /// should target running per second. + public uint KeyFrameFrequency + { + get => _keyFrameFrequency; + set + { + if (value <= 0 && value > 60) + throw new ArgumentOutOfRangeException(nameof(value)); + + if (value != _keyFrameFrequency) + { + _keyFrameFrequency = value; + RaiseConfigurationChanged(); + } + } + } + + /// The value specifying whether the depth buffer should synchronize with the camera pose. + public InterpolationMode Interpolation + { + get => _interpolation; + set + { + if (Initialized) + throw new InvalidOperationException("Cannot set this property after this component is initialized."); + + _interpolation = value; + } + } + + /// The value specifying whether to align depth pixels with closer (0.1) + /// or distant (1.0) pixels in the color image (aka the back-projection distance). + public float InterpolationPreference + { + get => _interpolationPreference; + set + { + if (Initialized) + throw new InvalidOperationException("Cannot set this property after this component is initialized."); + + if (value < 0f && value > 1f) + throw new ArgumentOutOfRangeException(nameof(value)); + + _interpolationPreference = value; + } + } + + /// The value specifying how to render occlusions. + public OcclusionMode OcclusionTechnique + { + get => _occlusionMode; + set + { + if (_occlusionMode == value) + return; + + _occlusionMode = value; + + VerifyOcclusionTechnique(); + + // Reset the mesh occluder if it's present + if (_meshOccluder != null) + _meshOccluder.Enabled = _occlusionMode == OcclusionMode.ScreenSpaceMesh; + + // Notify the renderer that the active features have changed + InvalidateActiveFeatures(); + } + } + + /// If true, will use bilinear filtering instead of point filtering on the depth texture. + public bool PreferSmoothEdges + { + get => _textureFilterMode != FilterMode.Point; + set => _textureFilterMode = value ? FilterMode.Bilinear : FilterMode.Point; + } + + /// Returns the underlying context awareness processor. + public IDepthBufferProcessor DepthBufferProcessor + { + get => _GetOrCreateProcessor(); + } + + /// Returns the latest depth buffer on CPU memory. This buffer is not displayed aligned, and + /// needs to be sampled with the DepthTransform property. + public IDepthBuffer CPUDepth + { + get => _cpuDepth; + } + private IDepthBuffer _cpuDepth; + + /// Returns the latest depth buffer on GPU memory. The resulting texture is not display aligned, + /// and needs to be used with the DepthTransform property. + public Texture GPUDepth + { + get + { + UpdateDepthTexture(fromBuffer: _cpuDepth); + return _depthTexture; + } + } + + /// Returns a transformation that fits the depth buffer to the target viewport. + public Matrix4x4 DepthTransform + { + get => _depthTransform; + } + private Matrix4x4 _depthTransform; + + // The context awareness processor for depth buffers + private DepthBufferProcessor _depthBufferProcessor; + + private DepthBufferProcessor _GetOrCreateProcessor() + { + if (_depthBufferProcessor == null) + { + _depthBufferProcessor = new DepthBufferProcessor(_camera) + { + InterpolationMode = _interpolation, + InterpolationPreference = _interpolationPreference + }; + } + + return _depthBufferProcessor; + } + + // GPU depth for occlusions + // TODO: Please make efforts to allow using a render texture for this in future updates + // Note: If we used a render texture, we could avoid a CPU copy that we don't need + private Texture2D _depthTexture; + + // Get the MeshOccluder created by this object, if created + // @note May be null + public DepthMeshOccluder MeshOccluder + { + get + { + return _meshOccluder; + } + } + + // Controls the occluder mesh, in case the + // screen space mesh technique is selected + private DepthMeshOccluder _meshOccluder; + + // The semantics manager is responsible for maintaining + // a suppression mask if that feature is enabled. + private ARSemanticSegmentationManager _semanticSegmentationManager; + + // Helpers + private bool _supportsFloatingPointTextures; + private bool _supportsZWrite; + private bool _debugVisualizationEnabled; + private int _lastFrameDepthTextureWasUpdated; + private int _depthFrameCount; + + public bool IsDepthNormalized + { + get => _occlusionMode != OcclusionMode.None && !_supportsFloatingPointTextures; + } + + protected override void InitializeImpl() + { + if (_camera == null) + { + var warning = + "The Camera field was not set on the ARDepthManager before use. " + + "Will default to use Unity's Camera.main"; + + ARLog._Warn(warning); + _camera = Camera.main; + } + + _GetOrCreateProcessor(); + + // Check hardware capabilities + _supportsFloatingPointTextures = SystemInfo.SupportsTextureFormat(TextureFormat.RFloat); + _supportsZWrite = DoesDeviceSupportWritingToZBuffer(); + ARLog._Debug("Graphics device: " + SystemInfo.graphicsDeviceType); + + // Verify the selected occlusion technique + VerifyOcclusionTechnique(); + + base.InitializeImpl(); + } + + private void VerifyOcclusionTechnique() + { + // Explicit technique + if (_occlusionMode != OcclusionMode.Auto) + { + // If depth buffering is selected without hardware support + if (_occlusionMode == OcclusionMode.DepthBuffer && !_supportsZWrite) + ARLog._Error + ( + "Occlusion: Using depth buffer technique on a device that does not support Z Buffering" + ); + else + ARLog._Debug + ( + "Occlusion: Using " + _occlusionMode + " technique (explicit)." + ); + + return; + } + + // Determine which occlusion technique to use based on the running hardware + _occlusionMode = _supportsZWrite + ? OcclusionMode.DepthBuffer + : OcclusionMode.ScreenSpaceMesh; + + ARLog._Debug + ( + "Occlusion: Using " + _occlusionMode + " technique (auto)." + ); + } + + protected override void DeinitializeImpl() + { + // Release the depth processor + _depthBufferProcessor?.Dispose(); + + // Release the mesh occluder, if any + _meshOccluder?.Dispose(); + + // Release depth texture + if (_depthTexture != null) + Destroy(_depthTexture); + + base.DeinitializeImpl(); + } + + protected override void EnableFeaturesImpl() + { + base.EnableFeaturesImpl(); + + if (_meshOccluder != null) + _meshOccluder.Enabled = _occlusionMode == OcclusionMode.ScreenSpaceMesh; + + // Attempt to acquire the semantics manager + if (_semanticSegmentationManager == null) + _semanticSegmentationManager = GetComponent(); + + // If the semantics manager is present, listen to its updates + if (_semanticSegmentationManager != null) + _semanticSegmentationManager.SemanticBufferUpdated += OnSemanticBufferUpdated; + + // Listen to updates from the depth stream + _depthBufferProcessor.AwarenessStreamBegan += OnDepthBufferInitialized; + _depthBufferProcessor.AwarenessStreamUpdated += OnDepthBufferUpdated; + } + + protected override void DisableFeaturesImpl() + { + base.DisableFeaturesImpl(); + + if (_meshOccluder != null) + _meshOccluder.Enabled = false; + + if (_semanticSegmentationManager != null) + _semanticSegmentationManager.SemanticBufferUpdated -= OnSemanticBufferUpdated; + + _depthBufferProcessor.AwarenessStreamBegan -= OnDepthBufferInitialized; + _depthBufferProcessor.AwarenessStreamUpdated -= OnDepthBufferUpdated; + } + + public override void ApplyARConfigurationChange + ( + ARSessionChangesCollector.ARSessionRunProperties properties + ) + { + if (properties.ARConfiguration is IARWorldTrackingConfiguration worldConfig) + { + worldConfig.IsDepthEnabled = AreFeaturesEnabled; + worldConfig.DepthTargetFrameRate = _keyFrameFrequency; + } + } + + private void OnDepthBufferInitialized(ContextAwarenessArgs args) + { + // Currently just a pass-through + DepthBufferInitialized?.Invoke(args); + } + + private void OnDepthBufferUpdated(ContextAwarenessStreamUpdatedArgs args) + { + // Acquire new information + var processor = args.Sender; + _cpuDepth = processor.AwarenessBuffer; + _depthTransform = processor.SamplerTransform; + + // Increment frame counter + _depthFrameCount++; + + // Only update the depth texture when occlusions are enabled + if (_occlusionMode != OcclusionMode.None && args.IsKeyFrame) + UpdateDepthTexture(fromBuffer: _cpuDepth); + + // Update the screen space mesh occluder + if (_occlusionMode == OcclusionMode.ScreenSpaceMesh) + { + // Do we need to allocate the occluder? + if (_meshOccluder == null) + TryCreateMeshOccluder(); + + if (_meshOccluder != null) + { + // Update the sampler transform for the occluder + _meshOccluder.DepthTransform = _depthTransform; + + // Update the screen orientation (the rendered mesh might change) + _meshOccluder.Orientation = Screen.orientation; + } + } + + // Finally, let users know the manager has finished updating. + DepthBufferUpdated?.Invoke(args); + } + + private void OnSemanticBufferUpdated(ContextAwarenessStreamUpdatedArgs args) + { + // Sync interpolation preference with the semantics processor + args.Sender.InterpolationPreference = _GetOrCreateProcessor().InterpolationPreference; + + // Update the depth suppression mask, if present + if (_occlusionMode == OcclusionMode.ScreenSpaceMesh && _meshOccluder != null) + { + _meshOccluder.SuppressionTexture = _semanticSegmentationManager.DepthSuppressionTexture; + _meshOccluder.SemanticsTransform = args.Sender.SamplerTransform; + } + } + + /// Updates the depth texture + private void UpdateDepthTexture(IDepthBuffer fromBuffer) + { + if (fromBuffer == null || _lastFrameDepthTextureWasUpdated == _depthFrameCount) + return; + + _lastFrameDepthTextureWasUpdated = _depthFrameCount; + + if (_supportsFloatingPointTextures) + // Deliver depth in a floating point texture intact + fromBuffer.CreateOrUpdateTextureRFloat(ref _depthTexture, filterMode: _textureFilterMode); + else + { + // Deliver depth in an ARGB32 (8888) texture normalized + float max = fromBuffer.FarDistance; + float min = fromBuffer.NearDistance; + fromBuffer.CreateOrUpdateTextureARGB32 + ( + ref _depthTexture, + filterMode: _textureFilterMode, + valueConverter: depth => (depth - min) / (max - min) + ); + } + } + + /// Attempts to allocate and initialize a new mesh occluder. + /// @note This method does nothing if the depth texture is + /// not available or the mesh occluder is already present. + private void TryCreateMeshOccluder() + { + // The mesh occluder instance already exists + if (_meshOccluder != null) + return; + + // Depth texture is not ready + if (_depthTexture == null) + return; + + // Allocate the mesh occluder component + _meshOccluder = new DepthMeshOccluder + ( + targetCamera: _camera, + depthTexture: _depthTexture, + meshResolution: _cpuDepth.CalculateDisplayFrame + ( + _camera.pixelWidth, + _camera.pixelHeight + ) + ) + { + DebugColorMask = _debugVisualizationEnabled + ? DepthMeshOccluder.ColorMask.Depth + : DepthMeshOccluder.ColorMask.None + }; + + // If we push normalized values to the GPU, + // we need to input the respective min and max values + // to scale them back during rendering. Otherwise, + // min 0 and max 1 will result in no scaling applied. + if (IsDepthNormalized) + // Scale using the interval [near, far] + _meshOccluder.SetScaling(_cpuDepth.NearDistance, _cpuDepth.FarDistance); + else + // Do not scale + _meshOccluder.SetScaling(0, 1); + } + + /// Invoked when this component is asked about the render features + /// it may be responsible for. + /// @note: The implementation needs to include all features that are + /// possibly managed by this component. + protected override HashSet OnAcquireFeatureSet() + { + return new HashSet + { + FeatureBindings.DepthZWrite, + FeatureBindings.DepthDebug + }; + } + + /// Invoked when it is time to calculate the actual features that + /// this component currently manages. + protected override RenderFeatureConfiguration OnEvaluateConfiguration() + { + // If the depth manager is not active, all features are disabled + if (!AreFeaturesEnabled) + return new RenderFeatureConfiguration(null, featuresDisabled: Features); + + var enabledFeatures = new List(); + + // Depth z-write? + if (_occlusionMode == OcclusionMode.DepthBuffer && _supportsZWrite) + enabledFeatures.Add(FeatureBindings.DepthZWrite); + + // Visualize depth? + if (_debugVisualizationEnabled) + enabledFeatures.Add(FeatureBindings.DepthDebug); + + // All other features are considered disabled + var disabledFeatures = new HashSet(Features); + disabledFeatures.ExceptWith(enabledFeatures); + return new RenderFeatureConfiguration(enabledFeatures, disabledFeatures); + } + + protected override void OnRenderTargetChanged(RenderTarget? target) + { + _GetOrCreateProcessor().AssignViewport(target ?? _camera); + } + + /// Called when it is time to copy the current render state to the main rendering material. + /// @param material Material used to render the frame. + public override void UpdateRenderState(Material material) + { + // This material is only used for the depth buffering technique... + if (_occlusionMode != OcclusionMode.DepthBuffer) + return; + + // This is the time when the frame renderer asks for additional + // information for rendering the AR background. Here we pass the + // texture with depth information and a matrix to align it with + // the viewport. + material.SetTexture(PropertyBindings.DepthChannel, _depthTexture); + material.SetMatrix(PropertyBindings.DepthTransform, _depthTransform); + + // When the running hardware does not support floating point textures, + // we normalize depth to fit in 8 bits and deliver an ARGB32 (8888) texture. + // In this case, we need to scale depth on the GPU before use. + if (IsDepthNormalized) + { + // Scale depth using the interval [MinDepth, MaxDepth] + material.SetFloat(PropertyBindings.DepthScaleMin, _depthBufferProcessor.MinDepth); + material.SetFloat(PropertyBindings.DepthScaleMax, _depthBufferProcessor.MaxDepth); + } + else + { + // Do not scale + material.SetFloat(PropertyBindings.DepthScaleMin, 0); + material.SetFloat(PropertyBindings.DepthScaleMax, 1); + } + } + + public void ToggleDebugVisualization(bool isEnabled) + { + if (_debugVisualizationEnabled == isEnabled) + return; + + _debugVisualizationEnabled = isEnabled; + + if (_meshOccluder != null) + { + _meshOccluder.DebugColorMask = + isEnabled + ? DepthMeshOccluder.ColorMask.Depth + : DepthMeshOccluder.ColorMask.None; + } + + InvalidateActiveFeatures(); + } + + private static bool DoesDeviceSupportWritingToZBuffer() + { + var device = SystemInfo.graphicsDeviceType; + switch (device) + { + case GraphicsDeviceType.Direct3D11: + case GraphicsDeviceType.Direct3D12: + case GraphicsDeviceType.OpenGLES3: + case GraphicsDeviceType.OpenGLCore: + case GraphicsDeviceType.Metal: + case GraphicsDeviceType.Vulkan: + return true; + + default: + return false; + } + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/Extensions/Depth/ARDepthManager.cs.meta b/Assets/ARDK/Extensions/Depth/ARDepthManager.cs.meta new file mode 100644 index 0000000..0efe96c --- /dev/null +++ b/Assets/ARDK/Extensions/Depth/ARDepthManager.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 80198c6deee0a4c5c9096accbcac4119 +timeCreated: 1623453922 \ No newline at end of file diff --git a/Assets/ARDK/Extensions/Depth/DepthMeshOcclusionManager.cs b/Assets/ARDK/Extensions/Depth/DepthMeshOcclusionManager.cs new file mode 100644 index 0000000..b034d17 --- /dev/null +++ b/Assets/ARDK/Extensions/Depth/DepthMeshOcclusionManager.cs @@ -0,0 +1,32 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.AR.Awareness.Depth; +using Niantic.ARDK.AR.Awareness.Semantics; + +using Niantic.ARDK.AR; + +using Niantic.ARDK.AR.Awareness; +using Niantic.ARDK.AR.Awareness.Depth.Effects; +using Niantic.ARDK.AR.Depth; +using Niantic.ARDK.AR.Depth.Effects; +using Niantic.ARDK.Internals.EditorUtilities; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; + +namespace Niantic.ARDK.Extensions.Depth +{ + /// + /// This helper can be placed in a scene to easily add occlusions, with minimal setup time. It + /// reads synchronized depth output from ARFrame, and feeds it into an DepthMeshOcclusionEffect + /// that then performs the actual shader occlusion. Both precision options of + /// DepthMeshOcclusionEffect are available, and can be toggled between. + /// + [Obsolete("Use the ARDepthManager with its OcclusionMode property set to ScreenSpaceMesh instead.")] + public class DepthMeshOcclusionManager: + UnityLifecycleDriver + { + } +} diff --git a/Assets/ARDK/Extensions/Depth/DepthMeshOcclusionManager.cs.meta b/Assets/ARDK/Extensions/Depth/DepthMeshOcclusionManager.cs.meta new file mode 100644 index 0000000..77c3c0b --- /dev/null +++ b/Assets/ARDK/Extensions/Depth/DepthMeshOcclusionManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: accb0ac6e30a44ace82c0357aecfbc7a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Depth/DepthPointCloudManager.cs b/Assets/ARDK/Extensions/Depth/DepthPointCloudManager.cs new file mode 100644 index 0000000..ac6652f --- /dev/null +++ b/Assets/ARDK/Extensions/Depth/DepthPointCloudManager.cs @@ -0,0 +1,148 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.ARSessionEventArgs; +using Niantic.ARDK.AR.Awareness.Depth.Generators; +using Niantic.ARDK.AR.Configuration; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; +using UnityEngine.Rendering; + +namespace Niantic.ARDK.Extensions.Depth +{ + /// This helper can be placed in a scene to help visualize the depth point cloud. + /// All data is expected to come from ARSession. + public class DepthPointCloudManager: ARSessionListener + { + private const int MAX_SIMULTANEOUS_DRAW = 1023; + + private bool _drawPointCloud; + private Vector3[] _pointCloud; + private Matrix4x4[] _pointCloudMatrices; + + [SerializeField] + private GameObject _pointObject = null; + + [SerializeField] + private float _pointObjectScale = 0.01f; + + [SerializeField] + private int _pointCloudDrawSkipCount = 6; + + private Mesh _pointMesh; + private Material _pointMaterial; + + protected override void ListenToSession() + { + ARSession.FrameUpdated += OnFrameUpdated; + } + + protected override void StopListeningToSession() + { + ARSession.FrameUpdated -= OnFrameUpdated; + } + + public override void ApplyARConfigurationChange + ( + ARSessionChangesCollector.ARSessionRunProperties properties + ) + { + if (!AreFeaturesEnabled) + return; + + if (properties.ARConfiguration is IARWorldTrackingConfiguration worldConfig) + { + worldConfig.IsDepthPointCloudEnabled = true; + } + } + + private void OnFrameUpdated(FrameUpdatedArgs args) + { + var frame = args.Frame; + if (frame == null || frame.Depth == null || frame.DepthPointCloud == null) + return; + + // If this is our first DisparityBuffer frame, set up our resources + if (_pointMesh == null) + { + // Set up the point cloud resources + _pointMesh = _pointObject.GetComponent().sharedMesh; + _pointMaterial = _pointObject.GetComponent().sharedMaterial; + } + + PreparePointCloud(frame); + } + + private void Update() + { + if (!_drawPointCloud || _pointCloud == null) + return; + + // Draw the cloud + var numPointsToDraw = _pointCloudMatrices.Length; + var matrixBuffer = new Matrix4x4[MAX_SIMULTANEOUS_DRAW]; + int drawLength; + for (var i = 0; i < numPointsToDraw; i += drawLength) + { + drawLength = Math.Min(MAX_SIMULTANEOUS_DRAW, numPointsToDraw - i); + + System.Array.Copy(_pointCloudMatrices, i, matrixBuffer, 0, drawLength); + Graphics.DrawMeshInstanced + ( + _pointMesh, + 0, + _pointMaterial, + matrixBuffer, + drawLength, + null, + ShadowCastingMode.Off, + false + ); + + Graphics.DrawMesh(_pointMesh, _pointCloudMatrices[0], _pointMaterial, 0); + } + } + + /// When enabled, the next point cloud is saved and rendered until drawing is disabled. + public void ToggleDrawPointCloud() + { + _drawPointCloud = !_drawPointCloud; + + if (!_drawPointCloud) + _pointCloud = null; + + Debug.Log("PointCloud: " + (_drawPointCloud ? "ON" : "OFF")); + } + + private void PreparePointCloud(IARFrame frame) + { + if (!_drawPointCloud || _pointCloud != null) + return; + + var numPoints = frame.DepthPointCloud.Points.Count; + var numPointsToDraw = numPoints / _pointCloudDrawSkipCount; + + // If we haven't made our particle matrix array yet, do so now + if (_pointCloudMatrices == null) + _pointCloudMatrices = new Matrix4x4[numPointsToDraw]; + + _pointCloud = frame.DepthPointCloud.Points.ToArray(); + + for (var i = 0; i < numPointsToDraw; ++i) + { + _pointCloudMatrices[i] = Matrix4x4.TRS + ( + _pointCloud[i * _pointCloudDrawSkipCount], + Quaternion.identity, + Vector3.one * _pointObjectScale + ); + } + } + } +} diff --git a/Assets/ARDK/Extensions/Depth/DepthPointCloudManager.cs.meta b/Assets/ARDK/Extensions/Depth/DepthPointCloudManager.cs.meta new file mode 100644 index 0000000..cefb288 --- /dev/null +++ b/Assets/ARDK/Extensions/Depth/DepthPointCloudManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a351de41322e34106be618bc75927bc3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/FacePrefab.prefab b/Assets/ARDK/Extensions/FacePrefab.prefab new file mode 100644 index 0000000..99e566b --- /dev/null +++ b/Assets/ARDK/Extensions/FacePrefab.prefab @@ -0,0 +1,79 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &3323179959433865484 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5491085689089650947} + - component: {fileID: 386709719638515486} + - component: {fileID: 67067421895151360} + m_Layer: 0 + m_Name: FacePrefab + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &5491085689089650947 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3323179959433865484} + m_LocalRotation: {x: 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} +--- !u!33 &386709719638515486 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3323179959433865484} + m_Mesh: {fileID: 0} +--- !u!23 &67067421895151360 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3323179959433865484} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 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 diff --git a/Assets/ARDK/Extensions/FacePrefab.prefab.meta b/Assets/ARDK/Extensions/FacePrefab.prefab.meta new file mode 100644 index 0000000..d2ee0c9 --- /dev/null +++ b/Assets/ARDK/Extensions/FacePrefab.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1a351732d8dee472583b34d9c7b634a6 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/FeaturePreloadManager.cs b/Assets/ARDK/Extensions/FeaturePreloadManager.cs new file mode 100644 index 0000000..1c23a24 --- /dev/null +++ b/Assets/ARDK/Extensions/FeaturePreloadManager.cs @@ -0,0 +1,266 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; + +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Logging; +using Niantic.ARDK.Utilities.Preloading; + +using UnityEngine; + +namespace Niantic.ARDK.Extensions +{ + public class FeaturePreloadManager: + UnityLifecycleDriver + { + public sealed class PreloadProgressUpdatedArgs: + IArdkEventArgs + { + public ReadOnlyCollection FailedPreloads; + public ReadOnlyCollection SuccessfulPreloads; + public float Progress; + public bool PreloadAttemptFinished; + } + + [SerializeField] + private List _features = null; + + private Coroutine _preloadCoroutine; + + public ArdkEventHandler ProgressUpdated; + + public IFeaturePreloader Preloader + { + get + { + if (_preloader != null) + return _preloader; + + ARLog._Error("FeaturePreloadManager has not been initialized yet."); + return null; + } + } + + private IFeaturePreloader _preloader; + + protected override void InitializeImpl() + { + base.InitializeImpl(); + + _preloader = FeaturePreloaderFactory.Create(); + + // Might not be null if initialized through Inspector. + if (_features == null) + _features = new List(); + + // Remove duplicate features if added (adding duplicates is only possible through Inspector). + if (_features.Count > Enum.GetValues(typeof(Feature)).Length) + _features = _features.Distinct().ToList(); + } + + protected override void DeinitializeImpl() + { + base.DeinitializeImpl(); + + if (_preloader != null) + _preloader.Dispose(); + } + + protected override void EnableFeaturesImpl() + { + base.EnableFeaturesImpl(); + + StartDownload(); + } + + protected override void DisableFeaturesImpl() + { + base.DisableFeaturesImpl(); + + StopDownload(); + } + + public void AddFeature(Feature feature) + { + if (!_features.Contains(feature)) + _features.Add(feature); + } + + /// Clears ALL downloaded features, not just the ones added to this manager's features list. + public void ClearCache() + { + foreach (Feature feature in Enum.GetValues(typeof(Feature))) + { + Preloader.ClearCache(feature); + } + } + + /// Starts asynchronous download of added features. + public void StartDownload() + { + if (_preloadCoroutine != null) + { + ARLog._Warn("Preloading features is already in progress."); + return; + } + + _preloadCoroutine = StartCoroutine(DownloadFeatures()); + } + + /// Stops download of added features, and clears any partially downloaded features from the cache. + public void StopDownload() + { + if (_preloadCoroutine == null) + return; + + StopCoroutine(_preloadCoroutine); + _preloadCoroutine = null; + + // Only clear the features that were only partially downloaded + var featuresToClear = new HashSet(); + foreach (var feature in _features) + { + var status = Preloader.GetStatus(feature); + + if (status != PreloadedFeatureState.Finished) + featuresToClear.Add(feature); + } + + // Todo: Change once canceling preloads is possible outside of just disposing the preloader + Preloader.Dispose(); + _preloader = FeaturePreloaderFactory.Create(); + + foreach (var feature in featuresToClear) + { + ARLog._DebugFormat("Cleared partial download of {0} feature from cache.", false, feature); + _preloader.ClearCache(feature); + } + } + + public bool AreAllFeaturesDownloaded() + { + foreach (var feature in _features) + { + if (!Preloader.ExistsInCache(feature)) + return false; + } + + return true; + } + + private IEnumerator DownloadFeatures() + { + var featuresToDownload = new List(); + + if (_features.Count == 0) + { + ARLog._Warn("No features were added to download."); + yield break; + } + + if (Preloader == null) + yield break; + + var successfulPreloads = new List(); + var failedPreloads = new List(); + + var updateArgs = + new PreloadProgressUpdatedArgs + { + FailedPreloads = new ReadOnlyCollection(failedPreloads), + SuccessfulPreloads = new ReadOnlyCollection(successfulPreloads), + }; + + foreach (var feature in _features) + { + // Don't add feature to be downloaded if it was found cached. + if (_preloader.ExistsInCache(feature)) + { + ARLog._DebugFormat("{0} Feature was found in cache", false, feature); + successfulPreloads.Add(feature); + continue; + } + + // Check cache again as workaround for bug where the first call to ExistsInCache might + // return a false negative. + if (_preloader.ExistsInCache(feature)) + { + ARLog._DebugFormat("{0} Feature was found in cache", false, feature); + successfulPreloads.Add(feature); + continue; + } + + featuresToDownload.Add(feature); + } + + if (featuresToDownload.Count == 0) + { + _preloadCoroutine = null; + + ARLog._Debug("All features were found in cache. No need to download."); + updateArgs.Progress = 1f; + updateArgs.PreloadAttemptFinished = true; + ProgressUpdated?.Invoke(updateArgs); + + _preloadCoroutine = null; + yield break; + } + + var featuresCount = (float) _features.Count; + + ARLog._Debug("Starting preload..."); + _preloader.Download(featuresToDownload.ToArray()); + + while (true) + { + yield return null; + + var allFeaturesProgress = 0f; + + for (int i = featuresToDownload.Count - 1; i >= 0; i--) + { + var feature = featuresToDownload[i]; + + switch (_preloader.GetStatus(feature)) + { + case PreloadedFeatureState.Invalid: + case PreloadedFeatureState.NotStarted: + case PreloadedFeatureState.Downloading: + var progress = _preloader.GetProgress(feature); + ARLog._DebugFormat("Downloading {0} feature... {1}", false, feature, progress); + allFeaturesProgress += progress; + break; + + case PreloadedFeatureState.Finished: + ARLog._DebugFormat("Successfully downloaded {0} feature", false, feature); + successfulPreloads.Add(feature); + featuresToDownload.RemoveAt(i); + break; + + case PreloadedFeatureState.Failed: + ARLog._DebugFormat("Failed to download {0} feature", false, feature); + failedPreloads.Add(feature); + featuresToDownload.RemoveAt(i); + break; + } + } + + var completedDownloads = successfulPreloads.Count + failedPreloads.Count; + updateArgs.Progress = (completedDownloads + allFeaturesProgress) / featuresCount; + updateArgs.PreloadAttemptFinished = completedDownloads == _features.Count; + + ProgressUpdated?.Invoke(updateArgs); + + if (updateArgs.PreloadAttemptFinished) + { + _preloadCoroutine = null; + yield break; + } + } + } + } +} diff --git a/Assets/ARDK/Extensions/FeaturePreloadManager.cs.meta b/Assets/ARDK/Extensions/FeaturePreloadManager.cs.meta new file mode 100644 index 0000000..e71b5e7 --- /dev/null +++ b/Assets/ARDK/Extensions/FeaturePreloadManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dbd4c2c932f814cb991e2c486ec09b34 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Gameboard.meta b/Assets/ARDK/Extensions/Gameboard.meta new file mode 100644 index 0000000..4791f78 --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e97e377e8794e47af843b89b298e805d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Gameboard/AgentConfiguration.cs b/Assets/ARDK/Extensions/Gameboard/AgentConfiguration.cs new file mode 100644 index 0000000..45d5295 --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/AgentConfiguration.cs @@ -0,0 +1,52 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +namespace Niantic.ARDK.Extensions.Gameboard +{ + public struct AgentConfiguration + { + /// The maximum distance an agent can jump in meters. + public readonly float JumpDistance; + + /// Determines the cost of jumping. + /// @note This is an added cost for steps taken 'off-surface'. + /// @discussion + /// Being off-surface includes steps taken at the jumping off point + /// and steps taken mid-jump. + /// If there is a 1 cell block between the start and the destination, + /// assuming going around takes ~3 points, then jumping over with no + /// penalty will cost 2 points, jumping over with 1 penalty will cost + /// 3 points, and so on... If there is a gap between the two surfaces, + /// the cost of jumping will aggregate with each step until the agent + /// lands on a surface. + public readonly int JumpPenalty; + + /// Determines how the agent should behave when its destination is on a foreign surface. + public readonly PathFindingBehaviour Behaviour; + + public AgentConfiguration(int jumpPenalty, float jumpDistance, PathFindingBehaviour behaviour) + { + if (jumpPenalty < 0) + throw new ArgumentException("Jump penalty must be greater or equal to zero."); + + if (jumpDistance < 0) + throw new ArgumentException("Tile size must be greater or equal to zero."); + + JumpDistance = jumpDistance; + JumpPenalty = jumpPenalty; + Behaviour = behaviour; + } + + public static AgentConfiguration CreateSimpleAgent() + { + return new AgentConfiguration(0, 0f, PathFindingBehaviour.SingleSurface); + } + + public static AgentConfiguration CreateJumpingAgent + (PathFindingBehaviour pathFindingBehaviour = PathFindingBehaviour.InterSurfacePreferResults) + { + return new AgentConfiguration(2, 1f, pathFindingBehaviour); + } + } +} diff --git a/Assets/ARDK/Extensions/Gameboard/AgentConfiguration.cs.meta b/Assets/ARDK/Extensions/Gameboard/AgentConfiguration.cs.meta new file mode 100644 index 0000000..9cb4f10 --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/AgentConfiguration.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 60907d38b0f54f67b2dbfdcff3d92f6c +timeCreated: 1626878688 \ No newline at end of file diff --git a/Assets/ARDK/Extensions/Gameboard/Bounds.cs b/Assets/ARDK/Extensions/Gameboard/Bounds.cs new file mode 100644 index 0000000..ab1227e --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/Bounds.cs @@ -0,0 +1,123 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using UnityEngine; + +namespace Niantic.ARDK.Extensions.Gameboard +{ + /// Specifies an area in a top-down 2D grid using a square. + public readonly struct Bounds: IEquatable + { + /// Bottom left point (from a top-down perspective) + private readonly Vector2Int _anchor; + + /// Returns the center of the square. + public Vector2Int Center + { + get => new Vector2Int(_anchor.x + Size / 2, _anchor.y + Size / 2); + } + + /// Returns the bottom left corner point (this is also the anchor of this square). + public Vector2Int BottomLeft + { + get => _anchor; + } + + /// Returns the bottom right corner point. + public Vector2Int BottomRight + { + get => new Vector2Int(_anchor.x + Size, _anchor.y); + } + + /// Returns the top right corner point. + public Vector2Int TopRight + { + get => new Vector2Int(_anchor.x + Size, _anchor.y + Size); + } + + /// Returns the top left corner point. + public Vector2Int TopLeft + { + get => new Vector2Int(_anchor.x, _anchor.y + Size); + } + + /// The size of each side. + public readonly int Size; + + public Bounds(Vector2Int bottomLeft, int size) + { + _anchor = bottomLeft; + Size = size; + } + + /// Returns true if the specified point is within bounds. + public bool ContainsPoint(Vector2Int point) + { + return point.x >= _anchor.x && + point.x < _anchor.x + Size && + point.y >= _anchor.y && + point.y < _anchor.y + Size; + } + + /// Returns true if the specified bounds overlap with this one. + public bool Intersects(Bounds other) + { + var thisHorizontalRange = _anchor.x + Size; + var thisVerticalRange = _anchor.y + Size; + var otherHorizontalRange = other._anchor.x + other.Size; + var otherVerticalRange = other._anchor.y + other.Size; + + var horizontalOverlap = + _anchor.x >= other._anchor.x && _anchor.x <= otherHorizontalRange || + other._anchor.x >= _anchor.x && other._anchor.x <= thisHorizontalRange; + + var verticalOverlap = + _anchor.y >= other._anchor.y && _anchor.y <= otherVerticalRange || + other._anchor.y >= _anchor.y && other._anchor.y <= thisVerticalRange; + + return horizontalOverlap && verticalOverlap; + } + + public void DrawGizmos(float unitSize, Color color) + { + var metricSize = Size * unitSize; + var metricAnchor = new Vector3(_anchor.x * unitSize, 0.0f, _anchor.y * unitSize); + + Gizmos.color = color; + + Gizmos.DrawLine(metricAnchor, metricAnchor + Vector3.right * metricSize); + Gizmos.DrawLine(metricAnchor, metricAnchor + Vector3.forward * metricSize); + Gizmos.DrawLine + ( + metricAnchor + Vector3.right * metricSize, + metricAnchor + new Vector3(metricSize, 0.0f, metricSize) + ); + Gizmos.DrawLine + ( + metricAnchor + Vector3.forward * metricSize, + metricAnchor + new Vector3(metricSize, 0.0f, metricSize) + ); + + Gizmos.color = Color.white; + } + + public bool Equals(Bounds other) + { + return _anchor.Equals(other._anchor) && Size == other.Size; + } + + public override bool Equals(object obj) + { + return obj is Bounds other && Equals(other); + } + + public override int GetHashCode() + { + unchecked + { + return (_anchor.GetHashCode() * 397) ^ Size; + } + } + } +} diff --git a/Assets/ARDK/Extensions/Gameboard/Bounds.cs.meta b/Assets/ARDK/Extensions/Gameboard/Bounds.cs.meta new file mode 100644 index 0000000..3226f13 --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/Bounds.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 0c8cf634447140fb9d53978c571032b6 +timeCreated: 1627321897 \ No newline at end of file diff --git a/Assets/ARDK/Extensions/Gameboard/Gameboard.cs b/Assets/ARDK/Extensions/Gameboard/Gameboard.cs new file mode 100644 index 0000000..151b8db --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/Gameboard.cs @@ -0,0 +1,288 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Linq; + +using Niantic.ARDK.Utilities; + +using UnityEngine; + +using Random = UnityEngine.Random; + +namespace Niantic.ARDK.Extensions.Gameboard +{ + internal sealed class Gameboard: IGameboard + { + private readonly ModelSettings _settings; + + private GameboardModel _model; + private PathFinding _pathFinding; + private Visualiser _visualiser; + private bool _visualise; + + /// The configuration of the GameboardModel. + public ModelSettings Settings + { + get => _settings; + } + + /// The discovered free area in square meters. + public float Area { get; private set; } + + private void RecalculateArea() + { + Area = 0; + float tileArea = _settings.TileSize * _settings.TileSize; + foreach (Surface modelSurface in _model.Surfaces) + { + Area += modelSurface.Elements.Count() * tileArea; + } + } + + // Is invoked whenever the model changes. + public event ArdkEventHandler GameboardUpdated; + + public event ArdkEventHandler GameboardDestroyed; + + public void Destroy() + { + if (_visualiser != null) + _visualiser.Destroy(); + _visualiser = null; + _model = null; + GameboardDestroyed?.Invoke(new GameboardUpdatedArgs(null, false)); + } + + /// Allocates a new Gameboard. + /// @param settings Settings to calibrate unoccupied area detection. + /// @param visualise Activate visualisation. + public Gameboard(ModelSettings settings, bool visualise) + { + if (settings.TileSize <= 0) + throw new ArgumentException("Tile size must be greater than zero."); + + if (settings.KernelSize % 2 == 0) + throw new ArgumentException("Kernel size must be an odd number."); + + if (settings.MaxSlope > 40.0f) + throw new ArgumentException("MaxSlope must be less than or equal to 40 degrees."); + if (settings.MaxSlope < 0.0f) + throw new ArgumentException("MaxSlope must be positive."); + + _settings = settings; + _visualise = visualise; + _model = new GameboardModel(settings, visualise); + _pathFinding = new PathFinding(_model); + _visualiser = new Visualiser(this, _model, visualise); + } + + public bool IsOnGameboard(Vector3 position, float delta) + { + var tile = Utils.PositionToTile(position, _settings.TileSize); + + if (_model.SpatialTree.GetElement(tile, out var node)) + { + float elevation = node.Elevation; + if (elevation > position.y + delta) + return false; + + if (elevation + delta < position.y) + return false; + + return true; + } + + return false; + } + + public bool FindNearestFreePosition(Vector3 sourcePosition, float range, out Vector3 nearestPosition) + { + nearestPosition = default; + + if (Area == 0) + return false; + + var referencePoint = Utils.PositionToTile(sourcePosition, _settings.TileSize); + + // Define the search window + var halfSize = Mathf.FloorToInt(range / _settings.TileSize); + var anchor = new Vector2Int(referencePoint.x - halfSize, referencePoint.y - halfSize); + var boundsOfSearch = new Bounds + ( + bottomLeft: anchor, + size: halfSize * 2 + ); + + // Extract points within the search bounds + var pointsOfInterest = _model.SpatialTree.Query(withinBounds: boundsOfSearch)?.ToList(); + + // Find the closest point from candidates + var success = Utils.GetNearestNode(pointsOfInterest, referencePoint, out var nearestNode); + + // Convert to world position + nearestPosition = Utils.GridNodeToPosition(nearestNode, _settings.TileSize); + return success; + } + + public bool FindRandomPosition(out Vector3 randomPosition) + { + return _model.FindRandomPosition(out randomPosition); + } + + public bool FindNearestFreePosition(Vector3 sourcePosition, out Vector3 nearestPosition) + { + // Get reference coordinates + var referencePoint = Utils.PositionToTile(sourcePosition, _settings.TileSize); + + // Get neighboring points + var pointsOfInterest = _model.SpatialTree.Query(neighboursTo: referencePoint)?.ToList(); + + // Find the closest point from candidates + var success = Utils.GetNearestNode(pointsOfInterest, referencePoint, out var nearestNode); + + // Convert to world position + nearestPosition = Utils.GridNodeToPosition(nearestNode, _settings.TileSize); + return success; + } + + public bool FindRandomPosition(Vector3 sourcePosition, float range, out Vector3 randomPosition) + { + randomPosition = default; + + if (Area == 0) + return false; + + var referencePoint = Utils.PositionToTile(sourcePosition, _settings.TileSize); + + // Define the search window + var halfSize = Mathf.FloorToInt(range / _settings.TileSize); + var anchor = new Vector2Int(referencePoint.x - halfSize, referencePoint.y - halfSize); + var boundsOfSearch = new Bounds + ( + bottomLeft: anchor, + size: halfSize * 2 + ); + + // Extract points within the search bounds + var pointsOfInterest = _model.SpatialTree.Query(withinBounds: boundsOfSearch).ToList(); + if (pointsOfInterest.Count > 0) + { + // Get random unoccupied position + var idx = Random.Range(0, pointsOfInterest.Count - 1); + randomPosition = Utils.GridNodeToPosition(pointsOfInterest[idx], _settings.TileSize); + return true; + } + + // The search didn't yield any unoccupied nodes within bounds + return false; + } + + public bool CheckFit(Vector3 center, float size) + { + var surface = _model.Surfaces.FirstOrDefault + (s => s.ContainsElement(Utils.PositionToGridNode(center, _settings.TileSize))); + if (surface == null) + return false; + + var r = (Vector3.right + Vector3.forward) * (size * 0.5f); + var min = Utils.PositionToGridNode(center - r, _settings.TileSize); + var max = Utils.PositionToGridNode(center + r, _settings.TileSize); + var position = min.Coordinates; + + for (position.x = min.Coordinates.x; position.x <= max.Coordinates.x; position.x += 1) + for (position.y = min.Coordinates.y; position.y <= max.Coordinates.y; position.y += 1) + if (!surface.ContainsElement(new GridNode(position))) + return false; + + return true; + } + + private bool RayCast(Surface surface, Ray ray, out Vector3 hitPoint) + { + // Initialize resulting point + hitPoint = Vector3.zero; + + if (surface.IsEmpty) + return false; + + // Construct a mathematical plane + var position = Utils.TileToPosition(surface.Elements.FirstOrDefault().Coordinates, _settings.TileSize); + var p = new UnityEngine.Plane + (Vector3.up, new Vector3(position.x, surface.Elevation, position.y)); + + // Raycast plane + if (p.Raycast(ray, out float enter)) + { + // Check whether the hit point refers to a valid tile on the plane + hitPoint = ray.GetPoint(enter); + return surface.ContainsElement(Utils.PositionToGridNode(hitPoint, _settings.TileSize)); + } + + return false; + } + + public bool RayCast(Ray ray, out Vector3 hitPoint) + { + hitPoint = Vector3.zero; + + var didHit = false; + var minDistance = float.MaxValue; + foreach (var entry in _model.Surfaces) + { + if (RayCast(entry, ray, out Vector3 raycastHit)) + { + didHit = true; + var dist = Vector3.Distance(ray.origin, raycastHit); + if (dist < minDistance) + { + minDistance = dist; + hitPoint = raycastHit; + } + } + } + + return didHit; + } + + public void SetVisualisationActive(bool active) + { + _visualise = !_visualise; + _model.ToggleVisualisation(); + _visualiser.SetActive(active); + } + + public bool CalculatePath + (Vector3 fromPosition, Vector3 toPosition, AgentConfiguration agent, out Path path) + { + bool result = _pathFinding.CalculatePath(fromPosition, toPosition, agent, out path); + + if (_visualise) + _visualiser.DrawPath(path); + + return result; + } + + public void Scan(Vector3 origin, float range) + { + HashSet nodesDeleted = _model.Scan(origin, range); + RecalculateArea(); + GameboardUpdated?.Invoke(new GameboardUpdatedArgs(nodesDeleted, false)); + } + + /// Removes all surfaces from the Gameboard. + public void Clear() + { + _model.Clear(); + RecalculateArea(); + GameboardUpdated?.Invoke(new GameboardUpdatedArgs(new HashSet(), true)); + } + + public void Prune(Vector3 keepNodesOrigin, float range) + { + _model.Prune(keepNodesOrigin, range); + RecalculateArea(); + GameboardUpdated?.Invoke(new GameboardUpdatedArgs(new HashSet(), true)); + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/Extensions/Gameboard/Gameboard.cs.meta b/Assets/ARDK/Extensions/Gameboard/Gameboard.cs.meta new file mode 100644 index 0000000..c8c5baa --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/Gameboard.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f54d92e1a87024f9682a068ac6b12f23 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Gameboard/GameboardCreatedArgs.cs b/Assets/ARDK/Extensions/Gameboard/GameboardCreatedArgs.cs new file mode 100644 index 0000000..eae76d7 --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/GameboardCreatedArgs.cs @@ -0,0 +1,16 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.Extensions.Gameboard +{ + public class GameboardCreatedArgs: IArdkEventArgs + { + public IGameboard Gameboard { get; private set; } + + public GameboardCreatedArgs(IGameboard gameboard) + { + Gameboard = gameboard; + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/Extensions/Gameboard/GameboardCreatedArgs.cs.meta b/Assets/ARDK/Extensions/Gameboard/GameboardCreatedArgs.cs.meta new file mode 100644 index 0000000..81b40df --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/GameboardCreatedArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3284ea0857ed740049fc4ce0c93a7631 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Gameboard/GameboardFactory.cs b/Assets/ARDK/Extensions/Gameboard/GameboardFactory.cs new file mode 100644 index 0000000..8422284 --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/GameboardFactory.cs @@ -0,0 +1,81 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.Extensions.Gameboard +{ + /// Class used to create Gameboard instances and passes instance to subscribers of + /// GameboardInitialized. If a Gameboard was created and still alive, a second one can not be + /// created. + public static class GameboardFactory + { + private static ArdkEventHandler _gameboardInitialized; + + private static object _activeGameboardLock = new object(); + private static IGameboard _activeGameboard; + + /// Create a Gameboard and notify subscribers of GameboardInitialized about it. + /// @param settings Settings for the created Gameboard instance. + /// @params visualise If the Gameboard visualisation is activated at start time. + /// @returns The created Gameboard, or throws a Gameboard instance is still active. + public static IGameboard Create(ModelSettings settings, bool visualise) + { + IGameboard result = new Gameboard(settings, visualise); + + _InvokeGameboardInitialized(result); + return result; + } + + /// Event invoked when a new Gameboard is created and initialized. + public static event ArdkEventHandler GameboardInitialized + { + add + { + _StaticMemberValidator._FieldIsNullWhenScopeEnds(() => _gameboardInitialized); + + _gameboardInitialized += value; + + IGameboard activeGameboard; + lock (_activeGameboardLock) + activeGameboard = _activeGameboard; + + if (activeGameboard != null) + { + var args = new GameboardCreatedArgs(activeGameboard); + value(args); + } + } + remove + { + _gameboardInitialized -= value; + } + } + + private static void _InvokeGameboardInitialized(IGameboard gameboard) + { + lock (_activeGameboardLock) + { + if (_activeGameboard != null) + throw new InvalidOperationException("There's already an active Gameboard."); + + _activeGameboard = gameboard; + } + + var handler = _gameboardInitialized; + if (handler != null) + { + var args = new GameboardCreatedArgs(gameboard); + handler(args); + } + + gameboard.GameboardDestroyed += + (_) => + { + lock (_activeGameboardLock) + if (_activeGameboard == gameboard) + _activeGameboard = null; + }; + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/Extensions/Gameboard/GameboardFactory.cs.meta b/Assets/ARDK/Extensions/Gameboard/GameboardFactory.cs.meta new file mode 100644 index 0000000..11a80d3 --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/GameboardFactory.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e6bf493fa156f435e9bddfab9fae1c8a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Gameboard/GameboardManager.cs b/Assets/ARDK/Extensions/Gameboard/GameboardManager.cs new file mode 100644 index 0000000..2dd6415 --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/GameboardManager.cs @@ -0,0 +1,289 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; +using UnityEngine.Serialization; + +namespace Niantic.ARDK.Extensions.Gameboard +{ + /// This helper can be placed in a scene to easily create and update a Gameboard. Other scripts + /// can subscribe to GameboardFactory.OnGameboardCreated to access the created Gameboard. + /// It will trigger regular scans of the environment in front of the ARCamera based on the scan + /// settings. The Gameboard will add and remove tiles based on the Gameboard settings. + /// Scanning can be enabled/disabled by calling EnableFeatures() / DisableFeatures(). + /// Gameboard debug visibility can be toggled on and off. This includes Gameboard tiles, paths, + /// and gizmos of the scanning rays + public class GameboardManager: UnityLifecycleDriver + { +#pragma warning disable 649 + [FormerlySerializedAs("_arCamera")] + [SerializeField] + [Tooltip("The scene camera used to render AR content.")] + private Camera _camera; +#pragma warning restore 649 + + public IGameboard Gameboard { get; private set; } + + [Header("Gameboard Settings")] + [SerializeField] + [Tooltip("Metric size of a grid tile containing one node")] + [Min(0.0000001f)] + private float _tileSize = 0.15f; + + [SerializeField] + [Tooltip("Tolerance to consider floor as flat despite meshing noise")] + [Min(0.0000001f)] + private float _flatFloorTolerance = 0.2f; + + [SerializeField] + [Tooltip("Maximum slope angle (degrees) an area can have and still be considered flat")] + [Range(0, 40)] + private float _maxSlope = 25.0f; + + [SerializeField] + [Tooltip("The maximum amount two cells can differ in elevation and still be considered on the same plane")] + [Min(0.0000001f)] + private float _stepHeight = 0.1f; + + [Header("Scan Settings")] + [SerializeField] + private float _scanInterval = 0.1f; + + [SerializeField] + private float _scanRange = 1.5f; + + [SerializeField] + [Tooltip("Must be the same layer as meshes.")] + private LayerMask _layerMask = ~0; + + [Header("Debug")] + [SerializeField] + public bool _visualise = true; + + private bool recreateGameboard = false; + +#region GetterAndSetter + public Camera Camera + { + get => _camera; + set => _camera = value; + } + + [Obsolete("Use Camera property instead.")] + public Camera ArCamera + { + get => _camera; + set => _camera = value; + } + + /// The value specifying the size (meters) of a grid tile containing one node. + public float TileSize + { + get => _tileSize; + set + { + if (value <= 0f) + throw new ArgumentOutOfRangeException(nameof(value), "TileSize must be greater than 0."); + + _tileSize = value; + } + } + + /// The value specifying the amount of tolerance for meshing noise allowed to consider the floor as flat. + public float FlatFloorTolerance + { + get => _flatFloorTolerance; + set => _flatFloorTolerance = value; + } + + /// The value specifying the maximum slope angle (degrees) an area can have and still be considered flat + public float MaxSlope + { + get => _maxSlope; + set => _maxSlope = value; + } + + /// The value specifying the maximum amount two cells can differ in elevation and still be considered on the same plane. + public float StepHeight + { + get => _stepHeight; + set => _stepHeight = value; + } + + public float ScanInterval + { + get => _scanInterval; + set => _scanInterval = value; + } + + public float ScanRange + { + get => _scanRange; + set => _scanRange = value; + } + + public LayerMask LayerMask + { + get => _layerMask; + set => _layerMask = value; + } + + /// The value specifying whether to render the debug Gameboard visualization or not. + public bool Visualise + { + get => _visualise; + set => _visualise = value; + } +#endregion + +#region OnValidateVariables + private Camera _prevArCamera; + private float _prevTileSize; + private float _prevFlatFloorTolerance; + private float _prevMaxSlope; + private float _prevStepHeight; + private float _prevScanInterval; + private float _prevScanRange; + private LayerMask _prevLayerMask; + private bool _prevVisualise; +#endregion + + private ModelSettings _modelSettings; + + private float _lastScan; + + protected override void InitializeImpl() + { + base.InitializeImpl(); + + _prevArCamera = _camera; + _prevTileSize = _tileSize; + _prevFlatFloorTolerance = _flatFloorTolerance; + _prevMaxSlope = _maxSlope; + _prevStepHeight = _stepHeight; + _prevScanInterval = _scanInterval; + _prevScanRange = _scanRange; + _prevLayerMask = _layerMask; + _prevVisualise = _visualise; + + CreateNewGameboard(); + } + + protected override void DeinitializeImpl() + { + base.DeinitializeImpl(); + DestroyGameboard(); + } + + /// Activate/deactivate visualisation of scan raycasts, Gameboard tiles and paths. + public void SetVisualisationActive(bool active) + { + Gameboard?.SetVisualisationActive(active); + } + + /// This function triggers a scan of the environment to update the Gameboard model, by + /// adding new free tiles and removing newly occupied tiles. The scan is done in front of + /// the ARCamera. + private void UpdateGameboard() + { + var cameraTransform = _camera.transform; + var playerPosition = cameraTransform.position; + var playerForward = cameraTransform.forward; + + // The origin of the scan should be in front of the player + var origin = playerPosition + Vector3.ProjectOnPlane(playerForward, Vector3.up).normalized; + + // Scan the environment + Gameboard.Scan(origin, range: _scanRange); + } + + private void Update() + { + if (!AreFeaturesEnabled || Gameboard == null) + return; + + if (!(Time.time - _lastScan > _scanInterval)) + return; + + _lastScan = Time.time; + UpdateGameboard(); + + if (recreateGameboard) + { + DestroyGameboard(); + CreateNewGameboard(); + recreateGameboard = false; + } + } + + /// Destroys the existing Gameboard + public void DestroyGameboard() + { + if (Gameboard == null) + { + ARLog._Warn("No Gameboard to destroy."); + return; + } + + Gameboard.Destroy(); + Gameboard = null; + } + + /// Creates a new Gameboard using the GameboardFactory + public void CreateNewGameboard() + { + _modelSettings = + new ModelSettings + ( + _tileSize, + _flatFloorTolerance, + _maxSlope, + _stepHeight, + _layerMask + ); + + Gameboard = GameboardFactory.Create(_modelSettings, _visualise); + } + + private void OnValidate() + { + // this means initializeImpl is not finished yet; + if (_prevTileSize == 0) + return; + + var configChanged = false; + + if (_tileSize != _prevTileSize) + { + _prevTileSize = _tileSize; + configChanged = true; + } + + if (_flatFloorTolerance != _prevFlatFloorTolerance) + { + _prevFlatFloorTolerance = _flatFloorTolerance; + configChanged = true; + } + + if (_maxSlope != _prevMaxSlope) + { + _prevMaxSlope = _maxSlope; + configChanged = true; + } + + if (_stepHeight != _prevStepHeight) + { + _prevStepHeight = _stepHeight; + configChanged = true; + } + + if (configChanged) + { + recreateGameboard = true; + } + } + } +} diff --git a/Assets/ARDK/Extensions/Gameboard/GameboardManager.cs.meta b/Assets/ARDK/Extensions/Gameboard/GameboardManager.cs.meta new file mode 100644 index 0000000..0e85648 --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/GameboardManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 17e8d937f54af472cb69a845bde0a42c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Gameboard/GameboardMeshChunk.prefab b/Assets/ARDK/Extensions/Gameboard/GameboardMeshChunk.prefab new file mode 100644 index 0000000..f69f092 --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/GameboardMeshChunk.prefab @@ -0,0 +1,81 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1001 &5934148337070829665 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 4479615875184760195, guid: 99a6454115a034b2e9add187cf73f9eb, + type: 3} + propertyPath: m_Materials.Array.data[0] + value: + objectReference: {fileID: 2100000, guid: 5a202886f0af042c29be6fd57497e721, type: 2} + - target: {fileID: 4498647483606855101, guid: 99a6454115a034b2e9add187cf73f9eb, + type: 3} + propertyPath: m_RootOrder + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4498647483606855101, guid: 99a6454115a034b2e9add187cf73f9eb, + type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4498647483606855101, guid: 99a6454115a034b2e9add187cf73f9eb, + type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4498647483606855101, guid: 99a6454115a034b2e9add187cf73f9eb, + type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4498647483606855101, guid: 99a6454115a034b2e9add187cf73f9eb, + type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4498647483606855101, guid: 99a6454115a034b2e9add187cf73f9eb, + type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4498647483606855101, guid: 99a6454115a034b2e9add187cf73f9eb, + type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4498647483606855101, guid: 99a6454115a034b2e9add187cf73f9eb, + type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4498647483606855101, guid: 99a6454115a034b2e9add187cf73f9eb, + type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4498647483606855101, guid: 99a6454115a034b2e9add187cf73f9eb, + type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4498647483606855101, guid: 99a6454115a034b2e9add187cf73f9eb, + type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4501392110370713671, guid: 99a6454115a034b2e9add187cf73f9eb, + type: 3} + propertyPath: m_Name + value: MeshGameBoardChunk Variant + objectReference: {fileID: 0} + - target: {fileID: 4501392110370713671, guid: 99a6454115a034b2e9add187cf73f9eb, + type: 3} + propertyPath: m_Layer + value: 9 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 99a6454115a034b2e9add187cf73f9eb, type: 3} diff --git a/Assets/ARDK/Extensions/Gameboard/GameboardMeshChunk.prefab.meta b/Assets/ARDK/Extensions/Gameboard/GameboardMeshChunk.prefab.meta new file mode 100644 index 0000000..22c39e9 --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/GameboardMeshChunk.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: d0183eaba3a4c44e9aafc695278e1e9d +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Gameboard/GameboardModel.cs b/Assets/ARDK/Extensions/Gameboard/GameboardModel.cs new file mode 100644 index 0000000..2d871e8 --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/GameboardModel.cs @@ -0,0 +1,357 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Linq; + +using UnityEngine; + +using Random = UnityEngine.Random; + +namespace Niantic.ARDK.Extensions.Gameboard +{ + internal sealed class GameboardModel + { + public SpatialTree SpatialTree { get; } + + // Internal container for all surfaces. + public List Surfaces { get; } + private int _nextSurfaceId = 0; + private bool _visualise; + + public readonly ModelSettings Settings; + + public GameboardModel(ModelSettings settings, bool visualise) + { + Settings = settings; + _visualise = visualise; + Surfaces = new List(); + SpatialTree = new SpatialTree(Mathf.FloorToInt(settings.SpatialChunkSize / settings.TileSize)); + } + + public void ToggleVisualisation() + { + _visualise = !_visualise; + } + + public HashSet Scan(Vector3 origin, float range) + { + // Cache parameters + var kernelSize = Settings.KernelSize; + var kernelHalfSize = kernelSize / 2; + var tileSize = Settings.TileSize; + var tileHalfSize = tileSize / 2.0f; + const float rayLength = 100.0f; + + float halfRange = range / 2; + + // Calculate bounds for this scan on the grid + var lowerBoundPosition = new Vector2(origin.x - halfRange, origin.z - halfRange); + var upperBoundPosition = new Vector2(origin.x + halfRange, origin.z + halfRange); + var lowerBounds = Utils.PositionToTile(lowerBoundPosition, Settings.TileSize); + var upperBounds = Utils.PositionToTile(upperBoundPosition, Settings.TileSize); + if (upperBounds.x - lowerBounds.x < kernelSize || + upperBounds.y - lowerBounds.y < kernelSize) + { + throw new ArgumentException("Range is too short for the specified tile size."); + } + + // Bounds of the search area + var w = upperBounds.x - lowerBounds.x; + var h = upperBounds.y - lowerBounds.y; + + // Array to store information on the nodes resulting from this scan + var scanArea = new GridNode[w * h]; + + // Scan heights + for (var x = 0; x < w; x++) + { + for (var y = 0; y < h; y++) + { + + // Calculate the world position of the ray + var coords = new Vector2Int(lowerBounds.x + x, lowerBounds.y + y); + var position = new Vector3 + ( + coords.x * tileSize + tileHalfSize, + origin.y, + coords.y * tileSize + tileHalfSize + ); + + var arrayIndex = y * w + x; + + if (_visualise) + Debug.DrawLine(position + Vector3.down, position + 2*Vector3.down, Color.green, 0.5f); + + // Raycast for height + var elevation = + Physics.Raycast + ( + new Ray(position, Vector3.down), + out RaycastHit hit, + rayLength, + layerMask: Settings.LayerMask + ) + ? hit.point.y + : -100; + + scanArea[arrayIndex] = new GridNode(coords) + { + DiffFromNeighbour = float.MaxValue, Elevation = elevation + }; + } + } + + // This set is used to register nodes that are obviously occupied + var invalidate = new HashSet(); + + // Calculate areal properties + var kernel = new Vector3[kernelSize * kernelSize]; + for (var x = kernelHalfSize; x < w - kernelHalfSize; x++) + { + for (var y = kernelHalfSize; y < h - kernelHalfSize; y++) + { + // Construct kernel for this grid cell using its neighbours + var kernelIndex = 0; + for (var kx = -kernelHalfSize; kx <= kernelHalfSize; kx++) + { + for (var ky = -kernelHalfSize; ky <= kernelHalfSize; ky++) + { + var x1 = Mathf.Clamp(kx + x, 0, w - 1); + var y1 = Mathf.Clamp(ky + y, 0, h - 1); + kernel[kernelIndex++] = Utils.GridNodeToPosition(scanArea[y1 * w + x1], Settings.TileSize); + } + } + + var idx = y * w + x; + + // Try to fit a plane on the neighbouring points + Utils.FastFitPlane(kernel, out Vector3 _, out Vector3 normal); + + // Assign standard deviation and slope angle + var slope = Mathf.Abs(90.0f - Vector3.Angle(Vector3.forward, normal)); + var std = Utils.CalculateStandardDeviation(kernel.Select(pos => pos.y)); + scanArea[idx].Deviation = std; + + // Collect nodes that are occupied + var isWalkable = std < Settings.KernelStdDevTol && + slope < Settings.MaxSlope && + scanArea[idx].Elevation > Settings.MinElevation; + + if (!isWalkable) + invalidate.Add(scanArea[idx]); + } + } + + // Remove nodes that are occupied from existing planes + HashSet removedNodes = InvalidateNodes(invalidate); + + var open = new Queue(); + var closed = new HashSet(); + var eligible = new HashSet(); + + // Define seed as the center of the search area + open.Enqueue(scanArea[(h / 2) * w + (w / 2)]); + while (open.Count > 0) + { + // Extract current tile + var currentNode = open.Dequeue(); + + // Consider this node to be visited + closed.Add(currentNode); + + if (invalidate.Contains(currentNode)) + continue; // Skip this node as it is occupied + + // Register this tile as unoccupied... + eligible.Add(currentNode); + + var neighbours = Utils.GetNeighbours(currentNode.Coordinates); + foreach (var neighbour in neighbours) + { + + // Get the coordinates transformed to our local scan area + var transformedNeighbour = neighbour - lowerBounds; + if (transformedNeighbour.x < kernelHalfSize || + transformedNeighbour.x >= w - kernelHalfSize || + transformedNeighbour.y < kernelHalfSize || + transformedNeighbour.y >= h - kernelHalfSize) + { + continue; // Out of bounds + } + + var arrayIndex = transformedNeighbour.y * w + transformedNeighbour.x; + + // If we've been here before + if (closed.Contains(scanArea[arrayIndex])) + continue; + + var diff = Mathf.Abs(currentNode.Elevation - scanArea[arrayIndex].Elevation); + if (scanArea[arrayIndex].DiffFromNeighbour > diff) + { + scanArea[arrayIndex].DiffFromNeighbour = diff; + } + + // Can we walk from the current node to this neighbour? + var isEligible = !open.Contains(scanArea[arrayIndex]) && + scanArea[arrayIndex].DiffFromNeighbour <= Settings.StepHeight; + + if (isEligible) + open.Enqueue(scanArea[arrayIndex]); + } + } + + if (eligible.Count >= 2) + { + // Merge newly found unoccupied areas with existing planes + MergeNodes(eligible); + } + + return removedNodes; + } + + /// Removes all surfaces from the board. + public void Clear() + { + if (Surfaces.Count == 0) + return ; + + Surfaces.Clear(); + SpatialTree.Clear(); + } + + public void Prune(Vector3 keepNodesOrigin, float range) + { + if (Surfaces.Count == 0) + return; + + float halfRange = range / 2; + + var topRight = keepNodesOrigin + + Vector3.right * halfRange + + Vector3.forward * halfRange; + + var bottomLeft = keepNodesOrigin + + Vector3.left * halfRange + + Vector3.back * halfRange; + + var min = Utils.PositionToGridNode(bottomLeft, Settings.TileSize); + var max = Utils.PositionToGridNode(topRight, Settings.TileSize); + + var bounds = new Bounds(min.Coordinates, max.Coordinates.x - min.Coordinates.x); + var toKeep = SpatialTree.Query(withinBounds: bounds).ToList(); + + SpatialTree.Clear(); + SpatialTree.Insert(toKeep); + + // Remove tiles for surfaces + Surfaces.ForEach(surface => surface.Intersect(toKeep)); + + // Clean empty surfaces + Surfaces.RemoveAll(surface => surface.IsEmpty); + } + + /// Invalidates the specified nodes of existing planes. + private HashSet InvalidateNodes(HashSet nodes) + { + // Remove nodes from registry + HashSet removedNodes = SpatialTree.Remove(nodes); + + // Remove nodes from its respective surfaces + Surfaces.ForEach(entry => entry.Except(nodes)); + + // Clean up empty planes + Surfaces.RemoveAll(entry =>entry.IsEmpty); + + return removedNodes; + } + + /// Merges new unoccupied nodes with existing planes. If the nodes cannot be merged, a new plane is created. + private void MergeNodes(HashSet nodes) + { + // Register new unoccupied nodes + SpatialTree.Insert(nodes); + + // Create a new planes from the provided (unoccupied) nodes + var candidate = new Surface(nodes, _nextSurfaceId); + _nextSurfaceId++; + + // Just add the candidate plane to the list if this is the first one we found + if (Surfaces.Count == 0) + { + Surfaces.Add(candidate); + return; + } + + // Gather overlapping planes + var overlappingPlanes = Surfaces.Where(entry => entry.Overlaps(candidate)).ToList(); + + // No overlap, add candidate as a new plane + if (!overlappingPlanes.Any()) + { + Surfaces.Add(candidate); + return; + } + + // Find an overlapping plane that satisfies the merging conditions + var anchorPlane = overlappingPlanes.FirstOrDefault + ( + entry => + entry.CanMerge(candidate, Settings.StepHeight * 2.0f) + ); + + // No such plane + if (anchorPlane == null) + { + // Exclude its nodes from existing planes + foreach (var surface in overlappingPlanes) + { + surface.Except(candidate); + } + + // Remove planes that were a subset of the candidate + Surfaces.RemoveAll(surface => surface.IsEmpty); + + // Add candidate as a new plane + Surfaces.Add(candidate); + return; + } + + // Base plane found to merge the new nodes to + anchorPlane.Merge(candidate); + + // Iterate through other overlapping planes except this base plane + overlappingPlanes.Remove(anchorPlane); + foreach (var entry in overlappingPlanes) + { + // Either merge or exclude nodes + if (anchorPlane.CanMerge(entry, Settings.StepHeight * 2.0f)) + { + anchorPlane.Merge(entry); + Surfaces.Remove(entry); + } + else + { + entry.Except(candidate); + } + } + } + + public bool FindRandomPosition(out Vector3 randomPosition) + { + if (Surfaces.Count == 0) + { + randomPosition = Vector3.zero; + return false; + } + + int randomSurface = Random.Range(0, Surfaces.Count-1); + int randomNode = Random.Range(0, Surfaces[randomSurface].Elements.Count()); + + randomPosition = Utils.GridNodeToPosition + (Surfaces[randomSurface].Elements.ElementAt(randomNode), Settings.TileSize); + + return true; + } + } +} diff --git a/Assets/ARDK/Extensions/Gameboard/GameboardModel.cs.meta b/Assets/ARDK/Extensions/Gameboard/GameboardModel.cs.meta new file mode 100644 index 0000000..2d1d5d7 --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/GameboardModel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1a9ef4951a0a24d0d8b7ec0f36b7d56e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Gameboard/GameboardUpdatedArgs.cs b/Assets/ARDK/Extensions/Gameboard/GameboardUpdatedArgs.cs new file mode 100644 index 0000000..02617a2 --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/GameboardUpdatedArgs.cs @@ -0,0 +1,21 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.Collections.Generic; +using Niantic.ARDK.Utilities; + +using UnityEngine; + +namespace Niantic.ARDK.Extensions.Gameboard +{ + public class GameboardUpdatedArgs : IArdkEventArgs + { + public HashSet RemovedNodes { get; } + public readonly bool PruneOrClear; + + public GameboardUpdatedArgs(HashSet removedNodes, bool pruneOrClear) + { + RemovedNodes = removedNodes; + PruneOrClear = pruneOrClear; + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/Extensions/Gameboard/GameboardUpdatedArgs.cs.meta b/Assets/ARDK/Extensions/Gameboard/GameboardUpdatedArgs.cs.meta new file mode 100644 index 0000000..69a31ff --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/GameboardUpdatedArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d0ba3383593cd4273b4cffc9e037db7e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Gameboard/GridNode.cs b/Assets/ARDK/Extensions/Gameboard/GridNode.cs new file mode 100644 index 0000000..656dc70 --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/GridNode.cs @@ -0,0 +1,40 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using UnityEngine; + +namespace Niantic.ARDK.Extensions.Gameboard +{ + /// Encloses data for grid elements used during scanning for walkable areas. + public struct GridNode: IEquatable + { + /// Coordinates of this node on the grid. + public readonly Vector2Int Coordinates; + + /// Height of the node. + public float Elevation; + + /// Standard deviation in the area around the node. + public float Deviation; + + /// The calculated minimum difference in elevation from a neighbouring node. + public float DiffFromNeighbour; + + public GridNode(Vector2Int coordinates) + : this() + { + Coordinates = coordinates; + } + + public bool Equals(GridNode other) + { + return Coordinates.Equals(other.Coordinates); + } + + public override int GetHashCode() + { + return Coordinates.GetHashCode(); + } + } +} diff --git a/Assets/ARDK/Extensions/Gameboard/GridNode.cs.meta b/Assets/ARDK/Extensions/Gameboard/GridNode.cs.meta new file mode 100644 index 0000000..9ded12d --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/GridNode.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: fc2bcc6cd8e32460cb5d55a1ea633688 +timeCreated: 1603971056 \ No newline at end of file diff --git a/Assets/ARDK/Extensions/Gameboard/IGameboard.cs b/Assets/ARDK/Extensions/Gameboard/IGameboard.cs new file mode 100644 index 0000000..039a3e3 --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/IGameboard.cs @@ -0,0 +1,106 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Utilities; + +using UnityEngine; + +namespace Niantic.ARDK.Extensions.Gameboard +{ + /// Holds information about unoccupied areas in the environment. Requires meshing to be enabled. + /// Provides pathfinding and functions for environmental queries. + public interface IGameboard + { + /// The configuration this Gameboard was created with. + ModelSettings Settings { get; } + + /// The discovered free area in square meters. + float Area { get; } + + /// Alerts subscribers that the Gameboard has been updated. + event ArdkEventHandler GameboardUpdated; + + /// Alerts subscribers that the Gameboard has been destroyed. + event ArdkEventHandler GameboardDestroyed; + + /// Destroys the Gameboard and triggers the GameboardDestroyed event. + void Destroy(); + + /// Searches for occupied and unoccupied areas in the environment and updates the Gameboard + /// accordingly by adding and removing nodes. For this, rays are cast against the mesh from the + /// scan origin downwards. Raycasts will not find free areas under obstacles like tables, etc. + /// @param origin Origin of the scan in world position. + /// @param range Area covered by the scan is size range*range. + void Scan(Vector3 origin, float range); + + /// Removes all surfaces from the board. + void Clear(); + + /// Removes nodes outside the specified squared area of size range*range. + /// Use this to prune Gameboard for performance. + /// @param keepNodesOrigin Defines an origin in world position from which nodes will be kept. + /// @param range Range of the box area where nodes will be kept. + void Prune(Vector3 keepNodesOrigin, float range); + + /// Checks whether an area is free to occupy by a box with footprint size*size. Does not take + /// the height into account. + /// @param center Origin of the area in world position. + /// @param size Width/Length of the object's estimated footprint in meter. + bool CheckFit(Vector3 center, float size); + + /// Checks whether the specified (projected) world position is on the Gameboard surface. + /// @param position World coordinate for the query. + /// @param delta Tolerance in y position still considered on the Gameboard surface + /// @returns True, if the specified position is on the Gameboard. + bool IsOnGameboard(Vector3 position, float delta); + + /// Finds the nearest world position on the Gameboard to the specified source position. + /// @param sourcePosition The origin of the search. + /// @param nearestPosition The resulting nearest position, if any. + /// @returns True, if a nearest point could be found. + bool FindNearestFreePosition(Vector3 sourcePosition, out Vector3 nearestPosition); + + /// Finds the nearest world position on the Gameboard to the specified source position within + /// a specified range. + /// @param sourcePosition The origin of the search. + /// @param range Defines the search window (size = 2 * range). + /// @param nearestPosition The resulting nearest position, if any. + /// @returns True, if a nearest point could be found. + bool FindNearestFreePosition(Vector3 sourcePosition, float range, out Vector3 nearestPosition); + + /// Finds a random world position on the Gameboard. + /// @param randomPosition The resulting random position, if any. + /// @returns True, if a point could be found. + bool FindRandomPosition(out Vector3 randomPosition); + + /// Finds a random world position on the Gameboard within a specified range. + /// @param sourcePosition The origin of the search. + /// @param range Defines the search window (size = 2 * range). + /// @param randomPosition The resulting random position, if any. + /// @returns True, if a point could be found. + bool FindRandomPosition(Vector3 sourcePosition, float range, out Vector3 randomPosition); + + /// Calculates a walkable path between the two specified positions. + /// @param fromPosition Start position. + /// @param toPosition Destination position + /// @param agent The configuration of the agent is path is calculated for. + /// @param path The calculated path + /// @returns True if either a complete or partial path is found. False otherwise. + bool CalculatePath + ( + Vector3 fromPosition, + Vector3 toPosition, + AgentConfiguration agent, + out Path path + ); + + /// Raycasts against the Gameboard. + /// @param ray Ray to perform this function with. + /// @param hitPoint Hit point in world coordinates, if any. + /// @returns True if the ray hit a point on any plane within the Gameboard. + bool RayCast(Ray ray, out Vector3 hitPoint); + + /// Activates/Deactivates visualisation of Gameboard areas and agent paths + /// @param active Activates visualisation if true, deactivates if false + void SetVisualisationActive(bool active); + } +} diff --git a/Assets/ARDK/Extensions/Gameboard/IGameboard.cs.meta b/Assets/ARDK/Extensions/Gameboard/IGameboard.cs.meta new file mode 100644 index 0000000..5eb0273 --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/IGameboard.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 59b17f2d719d4426a96676c86c18b2fd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Gameboard/ModelSettings.cs b/Assets/ARDK/Extensions/Gameboard/ModelSettings.cs new file mode 100644 index 0000000..722ea90 --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/ModelSettings.cs @@ -0,0 +1,68 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using UnityEngine; + +namespace Niantic.ARDK.Extensions.Gameboard { + public struct ModelSettings { + + + /// Metric size of a grid cell. + public float TileSize; + + /// Size of a spatial partition in square meters. + /// Grid cells within the same area will be stored together. + public float SpatialChunkSize; + + /// The size of the kernel used to compute areal properties for each cell. + /// @note This needs to be an odd integer. + public int KernelSize; + + /// The standard deviation tolerance value to use when determining node noise within a cell, + /// outside of which the cell is considered too noisy to be walkable. + public float KernelStdDevTol; + + /// Maximum slope angle (degrees) of an area to be considered flat. + public float MaxSlope; + + /// Minimum elevation (meters) a GridNode is expected to have in order to be walkable + public float MinElevation; + + /// The maximum amount two cells can differ in elevation to be considered on the same plane. + public float StepHeight; + + /// Specifies the layer of the environment to raycast. + public LayerMask LayerMask; + + public ModelSettings(float tileSize, float kernelStdDevTol, float maxSlope, float stepHeight, LayerMask layerMask) + : this() + { + TileSize = tileSize; + KernelStdDevTol = kernelStdDevTol; + MaxSlope = maxSlope; + StepHeight = stepHeight; + LayerMask = layerMask; + + // Rest is default for now: + SpatialChunkSize = 10.0f; + KernelSize = 3; + MinElevation = -10; + } + + /// Constructs a configuration with default settings. + public static ModelSettings Default + { + get => + new ModelSettings + { + TileSize = 0.15f, + SpatialChunkSize = 10.0f, + KernelSize = 3, + KernelStdDevTol = 0.2f, + MaxSlope = 25.0f, + StepHeight = 0.1f, + LayerMask = 1, + MinElevation = -10.0f, + }; + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/Extensions/Gameboard/ModelSettings.cs.meta b/Assets/ARDK/Extensions/Gameboard/ModelSettings.cs.meta new file mode 100644 index 0000000..fffd976 --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/ModelSettings.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 15fdec0e78e744f148a988fe67babd56 +timeCreated: 1602693831 \ No newline at end of file diff --git a/Assets/ARDK/Extensions/Gameboard/Path.cs b/Assets/ARDK/Extensions/Gameboard/Path.cs new file mode 100644 index 0000000..513a616 --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/Path.cs @@ -0,0 +1,35 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.Collections.Generic; + +namespace Niantic.ARDK.Extensions.Gameboard +{ + public class Path + { + public List Waypoints { get; } + public int Length + { + get + { + if (Waypoints == null) + return 0; + else + return Waypoints.Count; + } + } + + public enum Status {PathComplete, PathPartial, PathInvalid} + public Status PathStatus { get; } + + public Path(List waypoints, Status pathStatus) + { + Waypoints = waypoints; + PathStatus = pathStatus; + + if (waypoints == null || waypoints.Count == 0) + { + PathStatus = Status.PathInvalid; + } + } + } +} diff --git a/Assets/ARDK/Extensions/Gameboard/Path.cs.meta b/Assets/ARDK/Extensions/Gameboard/Path.cs.meta new file mode 100644 index 0000000..f094aa5 --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/Path.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cc5d92edfb87346f9941462c4afbdabc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Gameboard/PathFinding.cs b/Assets/ARDK/Extensions/Gameboard/PathFinding.cs new file mode 100644 index 0000000..6d95e47 --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/PathFinding.cs @@ -0,0 +1,406 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Linq; + +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; + +namespace Niantic.ARDK.Extensions.Gameboard +{ + internal sealed class PathFinding + { + private GameboardModel _model; + + public PathFinding(GameboardModel model) + { + _model = model; + } + + public bool CalculatePath + ( + Vector3 fromPosition, + Vector3 toPosition, + AgentConfiguration agent, + out Path path + ) + { + bool result; + + // Convert world positions to coordinates on the grid + var source = Utils.PositionToGridNode(fromPosition, _model.Settings.TileSize); + var destination = Utils.PositionToGridNode(toPosition, _model.Settings.TileSize); + + // Attempting to get path to the same tile + if (source.Equals(destination)) + { + ARLog._Warn("Attempted to calculate path to the same position."); + path = new Path(null, Path.Status.PathInvalid); + return false; + } + + // Find the subject surface on the Gameboard + var startSurface = _model.Surfaces.FirstOrDefault(p => p.ContainsElement(source)); + if (startSurface == null) + { + ARLog._Warn("Could not locate start position on any surface."); + path = new Path(null, Path.Status.PathInvalid); + return false; + } + + switch (agent.Behaviour) + { + case PathFindingBehaviour.SingleSurface: + result = CalculatePathOnSurface(startSurface, source, destination, out Vector2Int _, out path); + break; + + case PathFindingBehaviour.InterSurfacePreferPerformance: + result = CalculatePathOnBoardLocal(startSurface, source, destination, agent, out path); + break; + + case PathFindingBehaviour.InterSurfacePreferResults: + result = CalculatePathOnBoardGlobal(startSurface, source, destination, agent, out path); + break; + + default: + throw new NotImplementedException(); + } + + return result; + } + + private bool CalculatePathOnSurface + ( + Surface surface, + GridNode source, + GridNode destination, + out Vector2Int closestCoordinateToDestination, + out Path path + ) + { + var costToGoal = Vector2Int.Distance(source.Coordinates, destination.Coordinates); + var start = new PathFindingNode(source.Coordinates, surface) + { + CostToGoal = costToGoal + }; + + var open = new List {start}; + + var closed = new HashSet(); + List waypoints; + + // This is a substitute for the destination if it cannot be found on the surface + var closestNodeToGoal = start; + + while (open.Count > 0) + { + // Get the most eligible node to continue traversal + var current = open[0]; + open.RemoveAt(0); + closed.Add(current); + + if (current.CostToGoal < closestNodeToGoal.CostToGoal) + { + closestNodeToGoal = current; + } + + // Find neighbours on the plane + var neighbours = Utils.GetNeighbours(current.Coordinates); + foreach (var coords in neighbours) + { + if (!surface.ContainsElement(new GridNode(coords))) + { + // Discard this neighbour, since it cannot be found on the same plane + continue; + } + + // Potential successor + var successor = new PathFindingNode(coords, surface, current.Coordinates); + + // We arrived at the goal + if (successor.Coordinates.Equals(destination.Coordinates)) + { + closestCoordinateToDestination = successor.Coordinates; + waypoints = GeneratePath(nodes: closed, traceStart: successor); + path = new Path(waypoints, Path.Status.PathComplete); + return true; + } + + // We have already processed this grid cell. + if (closed.Contains(successor)) + { + continue; + } + + // Calculate costs + successor.CostToThis = current.CostToThis + Utils.ManhattanDistance(successor, current); + successor.CostToGoal = Vector2Int.Distance + (destination.Coordinates, successor.Coordinates); + + var existingIndex = open.FindIndex + (openNode => openNode.Coordinates.Equals(successor.Coordinates)); + + if (existingIndex >= 0) + { + var existing = open[existingIndex]; + if (existing.Cost <= successor.Cost) + { + continue; + } + + open.RemoveAt(existingIndex); + } + + open.InsertIntoSortedList(successor, (a, b) => a.CompareTo(b)); + } + } + + // We have reached the closest position to our destination on this surface + closestCoordinateToDestination = closestNodeToGoal.Coordinates; + waypoints = GeneratePath(nodes: closed, traceStart: closestNodeToGoal); + path = new Path(waypoints, Path.Status.PathPartial); + return true; + } + + private bool CalculatePathOnBoardLocal + ( + Surface startSurface, + GridNode source, + GridNode destination, + AgentConfiguration agent, + out Path path + ) + { + // We will use this origin to test its neighbouring nodes on the grid for validity to be jumped over or onto + var result = CalculatePathOnSurface(startSurface, source, destination, out Vector2Int searchOrigin, out path); + + var currentSurface = startSurface; + var closestCoordinateToDestination = searchOrigin; + var nextOrigin = searchOrigin; + + while (!searchOrigin.Equals(destination.Coordinates)) + { + var continueSearch = false; + var neighbours = Utils.GetNeighbours(searchOrigin) + .OrderBy(coords => Vector2Int.Distance(coords, destination.Coordinates)) + .ToArray(); + + foreach (var neighbour in neighbours) + { + var inspectedNeighbour = new GridNode(neighbour); + + // The inspected node can't belong to the same plane we're currently on and it has to be within the specified jump distance + var isValidNeighbour = !currentSurface.ContainsElement(inspectedNeighbour) && + Vector2Int.Distance + (inspectedNeighbour.Coordinates, closestCoordinateToDestination) * + _model.Settings.TileSize < + agent.JumpDistance && + Vector2Int.Distance + (inspectedNeighbour.Coordinates, destination.Coordinates) < + Vector2Int.Distance(searchOrigin, destination.Coordinates); + + if (!isValidNeighbour) + { + continue; + } + + if (!continueSearch) + { + // We store the new closest node to the destination + // in case we can't find a valid node to jump to in this range... + nextOrigin = inspectedNeighbour.Coordinates; + continueSearch = true; + } + + // Check whether the inspected node belongs to any other existing plane + var nextSurface = _model.Surfaces.FirstOrDefault + (surface => surface.ContainsElement(inspectedNeighbour)); + + if (nextSurface != null) + { + // Can we jump here? + if (Vector3.Distance + ( + Utils.TileToPosition(closestCoordinateToDestination, currentSurface.Elevation, _model.Settings.TileSize), + Utils.TileToPosition(nextOrigin, nextSurface.Elevation, _model.Settings.TileSize) + ) < + agent.JumpDistance) + { + // New surface found! + inspectedNeighbour.Elevation = nextSurface.Elevation; + var subRoute = CalculatePathOnSurface + (nextSurface, inspectedNeighbour, destination, out nextOrigin, out Path subPath); + + closestCoordinateToDestination = nextOrigin; + currentSurface = nextSurface; + path.Waypoints.AddRange(subPath.Waypoints); + + break; + } + } + } + + if (!continueSearch) + { + break; + } + + searchOrigin = nextOrigin; + } + + return result; + } + + private bool CalculatePathOnBoardGlobal + ( + Surface startSurface, + GridNode source, + GridNode destination, + AgentConfiguration agent, + out Path path + ) + { + var costToGoal = Vector2Int.Distance(source.Coordinates, destination.Coordinates); + var start = new PathFindingNode(source.Coordinates, startSurface) + { + CostToGoal = costToGoal + }; + + var open = new List + { + start + }; + + var closed = new HashSet(); + List waypoints; + + var closestNodeToGoal = start; + + while (open.Count > 0) + { + // Get the most eligible node to continue traversal + var current = open[0]; + open.RemoveAt(0); + closed.Add(current); + + if (current.CostToGoal < closestNodeToGoal.CostToGoal && current.Surface != null) + { + closestNodeToGoal = current; + } + + // Find neighbours on the plane + var neighbours = Utils.GetNeighbours(current.Coordinates); + foreach (var coords in neighbours) + { + var node = new GridNode(coords); + var surfaceOfNeighbour = current.Surface == null || !current.Surface.ContainsElement(node) + ? _model.Surfaces.FirstOrDefault(s => s.ContainsElement(node)) + : current.Surface; + + var offSurface = surfaceOfNeighbour == null; + + // Potential successor + var successor = offSurface + ? new PathFindingNode(coords, current.Elevation, parentCoordinates: current.Coordinates) + : new PathFindingNode(coords, surfaceOfNeighbour, parentCoordinates: current.Coordinates); + + var aggregateOffSurface = offSurface + ? current.AggregateOffSurface + 1 + : 0; + + var elevationDiff = Mathf.Abs(successor.Elevation - current.Elevation); + var offSurfaceDist = aggregateOffSurface * _model.Settings.TileSize; + var jumpDistance = Mathf.Sqrt + (elevationDiff * elevationDiff + offSurfaceDist * offSurfaceDist); + + if (jumpDistance > agent.JumpDistance) + { + continue; + } + + // We arrived at the goal + if (!offSurface && successor.Coordinates.Equals(destination.Coordinates)) + { + waypoints = GeneratePath(nodes: closed, traceStart: successor); + path = new Path(waypoints, Path.Status.PathComplete); + return true; + } + + // We have already processed this grid cell. + if (closed.Contains(successor)) + { + continue; + } + + // Calculate costs + var isJump = elevationDiff > 0 || offSurface; + successor.AggregateOffSurface = aggregateOffSurface; + successor.CostToThis = current.CostToThis + + Utils.ManhattanDistance(successor, current) + + (isJump ? agent.JumpPenalty : 0); + + successor.CostToGoal = Vector2Int.Distance + (destination.Coordinates, successor.Coordinates); + + var existingIndex = open.FindIndex + (openNode => openNode.Coordinates.Equals(successor.Coordinates)); + + if (existingIndex >= 0) + { + var existing = open[existingIndex]; + if (existing.Cost <= successor.Cost) + { + continue; + } + + open.RemoveAt(existingIndex); + } + + open.InsertIntoSortedList(successor, (a, b) => a.CompareTo(b)); + } + } + + // We have reached the closest position to our destination on this surface + waypoints = GeneratePath(nodes: closed, traceStart: closestNodeToGoal); + path = new Path(waypoints, Path.Status.PathPartial); + return true; + } + + /// Traces a path from a pre-computed PathNode collection. + /// @param nodesA collection containing parental relationships. + /// @param traceStart The source node of the trace. + private List GeneratePath(HashSet nodes, PathFindingNode traceStart) + { + var path = new List(); + + // Trace path + var node = traceStart; + while (node.HasParent) + { + var parent = nodes.FirstOrDefault + (entry => entry.Coordinates.Equals(node.ParentCoordinates)); + + // Extract node position + if (node.Surface != null) + { + var type = parent.Surface == node.Surface + ? Waypoint.MovementType.Walk + : Waypoint.MovementType.SurfaceEntry; + + var pos = Utils.TileToPosition(node.Coordinates, _model.Settings.TileSize); + path.Add(new Waypoint(new Vector3(pos.x, node.Elevation, pos.y), type, node.Coordinates)); + } + + // Go to parent + node = parent; + } + + // The resulting array should start with the source node + path.Reverse(); + + return path; + } + } +} diff --git a/Assets/ARDK/Extensions/Gameboard/PathFinding.cs.meta b/Assets/ARDK/Extensions/Gameboard/PathFinding.cs.meta new file mode 100644 index 0000000..0c0f095 --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/PathFinding.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 483c5f73bf33e440aaf6007fd732b7a2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Gameboard/PathFindingBehaviour.cs b/Assets/ARDK/Extensions/Gameboard/PathFindingBehaviour.cs new file mode 100644 index 0000000..3a44ad9 --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/PathFindingBehaviour.cs @@ -0,0 +1,21 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.Extensions.Gameboard +{ + public enum PathFindingBehaviour + { + /// The calculated route will navigate to the destination + /// or the closest point to it within a single surface. + SingleSurface = 0, + + /// The calculated route can contain jumps to other surfaces. + /// @note + /// The agent will only consider immediate nodes during the search. + /// This method is faster, but does not always find an existing path. + InterSurfacePreferPerformance = 1, + + /// The calculated route can contain jumps to other surfaces. + /// @note This method is slower, but it finds a path if it exists. + InterSurfacePreferResults = 2 + } +} diff --git a/Assets/ARDK/Extensions/Gameboard/PathFindingBehaviour.cs.meta b/Assets/ARDK/Extensions/Gameboard/PathFindingBehaviour.cs.meta new file mode 100644 index 0000000..5a5b94a --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/PathFindingBehaviour.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a5ea2dbede8ff485e891e7dfecfeb8c2 +timeCreated: 1610120066 \ No newline at end of file diff --git a/Assets/ARDK/Extensions/Gameboard/PathFindingNode.cs b/Assets/ARDK/Extensions/Gameboard/PathFindingNode.cs new file mode 100644 index 0000000..552bc27 --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/PathFindingNode.cs @@ -0,0 +1,90 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using UnityEngine; + +namespace Niantic.ARDK.Extensions.Gameboard +{ + /// Encloses data for grid elements used during path finding. + internal struct PathFindingNode: IEquatable, IComparable + { + /// The coordinates of this parent. + public readonly Vector2Int Coordinates; + + /// The coordinates of this node's parent. + public readonly Vector2Int ParentCoordinates; + + /// Elevation of the node. + public readonly float Elevation; + + /// Whether this path node has a parent assign. + public readonly bool HasParent; + + /// Cost to get to this node for the source in a path finding context. + public int CostToThis; + + /// Cost to get from this node to the destination in a path finding context. + public float CostToGoal; + + /// The number of continuous nodes without a surface. + public int AggregateOffSurface; + + /// The surface this node belongs to. Could be null. + public readonly Surface Surface; + + /// Combined cost of this node. + public float Cost + { + get + { + return CostToThis + CostToGoal; + } + } + + public PathFindingNode(Vector2Int coordinates, Surface surface) + : this() + { + Coordinates = coordinates; + Elevation = surface.Elevation; + Surface = surface; + } + + public PathFindingNode(Vector2Int coordinates, float elevation) + : this() + { + Coordinates = coordinates; + Elevation = elevation; + Surface = null; + } + + public PathFindingNode(Vector2Int coordinates, Surface surface, Vector2Int parentCoordinates) + : this(coordinates, surface) + { + ParentCoordinates = parentCoordinates; + HasParent = true; + } + + public PathFindingNode(Vector2Int coordinates, float elevation, Vector2Int parentCoordinates) + : this(coordinates, elevation) + { + ParentCoordinates = parentCoordinates; + HasParent = true; + } + + public bool Equals(PathFindingNode other) + { + return Coordinates.Equals(other.Coordinates); + } + + public override int GetHashCode() + { + return Coordinates.GetHashCode(); + } + + public int CompareTo(PathFindingNode other) + { + return Cost.CompareTo(other.Cost); + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/Extensions/Gameboard/PathFindingNode.cs.meta b/Assets/ARDK/Extensions/Gameboard/PathFindingNode.cs.meta new file mode 100644 index 0000000..cd761c3 --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/PathFindingNode.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: adcb485050113414793efdf67eabdd91 +timeCreated: 1602694317 \ No newline at end of file diff --git a/Assets/ARDK/Extensions/Gameboard/Quad.cs b/Assets/ARDK/Extensions/Gameboard/Quad.cs new file mode 100644 index 0000000..db2ec6f --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/Quad.cs @@ -0,0 +1,481 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Linq; + +using Niantic.ARDK.Utilities.Collections; + +using UnityEngine; + +namespace Niantic.ARDK.Extensions.Gameboard +{ + internal sealed partial class SpatialTree + { + private class Quad + { + // The bounding area of this quad + public Bounds Bounds { get; } + + // Store for items + private List _elements; + + // Store for child quads, if any + private Quad[] _children; + + // The number of items a quad can store before subdivision + private const int AtomicCapacity = 4; + + // The possible depth of this quad + private readonly int _rank; + + // The parent of this quadrant + private readonly WeakReference _parent; + + /// Returns whether this quad is a leaf bucket. + public bool IsLeaf + { + get => _children == null; + } + + public bool HasElements + { + get => _elements != null && _elements.Count > 0; + } + + /// Returns the child quadrants of this parent. + public IEnumerable GetChildren() + { + return _children?.AsArdkReadOnly(); + } + + /// Allocates a new quad. + /// @param origin The center of the quad. + /// @param rank Determines the number of subdivisions possible (rank - 1) + public Quad(Vector2Int origin, int rank) + { + // Minimum rank is 1 (stores 4 items) + _rank = rank < 1 ? 1 : rank; + + // Calculate the size of the bounding square's size + var size = (int)Mathf.Pow(2, _rank); + var halfSize = size / 2; + + // Create the bounding square + Bounds = new Bounds + ( + // Top left corner position (origin - size/2) + bottomLeft: origin - new Vector2Int(halfSize, halfSize), + size: size + ); + + // Every quad is a leaf until it gets subdivided + _elements = new List(AtomicCapacity); + _children = null; + + // Root node + _parent = new WeakReference(null); + } + + private Quad(Bounds bounds, int rank, Quad parent) + { + // Minimum rank is 1 (stores 4 items) + _rank = rank; + + // Set bounds + Bounds = bounds; + + // Every quad is a leaf until it gets subdivided + _elements = new List(AtomicCapacity); + _children = null; + + // Set parent + _parent = new WeakReference(parent); + } + + /// Inserts a new item into this quad. + public bool Insert(GridNode node) + { + // Discard points that are outside of bounds + if (!Bounds.ContainsPoint(node.Coordinates)) + return false; + + if (IsLeaf) + { + // Point is already registered (at position) + if (_elements.Contains(node)) + { + // Update node + var idx = _elements.FindIndex(n => n.Equals(node)); + _elements[idx] = node; + + // Node updated + return true; + } + + // Maximum capacity is not yet reached + if (_elements.Count < AtomicCapacity) + { + // Add item + _elements.Add(node); + + // Node inserted + return true; + } + + // Maximum capacity is reached + if (!Subdivide()) + return false; + } + + // Add item to to a child node + var itemInserted = + _children[0].Insert(node) || + _children[1].Insert(node) || + _children[2].Insert(node) || + _children[3].Insert(node); + + return itemInserted; + } + + /// Removes an item from this quad, if contained. + public bool Remove(GridNode node) + { + var quad = FindLeaf(node.Coordinates); + if (quad == null) + return false; + + var elements = quad._elements; + if (elements.Contains(node)) + { + // Remove node from elements + elements.Remove(node); + + // Merge containing quad with siblings if necessary + if (elements.Count == 0) + if (quad._parent.TryGetTarget(out var parent)) + MergeIfEmpty(parent); + + return true; + } + + return false; + } + + /// Returns all points in the area defined by the quad boundaries. + public IEnumerable GetElements() + { + if (IsLeaf) + return _elements; + + var result = new List(); + var stack = new Stack(); + stack.Push(this); + + while (stack.Count > 0) + { + // Get next quad + var current = stack.Pop(); + + // If this quad is not a leaf, it does not store any elements + if (!current.IsLeaf) + { + // Add children to the queue + for (int i = 0; i < current._children.Length; i++) + stack.Push(current._children[i]); + } + // If it is a leaf, collect its elements + else + result.AddRange(current._elements); + } + + return result; + } + + /// Returns elements of this quad within the specified boundaries. + /// @param withinBounds The enclosing boundaries. + /// @returns A new list of stored elements within the specified bounds. + public IEnumerable GetElements(Bounds withinBounds) + { + var result = new List(); + var stack = new Stack(); + stack.Push(this); + + while (stack.Count > 0) + { + // Get next quad + var current = stack.Pop(); + + // If this quad shares no common area with the search bounds, skip + if (!current.Bounds.Intersects(withinBounds)) + continue; + + // If this quad is not a leaf, it does not store any elements + if (!current.IsLeaf) + { + // Add children to the queue + for (int i = 0; i < current._children.Length; i++) + stack.Push(current._children[i]); + } + else + { + // Add elements within bounds + for (int i = 0; i < current._elements.Count; i++) + { + var entry = current._elements[i]; + if (withinBounds.ContainsPoint(entry.Coordinates)) + result.Add(entry); + } + } + } + + return result; + } + + public bool GetElement(Vector2Int atCoordinates, out GridNode result) + { + var quad = FindLeaf(atCoordinates); + if (quad == null) + { + result = default; + return false; + } + + for (int i = 0; i < quad._elements.Count; i++) + { + result = quad._elements[i]; + if (result.Coordinates.Equals(atCoordinates)) + return true; + } + + result = default; + return false; + } + + public IEnumerable GetNeighbours(Vector2Int toCoordinates) + { + var leaf = Bounds.ContainsPoint(toCoordinates) + ? FindLeaf(toCoordinates) + : FindNearestLeaf(toCoordinates); + + return leaf.HasElements + ? leaf.GetElements() + : leaf.FindNearestElementsInSiblings(toCoordinates); + } + + private Quad FindLeaf(Vector2Int forCoordinates) + { + var stack = new Stack(); + stack.Push(this); + + while (stack.Count > 0) + { + var current = stack.Pop(); + if (!current.Bounds.ContainsPoint(forCoordinates)) + continue; + + if (current.IsLeaf) + return current; + + for (int i = 0; i < current._children.Length; i++) + stack.Push(current._children[i]); + } + + return null; + } + + private Quad FindNearestLeaf(Vector2Int toCoordinates) + { + var stack = new Stack(); + stack.Push(this); + + while (stack.Count > 0) + { + var current = stack.Pop(); + if (current.IsLeaf) + return current; + + var minDistance = float.MaxValue; + Quad nearest = current._children[0]; + for (int i = 0; i < current._children.Length; i++) + { + var child = current._children[i]; + var dist = Vector2Int.Distance(child.Bounds.Center, toCoordinates); + if (dist < minDistance) + { + minDistance = dist; + nearest = child; + } + } + + stack.Push(nearest); + } + + return null; + } + + private IEnumerable FindNearestElementsInSiblings(Vector2Int reference) + { + if (!_parent.TryGetTarget(out Quad parent)) + return new List(); + + var stack = new Stack(); + var siblings = parent._children; + + for (var i = 0; i < siblings.Length; i++) + { + var child = siblings[i]; + if (child != this) + stack.Push(child); + } + + var result = new List(); + while (stack.Count > 0) + { + var current = stack.Pop(); + if (current.IsLeaf) + { + // Add elements to the list + if (current.HasElements) + result.AddRange(current._elements); + + // Discard empty + continue; + } + + GetNearestChildrenWithElements + ( + withinQuad: current, + toPoint: reference, + out Quad near1, + out Quad near2 + ); + + if (near1 != null) + stack.Push(near1); + + if (near2 != null) + stack.Push(near2); + } + + return result; + } + + /// Finds the two nearest quadrants to the reference point. + private static void GetNearestChildrenWithElements + (Quad withinQuad, Vector2Int toPoint, out Quad firstNearest, out Quad secondNearest) + { + // Helpers + var min1 = float.MaxValue; + var min2 = float.MaxValue; + + // Defaults + firstNearest = null; + secondNearest = null; + + for (int i = 0; i < withinQuad._children.Length; i++) + { + var entry = withinQuad._children[i]; + if (entry.IsLeaf && !entry.HasElements) + continue; + + var dist = Vector2Int.Distance(entry.Bounds.Center, toPoint); + if (dist < min1) + { + // Transfer first nearest to second + min2 = min1; + secondNearest = firstNearest; + + // Assign new first quadrant + min1 = dist; + firstNearest = entry; + } + else if (dist < min2) + { + // Assign new second quadrant + min2 = dist; + secondNearest = entry; + } + } + } + + private bool Subdivide() + { + if (_rank < 2) + return false; + + var childRank = _rank - 1; + var childSize = Bounds.Size / 2; + var anchor = Bounds.BottomLeft; + + // Allocate child store + _children = new Quad[4]; + + // Helpers + var childIndex = 0; + var itemsSorted = 0; + + for (int x = 0; x < 2; x++) + { + for (int y = 0; y < 2; y++) + { + // Create child node + _children[childIndex] = new Quad + ( + bounds: new Bounds(anchor + new Vector2Int(x * childSize, y * childSize), childSize), + rank: childRank, + parent: this + ); + + // Insert items + itemsSorted += _elements.Count(item => _children[childIndex].Insert(item)); + + // Done + childIndex++; + } + } + + if (itemsSorted != _elements.Count) + { + // This error is for when nodes in this quad fail to + // be assigned to child quadrants during subdivision. + Debug.LogError("Quad failed to sort its elements during subdivision."); + return false; + } + + // Release items + _elements = null; + + // Done + return true; + } + + private static void MergeIfEmpty(Quad quad) + { + while (true) + { + if (quad.IsLeaf) + return; + + // Merge if all children are empty leaves + var merge = !quad._children.Any(child => !child.IsLeaf || child.HasElements); + if (merge) + { + // Merge + quad._children = null; + quad._elements = new List(AtomicCapacity); + + // Try to merge enclosing quad + if (quad._parent.TryGetTarget(out var parent)) + { + quad = parent; + continue; + } + } + + break; + } + } + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/Extensions/Gameboard/Quad.cs.meta b/Assets/ARDK/Extensions/Gameboard/Quad.cs.meta new file mode 100644 index 0000000..6e0d8bb --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/Quad.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: eada2b97c579b4bca8bf9ea16fef429e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Gameboard/SpatialTree.cs b/Assets/ARDK/Extensions/Gameboard/SpatialTree.cs new file mode 100644 index 0000000..ff3fc68 --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/SpatialTree.cs @@ -0,0 +1,224 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +using UnityEngine; + +namespace Niantic.ARDK.Extensions.Gameboard +{ + internal sealed partial class SpatialTree + { + // The rank of the top level quads + private readonly int _initialRank; + + // The size of each root quad + // Each root can store N amount of GridNodes, where N = size * size + private readonly int _rootSize; + private readonly int _halfSize; + + // Store for root quads. Each root is identified with a location sensitive hash. + private readonly Dictionary _quads = new Dictionary(); + + /// Creates a new spatial tree instance. + /// A spatial tree consists of a grid of quads, which themselves can subdivide. + /// @param approximateQuadSize Defines the size of a quad. The actual size will + /// be less than or equal to this number. + public SpatialTree(int approximateQuadSize) + { + _initialRank = (int)(Math.Log(approximateQuadSize) / Math.Log(2)); + _rootSize = (int)Mathf.Pow(2, _initialRank); + _halfSize = _rootSize / 2; + } + + /// Inserts the provided elements to the tree. + /// @param gridNodes Grid nodes to insert. + /// @returns Whether all nodes were inserted successfully. + public bool Insert(IEnumerable gridNodes) + { + bool success = true; + foreach (var gridNode in gridNodes) + { + var position = gridNode.Coordinates; + var key = GetKey(forCoordinates: position); + + // Get or create (root) quad for the position + Quad quad; + if (_quads.ContainsKey(key)) + { + quad = _quads[key]; + } + else + { + quad = new Quad(SnapToGrid(position), _initialRank); + _quads.Add(key, quad); + } + + // Insert node + success = success && quad.Insert(gridNode); + } + + return success; + } + + /// Removes the provided elements from the tree. + /// @param gridNodes Grid nodes to remove. + public HashSet Remove(IEnumerable gridNodes) + { + HashSet removedNodes = new HashSet(); + + foreach (var gridNode in gridNodes) + { + // Find root quad and remove node from it + var key = GetKey(forCoordinates: gridNode.Coordinates); + if (_quads.ContainsKey(key)) + { + bool removed = _quads[key].Remove(gridNode); + if (removed) + removedNodes.Add(gridNode.Coordinates); + } + } + + return removedNodes; + } + + /// Returns the grid node at the specified location if exists. + /// @param atPosition The location of the grid node. + /// @param result The element stored at the specified location. + /// @returns True, if the grid node could be located. + public bool GetElement(Vector2Int atPosition, out GridNode result) + { + var key = GetKey(atPosition); + if (!_quads.ContainsKey(key)) + { + result = default; + return false; + } + + return _quads[key].GetElement(atPosition, out result); + } + + public IEnumerable Query(Bounds withinBounds) + { + if (_quads.Count < 1) + return null; + + // Aggregate quads that overlap the specified bounds + var quads = + _quads.Select(entry => entry.Value) + .Where(quad => quad.Bounds.Intersects(withinBounds)); + + // Extract points within bounds + var result = new List(); + foreach (var entry in quads) + result.AddRange(entry.GetElements(withinBounds)); + + return result; + } + + public IEnumerable Query(Vector2Int neighboursTo) + { + if (_quads.Count < 1) + return null; + + // Find the quad enclosing the reference point + var key = GetKey(neighboursTo); + var source = _quads.ContainsKey(key) ? _quads[key] : null; + + // Find neighbours + var elements = source?.GetNeighbours(neighboursTo); + if (elements != null) return elements; + + // At this point, the reference is outside the mapped area. + // Find the closest quad to the reference point. + Quad nearest = FindNearestQuad(_quads.Values, neighboursTo); + + var nodes = nearest?.GetNeighbours(neighboursTo); + return nodes ?? new GridNode[0]; + } + + public void Clear() + { + _quads.Clear(); + } + + /// Returns a key for finding the appropriate quad for the specified tile. + private long GetKey(Vector2Int forCoordinates) + { + // Correct for 0-based indexing + int xCoordinate = forCoordinates.x > 0 ? forCoordinates.x : forCoordinates.x + 1; + int yCoordinate = forCoordinates.y > 0 ? forCoordinates.y : forCoordinates.y + 1; + + // Calculate indices on the quad grid. + int n = xCoordinate / _halfSize; + int m = yCoordinate / _halfSize; + int x = _halfSize * (n + n % 2) / _rootSize; + int y = _halfSize * (m + m % 2) / _rootSize; + + // Hash results + ulong a = (ulong)(x >= 0 ? 2 * (long)x : -2 * (long)x - 1); + ulong b = (ulong)(y >= 0 ? 2 * (long)y : -2 * (long)y - 1); + long c = (long)((a >= b ? a * a + a + b : a + b * b) / 2); + + return x < 0 && y < 0 || x >= 0 && y >= 0 ? c : -c - 1; + } + + /// Snaps the specified coordinates to the quad grid. + private Vector2Int SnapToGrid(Vector2Int position) + { + // Correct for 0-based indexing + int xCoordinate = position.x > 0 ? position.x : position.x + 1; + int yCoordinate = position.y > 0 ? position.y : position.y + 1; + + int n = xCoordinate / _halfSize; + int m = yCoordinate / _halfSize; + + return new Vector2Int(_halfSize * (n + n % 2), _halfSize * (m + m % 2)); + } + + private static Quad FindNearestQuad(IEnumerable candidates, Vector2Int reference) + { + var minDistance = float.MaxValue; + Quad nearest = null; + foreach (var current in candidates) + { + var distance = Vector2Int.Distance(current.Bounds.Center, reference); + if (distance < minDistance) + { + minDistance = distance; + nearest = current; + } + } + + return nearest; + } + + /// Visualizes the quad-tree in the editor's scene view. + /// @param setting The Gameboard's configuration. + public void DrawGizmos(ModelSettings settings) + { + var queue = new Queue(); + + // Draw spatial map + foreach (var quad in _quads.Values) + queue.Enqueue(quad); + + while (queue.Count > 0) + { + var quad = queue.Dequeue(); + + // Draw root quad + quad.Bounds.DrawGizmos(settings.TileSize, Color.yellow); + + if (!quad.IsLeaf) + { + var children = quad.GetChildren(); + foreach (var child in children) + queue.Enqueue(child); + } + } + } + } +} diff --git a/Assets/ARDK/Extensions/Gameboard/SpatialTree.cs.meta b/Assets/ARDK/Extensions/Gameboard/SpatialTree.cs.meta new file mode 100644 index 0000000..e6cade1 --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/SpatialTree.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a520094309554de9900aa8c71eb456f0 +timeCreated: 1627331796 \ No newline at end of file diff --git a/Assets/ARDK/Extensions/Gameboard/Surface.cs b/Assets/ARDK/Extensions/Gameboard/Surface.cs new file mode 100644 index 0000000..997a872 --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/Surface.cs @@ -0,0 +1,133 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.Collections.Generic; +using System.Linq; + +using Niantic.ARDK.Utilities.Collections; + +using UnityEngine; + +namespace Niantic.ARDK.Extensions.Gameboard +{ + /// Represents a subset on the grid with cells of approximately the same elevation. + internal sealed class Surface + { + private int Id { get; } + + /// Elevation of the grid. + public float Elevation { get; private set; } + + /// Whether this planes does not contain any valid elements on the grid. + public bool IsEmpty + { + get + { + return _elements.Count == 0; + } + } + + /// Internal container for the nodes that make up this plane. + private readonly HashSet _elements; + + /// Grid nodes that make up this plane (readonly). + public IEnumerable Elements + { + get + { + return _elements.AsArdkReadOnly(); + } + } + + public Surface(IEnumerable gridElements, int id) + { + _elements = new HashSet(gridElements); + Elevation = CalculateElevation(_elements); + + Id = id; + } + + public bool ContainsElement(GridNode gridCell) + { + return _elements.Contains(gridCell); + } + + /// Merges the other plane's grid elements to this plane. + public void Merge(Surface other) + { + // Union, but prefer to keep the shared cells of the new plane + _elements.ExceptWith(other._elements); + _elements.UnionWith(other._elements); + Elevation = CalculateElevation(_elements); + } + + public bool CanMerge(Surface other, float elevationTreshold) + { + var otherElements = new HashSet(other._elements); + otherElements.IntersectWith(_elements); + if (otherElements.Count == 0) + { + return false; + } + + var thisElements = new HashSet(_elements); + thisElements.IntersectWith(other._elements); + + var foreignElevation = CalculateElevation(otherElements); + return Mathf.Abs(foreignElevation - CalculateElevation(thisElements)) <= elevationTreshold && + Mathf.Abs(foreignElevation - Elevation) < elevationTreshold; + } + + public bool Overlaps(Surface other) + { + return _elements.Overlaps(other._elements); + } + + public void Except(Surface other) + { + _elements.ExceptWith(other._elements); + } + + public void Except(IEnumerable nodes) + { + _elements.ExceptWith(nodes); + } + + public void Intersect(IEnumerable nodes) + { + _elements.IntersectWith(nodes); + } + + public GridNode GetClosestElement(Vector2Int reference) + { + return _elements.Aggregate + ( + (closest, entry) => + Vector2Int.Distance + (entry.Coordinates, reference) < + Vector2Int.Distance(closest.Coordinates, reference) + ? entry + : closest + ); + } + + private static float CalculateElevation(IEnumerable nodes) + { + var groupElevation = 0.0f; + var groupElevationAvgCount = 0; + foreach (var entry in nodes) + { + // Standard deviation tells us the general flatness around this cell + // When calculating the elevation of the plane, + // flat areas contribute more to the combined value + var elevationWeight = Mathf.FloorToInt((0.1f - entry.Deviation) * 100); + groupElevation += entry.Elevation * elevationWeight; + groupElevationAvgCount += elevationWeight; + } + + // AVG elevation + groupElevation /= groupElevationAvgCount; + + return groupElevation; + } + } +} diff --git a/Assets/ARDK/Extensions/Gameboard/Surface.cs.meta b/Assets/ARDK/Extensions/Gameboard/Surface.cs.meta new file mode 100644 index 0000000..f6d8dca --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/Surface.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6bbfc0b4f7013402e9ca05d768829dda +timeCreated: 1602693728 \ No newline at end of file diff --git a/Assets/ARDK/Extensions/Gameboard/Utils.cs b/Assets/ARDK/Extensions/Gameboard/Utils.cs new file mode 100644 index 0000000..6d6f8cc --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/Utils.cs @@ -0,0 +1,261 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; + +using UnityEngine; + +namespace Niantic.ARDK.Extensions.Gameboard +{ + public static class Utils + { + /// Calculates the manhattan distance between two nodes. + internal static int ManhattanDistance(PathFindingNode from, PathFindingNode to) + { + return Math.Abs + (from.Coordinates.x - to.Coordinates.x) + + Math.Abs(from.Coordinates.y - to.Coordinates.y); + } + + /// Calculates the standard deviation of the provided sample. + internal static float CalculateStandardDeviation(IEnumerable samples) + { + var m = 0.0f; + var s = 0.0f; + var k = 1; + foreach (var value in samples) + { + var tmpM = m; + m += (value - tmpM) / k; + s += (value - tmpM) * (value - m); + k++; + } + + return Mathf.Sqrt(s / Mathf.Max(1, k - 1)); + } + + /// Fits a plane to best align with the specified set of points. + internal static void FastFitPlane + ( + Vector3[] points, + out Vector3 position, + out Vector3 normal + ) + { + position = default; + normal = default; + + var n = points.Length; + if (n < 3) + { + return; + } + + var sum = Vector3.zero; + for (var i = 0; i < points.Length; i++) + sum += points[i]; + + position = sum * (1.0f / n); + + var xx = 0.0f; + var xy = 0.0f; + var xz = 0.0f; + var yy = 0.0f; + var yz = 0.0f; + var zz = 0.0f; + + for (var i = 0; i < points.Length; i++) + { + var r = points[i] - position; + xx += r.x * r.x; + xy += r.x * r.y; + xz += r.x * r.z; + yy += r.y * r.y; + yz += r.y * r.z; + zz += r.z * r.z; + } + + xx /= n; + xy /= n; + xz /= n; + yy /= n; + yz /= n; + zz /= n; + + var weightedDir = Vector3.zero; + + { + var detX = yy * zz - yz * yz; + var axisDir = new Vector3 + ( + x: detX, + y: xz * yz - xy * zz, + z: xy * yz - xz * yy + ); + + var weight = detX * detX; + weightedDir += axisDir * weight; + } + + { + var detY = xx * zz - xz * xz; + var axisDir = new Vector3 + ( + x: xz * yz - xy * zz, + y: detY, + z: xy * xz - yz * xx + ); + + var weight = detY * detY; + weightedDir += axisDir * weight; + } + + { + var detZ = xx * yy - xy * xy; + var axisDir = new Vector3 + ( + x: xy * yz - xz * yy, + y: xy * xz - yz * xx, + z: detZ + ); + + var weight = detZ * detZ; + weightedDir += axisDir * weight; + } + + float num = Vector3.Magnitude(weightedDir); + normal = weightedDir / num; + } + + /// Insert a value into an IList{T} that is presumed to be already sorted such that sort + internal static void InsertIntoSortedList(this IList list, T value, Comparison comparison) + { + var startIndex = 0; + var endIndex = list.Count; + while (endIndex > startIndex) + { + var windowSize = endIndex - startIndex; + var middleIndex = startIndex + (windowSize / 2); + var middleValue = list[middleIndex]; + var compareToResult = comparison(middleValue, value); + if (compareToResult == 0) + { + list.Insert(middleIndex, value); + return; + } + + if (compareToResult < 0) + { + startIndex = middleIndex + 1; + } + else + { + endIndex = middleIndex; + } + } + list.Insert(startIndex, value); + } + + + /// Returns the 8 neighbouring tiles of the specified coordinate. + internal static IEnumerable GetNeighbours(Vector2Int vertex) + { + return new[] + { + new Vector2Int(vertex.x + 1, vertex.y), + new Vector2Int(vertex.x - 1, vertex.y), + new Vector2Int(vertex.x, vertex.y + 1), + new Vector2Int(vertex.x, vertex.y - 1), + new Vector2Int(vertex.x - 1, vertex.y + 1), + new Vector2Int(vertex.x + 1, vertex.y + 1), + new Vector2Int(vertex.x - 1, vertex.y - 1), + new Vector2Int(vertex.x + 1, vertex.y - 1) + }; + } + + /// Finds the closest node to the specified reference in candidates. + internal static bool GetNearestNode(IList candidates, Vector2Int reference, out GridNode nearestNode) + { + // Helpers + var minDistance = float.MaxValue; + var success = false; + + // Initialize result + nearestNode = default; + + if (candidates == null) + return false; + + // Find nearest + for (int i = 0; i < candidates.Count; i++) + { + var point = candidates[i]; + var distance = Vector2Int.Distance(point.Coordinates, reference); + + if (distance < minDistance) + { + // Found a candidate + success = true; + minDistance = distance; + nearestNode = point; + } + } + + return success; + } + + /// Converts a world position to grid coordinates. + internal static Vector2Int PositionToTile(Vector2 position, float tileSize) + { + return new Vector2Int + ( + Mathf.FloorToInt(position.x / tileSize), + Mathf.FloorToInt(position.y / tileSize) + ); + } + + /// Converts a world position to grid coordinates. + /// @param position Position to convert. + /// @param tileSize Metric size of each tile in the grid. + public static Vector2Int PositionToTile(Vector3 position, float tileSize) + { + return new Vector2Int + ( + Mathf.FloorToInt(position.x / tileSize), + Mathf.FloorToInt(position.z / tileSize) + ); + } + + /// Converts a grid coordinate to world position. + internal static Vector2 TileToPosition(Vector2Int tile, float tileSize) + { + var halfSize = tileSize / 2.0f; + return new Vector2 + (tile.x * tileSize + halfSize, tile.y * tileSize + halfSize); + } + + /// Converts a grid coordinate to world position. + internal static Vector3 TileToPosition(Vector2Int tile, float elevation, float tileSize) + { + var halfSize = tileSize / 2.0f; + return new Vector3 + ( + tile.x * tileSize + halfSize, + elevation, + tile.y * tileSize + halfSize + ); + } + + /// Converts a world position to a node on the Gameboard. + internal static GridNode PositionToGridNode(Vector3 worldPosition, float tileSize) + { + return new GridNode(PositionToTile(worldPosition, tileSize)); + } + + /// Converts a node on the Gameboard to its corresponding world position. + internal static Vector3 GridNodeToPosition(GridNode node, float tileSize) + { + return TileToPosition(node.Coordinates, node.Elevation, tileSize); + } + } +} diff --git a/Assets/ARDK/Extensions/Gameboard/Utils.cs.meta b/Assets/ARDK/Extensions/Gameboard/Utils.cs.meta new file mode 100644 index 0000000..d7cad30 --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/Utils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 57c0b93e51125447494a8308c7898391 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Gameboard/Visualiser.cs b/Assets/ARDK/Extensions/Gameboard/Visualiser.cs new file mode 100644 index 0000000..9019845 --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/Visualiser.cs @@ -0,0 +1,253 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.Collections.Generic; +using System.Linq; + +using UnityEngine; + +namespace Niantic.ARDK.Extensions.Gameboard +{ + internal sealed class Visualiser + { + private IGameboard _gameboard; + private GameboardModel _model; + + private List _pathDebugObjects; + private List _unusedPathDebugObjects; + private LineRenderer _lineRenderer; + + private GameObject _visualRoot; + private MeshFilter _meshFilter = new MeshFilter(); + + private bool _active; + + public Visualiser(IGameboard gameboard, GameboardModel model, bool active) + { + _model = model; + _gameboard = gameboard; + + if (active) + CreateNewDebugObjects(); + + _active = active; + + if (active) + _gameboard.GameboardUpdated += OnGameboardSurfaceUpdate; + } + + public void Destroy() + { + if (_pathDebugObjects == null) + return; + + foreach (var obj in _pathDebugObjects) + GameObject.Destroy(obj); + + _pathDebugObjects.Clear(); + + foreach (var obj in _unusedPathDebugObjects) + GameObject.Destroy(obj); + + _unusedPathDebugObjects.Clear(); + + if (_meshFilter != null) + GameObject.Destroy(_meshFilter.gameObject); + GameObject.Destroy(_visualRoot); + } + + public void SetActive(bool active) + { + _active = active; + + if (_active) + { + if (_meshFilter == null) + CreateNewDebugObjects(); + + _gameboard.GameboardUpdated += OnGameboardSurfaceUpdate; + UpdateDebugMesh(_model.Surfaces, _meshFilter.mesh); + } + else + { + _gameboard.GameboardUpdated -= OnGameboardSurfaceUpdate; + _meshFilter.mesh.Clear(); + } + + _lineRenderer.enabled = _active; + + foreach (var sphere in _pathDebugObjects) + sphere.SetActive(_active); + } + + private void OnGameboardSurfaceUpdate(GameboardUpdatedArgs args) + { + if (args.PruneOrClear) + { + _meshFilter.mesh.Clear(); + return; + } + + UpdateDebugMesh(_model.Surfaces, _meshFilter.mesh); + } + + private void CreateNewDebugObjects() + { + _visualRoot = new GameObject(); + _visualRoot.name = "Gameboard Visualisation"; + _visualRoot.transform.position = Vector3.zero; + + _pathDebugObjects = new List(); + _unusedPathDebugObjects = new List(); + + _lineRenderer = _visualRoot.AddComponent(); + _lineRenderer.widthCurve = new AnimationCurve(new Keyframe(0, 0.1f)); + _lineRenderer.material.color = Color.black; + _lineRenderer.positionCount = 0; + + GameObject debugMeshGameObject = new GameObject(); + debugMeshGameObject.transform.SetParent(_visualRoot.transform, false); + debugMeshGameObject.name = "GameboardDebug"; + MeshRenderer renderer = debugMeshGameObject.AddComponent(); + renderer.material.color = Color.green; + renderer.material.shader = Shader.Find("Unlit/Color"); + _meshFilter = debugMeshGameObject.AddComponent(); + _meshFilter.mesh.MarkDynamic(); + } + + #region TilesDrawing + + public void UpdateDebugMesh(List surfaces, Mesh mesh) + { + float offset = 0.002f; + + var vertices = new List(); + var triangles = new List(); + var vIndex = 0; + var halfSize = _gameboard.Settings.TileSize / 2.0f; + foreach (var surface in surfaces) + { + foreach (var center in surface.Elements.Select + (node => Utils.TileToPosition(node.Coordinates, surface.Elevation, _gameboard.Settings.TileSize))) + { + // Vertices + vertices.Add + (center + new Vector3(-halfSize + offset, 0.0f, -halfSize + offset)); + + vertices.Add(center + new Vector3(halfSize - offset, 0.0f, -halfSize + offset)); + vertices.Add(center + new Vector3(halfSize - offset, 0.0f, halfSize - offset)); + vertices.Add(center + new Vector3(-halfSize + offset, 0.0f, halfSize - offset)); + + + // Indices + triangles.Add(vIndex + 2); + triangles.Add(vIndex + 1); + triangles.Add(vIndex); + + triangles.Add(vIndex); + triangles.Add(vIndex + 3); + triangles.Add(vIndex + 2); + + vIndex += 4; + } + } + + mesh.Clear(); + if (vertices.Count >= 4) + { + mesh.vertices = vertices.ToArray(); + mesh.triangles = triangles.ToArray(); + mesh.UploadMeshData(markNoLongerReadable: false); + } + } + + #endregion + + #region PathDrawing + + private void DrawLine(List path) + { + _lineRenderer.positionCount = path.Count; + Vector3[] positions = new Vector3[path.Count]; + for (int index = 0; index < path.Count; index++) + { + positions[index] = path[index].WorldPosition; + } + _lineRenderer.SetPositions(positions); + } + + private GameObject CreateSphere(Vector3 position) + { + GameObject waypoint = GameObject.CreatePrimitive(PrimitiveType.Sphere); + Object.Destroy(waypoint.GetComponent()); + + waypoint.transform.localScale = _gameboard.Settings.TileSize * 0.5f * Vector3.one; + waypoint.transform.position = position; + waypoint.transform.SetParent(_visualRoot.transform); + + return waypoint; + } + + private void MoveSphereToCache(GameObject unusedSphere) + { + unusedSphere.transform.position = new Vector3(int.MaxValue, int.MaxValue, int.MaxValue); + _unusedPathDebugObjects.Add(unusedSphere); + _pathDebugObjects.RemoveAt(_pathDebugObjects.Count-1); + } + + private void MoveSphereFromCache(GameObject usedSphere, Vector3 position) + { + usedSphere.transform.position = position; + _unusedPathDebugObjects.RemoveAt(0); + _pathDebugObjects.Add(usedSphere); + } + + public void DrawPath(Path path) + { + if (path.PathStatus == Path.Status.PathInvalid) + { + while (_pathDebugObjects.Count > 0) + { + MoveSphereToCache(_pathDebugObjects.Last()); + } + + _lineRenderer.positionCount = 0; + return; + } + + DrawLine(path.Waypoints); + + for (int index = 0; index < path.Waypoints.Count; index++) + { + if (index < _pathDebugObjects.Count) + { + _pathDebugObjects[index].transform.position = path.Waypoints[index].WorldPosition; + } + else + { + if (_unusedPathDebugObjects.Count > 0) + { + GameObject waypoint = _unusedPathDebugObjects[0]; + MoveSphereFromCache(waypoint, path.Waypoints[index].WorldPosition); + } + else + { + GameObject waypointDebugSphere = CreateSphere(path.Waypoints[index].WorldPosition); + _pathDebugObjects.Add(waypointDebugSphere); + } + } + } + + if (path.Waypoints.Count < _pathDebugObjects.Count) + { + for (int index = _pathDebugObjects.Count - 1; index > path.Waypoints.Count - 1; index--) + { + GameObject unusedWaypoint = _pathDebugObjects[index]; + MoveSphereToCache(unusedWaypoint); + } + } + } + + + #endregion + } +} diff --git a/Assets/ARDK/Extensions/Gameboard/Visualiser.cs.meta b/Assets/ARDK/Extensions/Gameboard/Visualiser.cs.meta new file mode 100644 index 0000000..7f298d2 --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/Visualiser.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 848d5aba8f69046f0b0685f7d99ff316 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Gameboard/Waypoint.cs b/Assets/ARDK/Extensions/Gameboard/Waypoint.cs new file mode 100644 index 0000000..ff66df2 --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/Waypoint.cs @@ -0,0 +1,34 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using UnityEngine; + +namespace Niantic.ARDK.Extensions.Gameboard +{ + public readonly struct Waypoint + { + /// The type of movement of a waypoint + public enum MovementType + { + /// Walk node. + Walk = 0, + + /// The first node of a new surface on the path. + SurfaceEntry = 1 + } + + /// The position of this point in world coordinates. + public readonly Vector3 WorldPosition; + + /// The type of movement of this waypoint. + public readonly MovementType Type; + + public readonly Vector2Int Coordinates; + + public Waypoint(Vector3 worldPosition, MovementType type, Vector2Int coordinates) + { + WorldPosition = worldPosition; + Type = type; + Coordinates = coordinates; + } + } +} diff --git a/Assets/ARDK/Extensions/Gameboard/Waypoint.cs.meta b/Assets/ARDK/Extensions/Gameboard/Waypoint.cs.meta new file mode 100644 index 0000000..08e9707 --- /dev/null +++ b/Assets/ARDK/Extensions/Gameboard/Waypoint.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7849c49f67deb45cf8636b27d488801d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/MapVisualization.meta b/Assets/ARDK/Extensions/MapVisualization.meta new file mode 100644 index 0000000..3a658a4 --- /dev/null +++ b/Assets/ARDK/Extensions/MapVisualization.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c15dd93b6c17e409f9bb34c11b206c88 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/MapVisualization/ARMapController.cs b/Assets/ARDK/Extensions/MapVisualization/ARMapController.cs new file mode 100644 index 0000000..2f4c1f8 --- /dev/null +++ b/Assets/ARDK/Extensions/MapVisualization/ARMapController.cs @@ -0,0 +1,40 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using Niantic.ARDK.AR.SLAM; +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.Extensions.MapVisualization { + /// Controller for map visualization prefab for AR localization + public class ARMapController : MonoBehaviour, IMapVisualizationController { + private MeshRenderer _meshRenderer = null; + private Color _color; + private bool _visibility = true; + + /// + public void VisualizeMap(ARDK.AR.SLAM.IARMap map) { + if (_meshRenderer == null) { + _meshRenderer = GetComponent(); + _color = Random.ColorHSV(0.5f, 1f, 0.5f, 1f, 0.5f, 1f, 1f, 1f); + } + + transform.position = map.Transform.ToPosition(); + transform.rotation = map.Transform.ToRotation(); + transform.localScale = new Vector3(0.05f,0.05f,0.05f); + _meshRenderer.material.color = _color; + } + + /// + public void SetVisibility(bool visibility) { + if (_visibility == visibility) { + // Visibility did not change, do nothing + return; + } + + _visibility = visibility; + transform.gameObject.SetActive(_visibility); + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/Extensions/MapVisualization/ARMapController.cs.meta b/Assets/ARDK/Extensions/MapVisualization/ARMapController.cs.meta new file mode 100644 index 0000000..b13a1ae --- /dev/null +++ b/Assets/ARDK/Extensions/MapVisualization/ARMapController.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cf58b2ff8ea6e44e8b1db0cc81fcef7a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/MapVisualization/ARMapPrefab.prefab b/Assets/ARDK/Extensions/MapVisualization/ARMapPrefab.prefab new file mode 100644 index 0000000..e678063 --- /dev/null +++ b/Assets/ARDK/Extensions/MapVisualization/ARMapPrefab.prefab @@ -0,0 +1,109 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1001 &100100000 +Prefab: + m_ObjectHideFlags: 1 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: [] + m_RemovedComponents: [] + m_ParentPrefab: {fileID: 0} + m_RootGameObject: {fileID: 1786189840560220} + m_IsPrefabParent: 1 +--- !u!1 &1786189840560220 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 4353478769245966} + - component: {fileID: 33132115701999894} + - component: {fileID: 135102982351069994} + - component: {fileID: 23339986533373938} + - component: {fileID: 114670359748406276} + m_Layer: 0 + m_Name: ARMapPrefab + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4353478769245966 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1786189840560220} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0.05, y: 0.05, z: 0.05} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!23 &23339986533373938 +MeshRenderer: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1786189840560220} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_Materials: + - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!33 &33132115701999894 +MeshFilter: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1786189840560220} + m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} +--- !u!114 &114670359748406276 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1786189840560220} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: cf58b2ff8ea6e44e8b1db0cc81fcef7a, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!135 &135102982351069994 +SphereCollider: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1786189840560220} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Radius: 0.5 + m_Center: {x: 0, y: 0, z: 0} diff --git a/Assets/ARDK/Extensions/MapVisualization/ARMapPrefab.prefab.meta b/Assets/ARDK/Extensions/MapVisualization/ARMapPrefab.prefab.meta new file mode 100644 index 0000000..04982c2 --- /dev/null +++ b/Assets/ARDK/Extensions/MapVisualization/ARMapPrefab.prefab.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a69a384c1d25d432da08e87e0674c9bd +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/MapVisualization/ARMapVisualizationRenderer.cs b/Assets/ARDK/Extensions/MapVisualization/ARMapVisualizationRenderer.cs new file mode 100644 index 0000000..bcd96cd --- /dev/null +++ b/Assets/ARDK/Extensions/MapVisualization/ARMapVisualizationRenderer.cs @@ -0,0 +1,163 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.ARSessionEventArgs; +using Niantic.ARDK.AR.Networking; +using Niantic.ARDK.AR.Networking.ARNetworkingEventArgs; +using Niantic.ARDK.AR.SLAM; +using Niantic.ARDK.Networking; +using Niantic.ARDK.Networking.MultipeerNetworkingEventArgs; + +using UnityEngine; + +namespace Niantic.ARDK.Extensions.MapVisualization +{ + /// @brief Helper class that visualizes scanned maps used for AR localization. + /// + /// Listens for new AR localization maps and instantiates visualization prefabs + /// for each new map. To use, add an instance to your scene. + /// Map visualizations are only valid when the AR localization is + /// in a stable state where + /// [PeerState](@ref Niantic.ARDK.AR.Networking.PeerState) is + /// ```Stable``` or ```Stabilizing```. + public class ARMapVisualizationRenderer: + MonoBehaviour + { + /// The object to spawn and manage when a map is detected. + public ARMapController ARMapPrefab; + + private Dictionary _mapLookup = + new Dictionary(); + + private bool _mapVisibility = false; + private IPeer _self; + + private IARSession _session; + private IARNetworking _arNetworking; + private IMultipeerNetworking _multipeerNetworking; + + private void Awake() + { + // Listen for maps + ARSessionFactory.SessionInitialized += _SessionInitialized; + + ARNetworkingFactory.ARNetworkingInitialized += _NetworkingInitialized; + MultipeerNetworkingFactory.NetworkingInitialized += _MultipeerNetworkingInitialized; + } + + private void OnDestroy() + { + ARSessionFactory.SessionInitialized -= _SessionInitialized; + _RemoveSessionEvents(_session); + + ARNetworkingFactory.ARNetworkingInitialized -= _NetworkingInitialized; + + var oldNetworking = _arNetworking; + if (oldNetworking != null) + oldNetworking.PeerStateReceived -= _PeerStateReceived; + + var oldMultipeerNetworking = _multipeerNetworking; + if (oldMultipeerNetworking != null) + oldMultipeerNetworking.Connected -= _MultipeerNetworkingConnected; + } + + private void _RemoveSessionEvents(IARSession session) + { + if (session == null) + return; + + session.MapsAdded -= OnAnyMapsAdded; + session.MapsUpdated -= OnAnyMapsUpdated; + session.Deinitialized -= SessionDeinitialized; + } + + private void _SessionInitialized(AnyARSessionInitializedArgs args) + { + _session = args.Session; + _session.MapsAdded += OnAnyMapsAdded; + _session.MapsUpdated += OnAnyMapsUpdated; + _session.Deinitialized += SessionDeinitialized; + } + + private void SessionDeinitialized(ARSessionDeinitializedArgs args) + { + foreach (var map in _mapLookup.Values) + { + var mapBehaviour = map as ARMapController; + if (mapBehaviour != null) + Destroy(mapBehaviour.gameObject); + } + + _mapLookup.Clear(); + _mapVisibility = false; + _self = null; + _session = null; + } + + private void _NetworkingInitialized(AnyARNetworkingInitializedArgs args) + { + var oldNetworking = _arNetworking; + if (oldNetworking != null) + oldNetworking.PeerStateReceived -= _PeerStateReceived; + + _arNetworking = args.ARNetworking; + _arNetworking.PeerStateReceived += _PeerStateReceived; + } + + private void _MultipeerNetworkingInitialized(AnyMultipeerNetworkingInitializedArgs args) + { + var oldMultipeerNetworking = _multipeerNetworking; + if (oldMultipeerNetworking != null) + oldMultipeerNetworking.Connected -= _MultipeerNetworkingConnected; + + var multipeerNetworking = args.Networking; + _multipeerNetworking = multipeerNetworking; + multipeerNetworking.Connected += _MultipeerNetworkingConnected; + } + + private void OnAnyMapsAdded(MapsArgs args) + { + foreach (var map in args.Maps) + { + // Spawn a new map prefab + _mapLookup.Add(map.Identifier, Instantiate(ARMapPrefab)); + RefreshMap(map, _mapVisibility); + } + } + + private void OnAnyMapsUpdated(MapsArgs args) + { + foreach (var map in args.Maps) + { + // Update existing map prefab + RefreshMap(map, _mapVisibility); + } + } + + private void _PeerStateReceived(PeerStateReceivedArgs args) + { + if (args.Peer.Identifier != _self.Identifier || args.State != PeerState.Stable) + return; + + // Show all maps + _mapVisibility = true; + foreach (var mapLookup in _mapLookup) + mapLookup.Value.SetVisibility(_mapVisibility); + } + + private void _MultipeerNetworkingConnected(ConnectedArgs args) + { + _self = args.Self; + } + + private void RefreshMap(IARMap map, bool visibility) + { + var mapVisualizationController = _mapLookup[map.Identifier]; + mapVisualizationController.VisualizeMap(map); + mapVisualizationController.SetVisibility(visibility); + } + } +} diff --git a/Assets/ARDK/Extensions/MapVisualization/ARMapVisualizationRenderer.cs.meta b/Assets/ARDK/Extensions/MapVisualization/ARMapVisualizationRenderer.cs.meta new file mode 100644 index 0000000..ad81f98 --- /dev/null +++ b/Assets/ARDK/Extensions/MapVisualization/ARMapVisualizationRenderer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 79b292c3889d7422493f164cbebb50e9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/MapVisualization/ARMapVisualizationRenderer.prefab b/Assets/ARDK/Extensions/MapVisualization/ARMapVisualizationRenderer.prefab new file mode 100644 index 0000000..ab36853 --- /dev/null +++ b/Assets/ARDK/Extensions/MapVisualization/ARMapVisualizationRenderer.prefab @@ -0,0 +1,55 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1001 &100100000 +Prefab: + m_ObjectHideFlags: 1 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: [] + m_RemovedComponents: [] + m_ParentPrefab: {fileID: 0} + m_RootGameObject: {fileID: 1954499129559468} + m_IsPrefabParent: 1 +--- !u!1 &1954499129559468 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 4469971619959684} + - component: {fileID: 114182683236899166} + m_Layer: 0 + m_Name: ARMapVisualizationRenderer + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4469971619959684 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1954499129559468} + m_LocalRotation: {x: 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} +--- !u!114 &114182683236899166 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1954499129559468} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 79b292c3889d7422493f164cbebb50e9, type: 3} + m_Name: + m_EditorClassIdentifier: + ARMapPrefab: {fileID: 114670359748406276, guid: a69a384c1d25d432da08e87e0674c9bd, + type: 2} diff --git a/Assets/ARDK/Extensions/MapVisualization/ARMapVisualizationRenderer.prefab.meta b/Assets/ARDK/Extensions/MapVisualization/ARMapVisualizationRenderer.prefab.meta new file mode 100644 index 0000000..9a2690b --- /dev/null +++ b/Assets/ARDK/Extensions/MapVisualization/ARMapVisualizationRenderer.prefab.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1317ae0933d8e4a1798c6426f600fcad +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/MapVisualization/IMapVisualizationController.cs b/Assets/ARDK/Extensions/MapVisualization/IMapVisualizationController.cs new file mode 100644 index 0000000..89ebc0e --- /dev/null +++ b/Assets/ARDK/Extensions/MapVisualization/IMapVisualizationController.cs @@ -0,0 +1,21 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using Niantic.ARDK.AR.SLAM; +using UnityEngine.Rendering; + +namespace Niantic.ARDK.Extensions.MapVisualization { + /// @brief Controller for map visualization + public interface IMapVisualizationController { + /// + /// Set the map that needs to be visualized + /// + void VisualizeMap(IARMap _map); + + /// + /// If true, shows the map. Else hides the map. + /// + void SetVisibility(bool visibility); + } + +} \ No newline at end of file diff --git a/Assets/ARDK/Extensions/MapVisualization/IMapVisualizationController.cs.meta b/Assets/ARDK/Extensions/MapVisualization/IMapVisualizationController.cs.meta new file mode 100644 index 0000000..e63889c --- /dev/null +++ b/Assets/ARDK/Extensions/MapVisualization/IMapVisualizationController.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2a3cc0f0b99714aa0a82f8b76b7d5992 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/MarkerSync.meta b/Assets/ARDK/Extensions/MarkerSync.meta new file mode 100644 index 0000000..029d0fd --- /dev/null +++ b/Assets/ARDK/Extensions/MarkerSync.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e7fd648517b1e455c82497fc8f37a952 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/MarkerSync/BarcodeDisplay.cs b/Assets/ARDK/Extensions/MarkerSync/BarcodeDisplay.cs new file mode 100644 index 0000000..7174ffd --- /dev/null +++ b/Assets/ARDK/Extensions/MarkerSync/BarcodeDisplay.cs @@ -0,0 +1,191 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Utilities.Logging; +using Niantic.ARDK.Utilities.Marker; +using Niantic.ARDK.Utilities.QR; +using UnityEngine; +using UnityEngine.Serialization; +using UnityEngine.UI; +using ZXing; + +namespace Niantic.ARDK.Extensions.MarkerSync +{ + /// @note This is part of an experimental feature that is not advised to be used in release builds. + public class BarcodeDisplay : MonoBehaviour + { + [FormerlySerializedAs("_image")] + [SerializeField] + [Tooltip("The image component to render the generated barcode to. It should be square.")] + private RawImage _barcodeImage = null; + + [SerializeField] + [Tooltip("[Optional] The image component for displaying a border around the generated barcode. It should be square and larger than the BarcodeImage component.")] + private RawImage _borderImage = null; + + [SerializeField] + [Tooltip("[Optional] The image component for hiding the view behind the barcode")] + private RawImage _backgroundImage = null; + + [SerializeField] + private BarcodeFormat _format = BarcodeFormat.QR_CODE; + + /// The image component to render the generated barcode to. It should be square. + public RawImage BarcodeImage + { + get => _barcodeImage; + set => _barcodeImage = value; + } + + /// Optional image component to render the barcode image's border to. It should be + /// square and larger than the BarcodeImage component. + public RawImage BorderImage + { + get => _borderImage; + set => _borderImage = value; + } + + /// Optional image component that is enabled when the BarcodeImage is displayed to hide other + /// components on the screen. It should be behind the BarcodeImage component. + public RawImage BackgroundImage + { + get => _backgroundImage; + set => _backgroundImage = value; + } + + /// The screenspace position of the BarcodeImage. + public Vector2 Center { get; private set; } + + /// The screenspace positions of the generated barcode's borders. + /// The returned array of 4 vertices is clockwise, starting from the bottom left. + public Vector2[] Points { get; private set; } + + private bool _generatedCode; + private bool _isShowing; + + private void Awake() + { + if (_barcodeImage == null) + { + ARLog._Error("BarcodeDisplay requires a RawImage component to be assigned."); + return; + } + + if (_barcodeImage.canvas.renderMode != RenderMode.ScreenSpaceOverlay) + { + // Canvas must be in ScreenSpaceOverlay Source for pixel positions to be correct + ARLog._Error("BarcodeDisplay requires the image be displayed on a ScreenSpaceOverlay canvas."); + return; + } + + SetPixelPositions(); + Hide(true); + } + + private void SetPixelPositions() + { + var rectPosition = _barcodeImage.rectTransform.position; + + // Todo: Get working for different anchors and offsets + Center = new Vector2(rectPosition.x, rectPosition.y); + Points = new Vector2[4]; + } + + public void Show(bool force = false) + { + if (!_generatedCode) + { + ARLog._Error("Must generate the barcode before showing."); + return; + } + + if (_isShowing && !force) { return;} + + ARLog._Debug("Show BarcodeDisplay"); + ToggleComponents(true); + } + + public void Hide(bool force = false) + { + if (!_isShowing && !force) { return; } + + ARLog._Debug("Hide BarcodeDisplay"); + ToggleComponents(false); + } + + private void ToggleComponents(bool isEnabled) + { + _isShowing = isEnabled; + + if (_barcodeImage != null) + { + _barcodeImage.enabled = isEnabled; + } + + if (_borderImage != null) + { + _borderImage.enabled = isEnabled; + } + + if (_backgroundImage != null) + { + _backgroundImage.enabled = isEnabled; + } + } + + public ZXingMarkerGenerator.MarkerGenerationResult GenerateBarcode + ( + MarkerMetadata info, + bool showAfterGenerating = false + ) + { + _generatedCode = true; + + var dimensions = _barcodeImage.rectTransform.sizeDelta; + + var width = (int) dimensions.x; + var height = (int) dimensions.y; + var generatorResult = ZXingMarkerGenerator.GenerateBarcode + ( + info, + _format, + width, + height + ); + + // Parse and save corrected point positions + var parser = new ZXingBarcodeParser(); + + IParserResult parserResult; + var parserSuccess = parser.Decode + ( + generatorResult.RawPixels, + width, + height, + out parserResult + ); + + if (parserSuccess) + { + var translation = new Vector2(Center.x - (width / 2), Center.y - (height / 2)); + for (var i = 0; i < 4; i++) + { + Points[i] = parserResult.DetectedPoints[i] + translation; + } + } + else + { + ARLog._Error("Error trying to generate barcode texture."); + return null; + } + + // Setup the RawImage + _barcodeImage.texture = generatorResult.Texture; + + if (showAfterGenerating) { + Show(); + } + + return generatorResult; + } + } +} diff --git a/Assets/ARDK/Extensions/MarkerSync/BarcodeDisplay.cs.meta b/Assets/ARDK/Extensions/MarkerSync/BarcodeDisplay.cs.meta new file mode 100644 index 0000000..701f93e --- /dev/null +++ b/Assets/ARDK/Extensions/MarkerSync/BarcodeDisplay.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2db1fbbee84014ef4bf4d564e2c3d251 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Meshing.meta b/Assets/ARDK/Extensions/Meshing.meta new file mode 100644 index 0000000..e498645 --- /dev/null +++ b/Assets/ARDK/Extensions/Meshing.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7bf738719bcd48329b2fd7f8b463f61c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Meshing/ARMesh.prefab b/Assets/ARDK/Extensions/Meshing/ARMesh.prefab new file mode 100644 index 0000000..5309eea --- /dev/null +++ b/Assets/ARDK/Extensions/Meshing/ARMesh.prefab @@ -0,0 +1,57 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &4544129020768840140 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4544129020768840141} + - component: {fileID: 7963815754292762357} + m_Layer: 0 + m_Name: ARMesh + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4544129020768840141 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4544129020768840140} + m_LocalRotation: {x: 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} +--- !u!114 &7963815754292762357 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4544129020768840140} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: e03b458a9fbbf4cc18d8fd737e2a215e, type: 3} + m_Name: + m_EditorClassIdentifier: + _manageUsingUnityLifecycle: 1 + _targetFrameRate: 20 + _meshingRadius: 0 + _targetBlockSize: 1.4 + _parseMeshData: 1 + _generateUnityMeshes: 1 + _meshPrefab: {fileID: 2988715159741781419, guid: b79f4734d3e2462186a55d546e80cfb4, + type: 3} + _meshRoot: {fileID: 4544129020768840140} + _colliderUpdateThrottle: 10 + _useInvisibleMaterial: 0 + _invisibleMaterial: {fileID: 2100000, guid: 4d00d51d9ad64916abef2551d151e0ab, type: 2} diff --git a/Assets/ARDK/Extensions/Meshing/ARMesh.prefab.meta b/Assets/ARDK/Extensions/Meshing/ARMesh.prefab.meta new file mode 100644 index 0000000..7ec09ad --- /dev/null +++ b/Assets/ARDK/Extensions/Meshing/ARMesh.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 9f82ecc5afc3c4c2695d9cf37d46f25c +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Meshing/ARMeshManager.cs b/Assets/ARDK/Extensions/Meshing/ARMeshManager.cs new file mode 100644 index 0000000..5e99014 --- /dev/null +++ b/Assets/ARDK/Extensions/Meshing/ARMeshManager.cs @@ -0,0 +1,421 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.Configuration; +using Niantic.ARDK.AR.Mesh; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Collections; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; + +namespace Niantic.ARDK.Extensions.Meshing +{ + /// This helper can be placed in a scene to easily add environment meshes. + /// It reads meshing output from the ARSession, and instantiates mesh prefabs loaded with + /// components and materials for the desired behavior and rendering. + /// Mesh visibility can be toggled on and off, using a depth mask material for occlusion effect. + /// + /// OnEnable/EnableFeatures: + /// If an ARSession is running, meshing will be enabled and the ARSession will be re-run. + /// Else, the next run ARSession will have meshing enabled. + /// OnDisable/DisableFeatures: + /// If an ARSession is running, meshing will be disabled and the ARSession will be re-run. + /// Else, the next run ARSession will have meshing disabled. + public class ARMeshManager: ARSessionListener + { + [Header("AR Configuration Properties")] + [SerializeField] + [Tooltip("Target number of times per second to run the mesh update routine.")] + private uint _targetFrameRate = 20; + + [SerializeField] + [Tooltip("Target size of a mesh block in meters")] + private float _targetBlockSize = 1.4f; + + [SerializeField] + [Tooltip("Radius in meters of the meshed surface around the player. 0 means 'Infinity'")] + private float _meshingRadius = 0; + + [Header("Mesh Generation Settings")] + [SerializeField] + [Tooltip("When true, a Unity mesh will be instantiated and updated for each mesh block.")] + private bool _generateUnityMeshes; + + /// This GameObject requires a MeshFilter component, and will update a MeshCollider component if + /// able. A MeshRenderer component is optional, but required for the SetUseInvisibleMaterial method. + [SerializeField] + [Tooltip("The GameObject to instantiate and update for each mesh block.")] + private GameObject _meshPrefab; + + [SerializeField] + [Tooltip( + "Parent of every block (piece of mesh). If empty, this is assigned to the component's " + + "GameObject in Initialize()." + )] + private GameObject _meshRoot; + + /// A value of zero or lower means the MeshCollider updates every time. + /// A throttle is sometimes needed because MeshCollider updates are a lot more expensive than + /// MeshRenderer updates. + [SerializeField] + [Tooltip("The number of mesh updates to skip between two consecutive MeshCollider updates.")] + private int _colliderUpdateThrottle = 10; + + [Header("Mesh Visibility Settings")] + [SerializeField] + [Tooltip( + "When true, mesh blocks are rendered using InvisibleMaterial instead of the prefab's " + + "default material." + )] + private bool _useInvisibleMaterial = false; + + [SerializeField] + [Tooltip( + "(Optional) Used as a substitution material when the mesh is hidden (a depth mask " + + "material should typically be used here)." + )] + private Material _invisibleMaterial; + + /// The value specifying the how many times the meshing routine + /// should target running per second. + public uint TargetFrameRate + { + get { return _targetFrameRate; } + set + { + if (value != _targetFrameRate) + { + _targetFrameRate = value; + RaiseConfigurationChanged(); + } + } + } + + /// The value specifying the target size of a mesh block in meters + public float TargetBlockSize + { + get { return _targetBlockSize; } + set + { + if (!Mathf.Approximately(_targetBlockSize, value)) + { + _targetBlockSize = value; + RaiseConfigurationChanged(); + } + } + } + + /// The value specifying the radius, in meters, of the meshed surface around the player. + /// @note A value of 0 represents 'Infinity' + public float MeshingRadius + { + get { return _meshingRadius; } + set + { + if (value > 0 && value < 5) + { + ARLog._Error(MeshingRadiusError); + return; + } + + if (!Mathf.Approximately(_meshingRadius, value)) + { + _meshingRadius = value; + RaiseConfigurationChanged(); + } + } + } + + /// When false, mesh block GameObjects will not be updated + /// (a running ARSession will still surface mesh updates). + public bool GenerateUnityMeshes + { + get { return _generateUnityMeshes; } + set { _generateUnityMeshes = value; } + } + + /// The prefab to instantiate and update for each mesh block. + /// @note + /// This GameObject requires a MeshFilter component, and will update a MeshCollider + /// component if able. A MeshRenderer component is optional, but required for the + /// SetUseInvisibleMaterial method. + public GameObject MeshPrefab + { + get { return _meshPrefab; } + set + { + if (_generator != null) + { + ARLog._Error + ( + "MeshPrefab value cannot be changed after an ARSession has already been initialized." + ); + } + else + { + _meshPrefab = value; + } + } + } + + /// Parent of every block (piece of mesh). If empty, this is assigned to this component's + /// GameObject when initialized. + public GameObject MeshRoot + { + get { return _meshRoot; } + set + { + if (_generator != null) + { + ARLog._Error + ( + "MeshPrefab value cannot be changed after an ARSession has already been initialized." + ); + } + else + { + _meshRoot = value; + } + } + } + + /// False if the mesh objects are visible (i.e. it renders using the prefab's default material) + /// and true if the mesh objects are hidden (i.e. it uses the invisible material). + public bool UseInvisibleMaterial + { + get { return _useInvisibleMaterial; } + set { SetUseInvisibleMaterial(value); } + } + + /// Called when all mesh blocks have been updated with info from the the latest mesh update. + public event ArdkEventHandler MeshObjectsUpdated; + + /// Called when all mesh blocks have been cleared. + public event ArdkEventHandler MeshObjectsCleared; + + private IARMesh ARMesh + { + get + { + if (ARSession != null) + return ARSession.Mesh; + + return null; + } + } + + // Used to track when the Inspector-public variables are changed in OnValidate + private uint _prevTargetFrameRate; + private float _prevTargetBlockSize; + private float _prevMeshingRadius; + + private bool _clearMeshOnRerun = false; + + private MeshObjectsGenerator _generator; + private const string MeshingRadiusError = + "The smallest meshing radius possible is 5 meters. Set the value to 0 for an infinite radius."; + + protected override void InitializeImpl() + { + base.InitializeImpl(); + + if (!_meshRoot) + _meshRoot = gameObject; + + if (!_meshPrefab) + { + ARLog._Warn("No mesh prefab set on the ARMeshManager. No mesh blocks will be generated."); + return; + } + } + + protected override void DeinitializeImpl() + { + ClearMeshObjects(); + + base.DeinitializeImpl(); + + _generator?.Clear(); + } + + protected override void EnableFeaturesImpl() + { + base.EnableFeaturesImpl(); + + _prevTargetFrameRate = _targetFrameRate; + _prevTargetBlockSize = _targetBlockSize; + _prevMeshingRadius = _meshingRadius; + RaiseConfigurationChanged(); + } + + protected override void DisableFeaturesImpl() + { + base.DisableFeaturesImpl(); + RaiseConfigurationChanged(); + } + + protected override void ListenToSession() + { + // TODO (Awareness): Integrate check for if Awareness initialization failed + + _generator?.Clear(); + + _generator = + new MeshObjectsGenerator + ( + ARSession.Mesh, + _meshRoot, + _meshPrefab, + _invisibleMaterial, + _colliderUpdateThrottle + ); + + SetUseInvisibleMaterial(_useInvisibleMaterial); + + ARSession.Mesh.MeshBlocksUpdated += OnMeshUpdated; + + _generator.MeshObjectsUpdated += OnMeshObjectsUpdated; + _generator.MeshObjectsCleared += OnMeshObjectsCleared; + } + + protected override void StopListeningToSession() + { + ARSession.Mesh.MeshBlocksUpdated -= OnMeshUpdated; + + _generator.MeshObjectsUpdated -= OnMeshObjectsUpdated; + _generator.MeshObjectsCleared -= OnMeshObjectsCleared; + } + + public override void ApplyARConfigurationChange + ( + ARSessionChangesCollector.ARSessionRunProperties properties + ) + { + if (properties.ARConfiguration is IARWorldTrackingConfiguration worldConfig) + { + worldConfig.IsMeshingEnabled = AreFeaturesEnabled; + worldConfig.MeshingTargetFrameRate = TargetFrameRate; + worldConfig.MeshingTargetBlockSize = TargetBlockSize; + worldConfig.MeshingRadius = MeshingRadius; + + if (_clearMeshOnRerun) + { + properties.RunOptions |= ARSessionRunOptions.RemoveExistingMesh; + _clearMeshOnRerun = false; + } + } + } + + /// Convenience method to convert world coordinates in Unity to integer block coordinates. + public bool GetBlockCoords(Vector3 worldCoords, out Vector3Int blockCoords) + { + // Parser dne or has not yet processed the first mesh update + if (ARMesh == null || ARMesh.MeshVersion == 0) + { + blockCoords = Vector3Int.zero; + return false; + } + + Vector3 meshCoords = _meshRoot.transform.InverseTransformPoint(worldCoords); + + var meshBlockSize = ARMesh.MeshBlockSize; + blockCoords = new Vector3Int + ( + Mathf.FloorToInt(meshCoords.x / meshBlockSize), + Mathf.FloorToInt(meshCoords.y / meshBlockSize), + Mathf.FloorToInt(meshCoords.z / meshBlockSize) + ); + + return true; + } + + /// Convenience method to get the mesh GameObject at the specified block coordinates. + /// Returns null if no object exists at those coordinates. + public GameObject GetBlockGameObject(Vector3Int blockCoords) + { + if (_generator == null || ARMesh == null) + return null; + + MeshBlock block; + if (ARMesh.Blocks.TryGetValue(blockCoords, out block)) + { + GameObject blockObject; + if (_generator.BlockObjects.TryGetValue(blockCoords, out blockObject)) + return blockObject; + } + + return null; + } + + /// Updates the MeshRenderers of all GameObjects in _blocks with either the invisible or the + /// original prefab material. Does nothing if the prefab is null or does not contain a MeshRenderer. + public void SetUseInvisibleMaterial(bool useInvisible) + { + _useInvisibleMaterial = useInvisible; + + _generator?.SetUseInvisibleMaterial(useInvisible); + } + + /// Clear the mesh, delete all GameObjects under _meshRoot. + /// Sends a MeshCleared event if there's a listener when it's done. + public void ClearMeshObjects() + { + _generator?.Clear(); + _clearMeshOnRerun = true; + RaiseConfigurationChanged(); + } + + // Callback on the ARSession.Mesh.MeshBlocksUpdated event. + // Generates new Unity meshes if required. + private void OnMeshUpdated(MeshBlocksUpdatedArgs args) + { + if (!GenerateUnityMeshes || (args.BlocksObsoleted.Count == 0 && args.BlocksUpdated.Count == 0)) + return; + + _generator.UpdateMeshBlocks(args); + } + + private void OnMeshObjectsUpdated(MeshObjectsUpdatedArgs args) + { + // Currently just a pass-through. + MeshObjectsUpdated?.Invoke(args); + } + + private void OnMeshObjectsCleared(MeshObjectsClearedArgs args) + { + // Currently just a pass-through. + MeshObjectsCleared?.Invoke(args); + } + + private void OnValidate() + { + if (_prevTargetFrameRate != _targetFrameRate) + { + _prevTargetFrameRate = _targetFrameRate; + RaiseConfigurationChanged(); + } + + if (!Mathf.Approximately(_prevTargetBlockSize, _targetBlockSize)) + { + _prevTargetBlockSize = _targetBlockSize; + RaiseConfigurationChanged(); + } + + if (!Mathf.Approximately(_prevMeshingRadius, _meshingRadius)) + { + if (_meshingRadius > 0 && _meshingRadius < 5) + { + ARLog._Error(MeshingRadiusError); + _meshingRadius = 5; + } + + if (!Mathf.Approximately(_prevMeshingRadius, _meshingRadius)) + { + _prevMeshingRadius = _meshingRadius; + RaiseConfigurationChanged(); + } + } + } + } +} diff --git a/Assets/ARDK/Extensions/Meshing/ARMeshManager.cs.meta b/Assets/ARDK/Extensions/Meshing/ARMeshManager.cs.meta new file mode 100644 index 0000000..19ae077 --- /dev/null +++ b/Assets/ARDK/Extensions/Meshing/ARMeshManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e03b458a9fbbf4cc18d8fd737e2a215e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Meshing/Materials.meta b/Assets/ARDK/Extensions/Meshing/Materials.meta new file mode 100644 index 0000000..ba33b41 --- /dev/null +++ b/Assets/ARDK/Extensions/Meshing/Materials.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3127ee6163dd4a1c9f6822e2fce0e1ab +timeCreated: 1611860016 \ No newline at end of file diff --git a/Assets/ARDK/Extensions/Meshing/Materials/MeshInvisible.mat b/Assets/ARDK/Extensions/Meshing/Materials/MeshInvisible.mat new file mode 100644 index 0000000..38842a0 --- /dev/null +++ b/Assets/ARDK/Extensions/Meshing/Materials/MeshInvisible.mat @@ -0,0 +1,77 @@ +%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: MeshInvisible + m_Shader: {fileID: 4800000, guid: a22e024884d5b4a248963661fb0729ff, type: 3} + m_ShaderKeywords: + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 1, g: 1, b: 1, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/Assets/ARDK/Extensions/Meshing/Materials/MeshInvisible.mat.meta b/Assets/ARDK/Extensions/Meshing/Materials/MeshInvisible.mat.meta new file mode 100644 index 0000000..09de923 --- /dev/null +++ b/Assets/ARDK/Extensions/Meshing/Materials/MeshInvisible.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4d00d51d9ad64916abef2551d151e0ab +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Meshing/Materials/MeshInvisible.shader b/Assets/ARDK/Extensions/Meshing/Materials/MeshInvisible.shader new file mode 100644 index 0000000..bfef8d6 --- /dev/null +++ b/Assets/ARDK/Extensions/Meshing/Materials/MeshInvisible.shader @@ -0,0 +1,10 @@ +Shader "ARDK/Meshing/Invisible" { + SubShader { + Tags {"Queue" = "Geometry-10" } + + ColorMask 0 + ZWrite On + + Pass {} + } +} \ No newline at end of file diff --git a/Assets/ARDK/Extensions/Meshing/Materials/MeshInvisible.shader.meta b/Assets/ARDK/Extensions/Meshing/Materials/MeshInvisible.shader.meta new file mode 100644 index 0000000..eb577b0 --- /dev/null +++ b/Assets/ARDK/Extensions/Meshing/Materials/MeshInvisible.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: a22e024884d5b4a248963661fb0729ff +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Meshing/Materials/MeshNormal.mat b/Assets/ARDK/Extensions/Meshing/Materials/MeshNormal.mat new file mode 100644 index 0000000..1a4bde6 --- /dev/null +++ b/Assets/ARDK/Extensions/Meshing/Materials/MeshNormal.mat @@ -0,0 +1,124 @@ +%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: MeshNormal + m_Shader: {fileID: 4800000, guid: 66723c52c76144edca126b78c7da4abb, type: 3} + m_ShaderKeywords: _ALPHAPREMULTIPLY_ON + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Control: + 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} + - _Normal0: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Normal1: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Normal2: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Normal3: + 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} + - _Splat0: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Splat1: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Splat2: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Splat3: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _Alpha: 0.5 + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DistanceClose: 2 + - _DistanceFar: 5 + - _DstBlend: 10 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _Metallic: 0.2 + - _Metallic0: 0 + - _Metallic1: 0 + - _Metallic2: 0 + - _Metallic3: 0 + - _Mode: 3 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _Smoothness0: 1 + - _Smoothness1: 1 + - _Smoothness2: 1 + - _Smoothness3: 1 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 0 + m_Colors: + - _ColorClose: {r: 0, g: 0.8627451, b: 0.7176471, a: 0.4} + - _ColorFar: {r: 0.99607843, g: 0.74509805, b: 0.15294118, a: 0.019607844} diff --git a/Assets/ARDK/Extensions/Meshing/Materials/MeshNormal.mat.meta b/Assets/ARDK/Extensions/Meshing/Materials/MeshNormal.mat.meta new file mode 100644 index 0000000..09d0e8f --- /dev/null +++ b/Assets/ARDK/Extensions/Meshing/Materials/MeshNormal.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0dc9556565924f28a1efd29f71a5142a +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Meshing/Materials/MeshNormal.shader b/Assets/ARDK/Extensions/Meshing/Materials/MeshNormal.shader new file mode 100644 index 0000000..268d44f --- /dev/null +++ b/Assets/ARDK/Extensions/Meshing/Materials/MeshNormal.shader @@ -0,0 +1,74 @@ +Shader "ARDK/Meshing/Normal" { + Properties { + _Alpha ("Alpha", Range(0,1)) = 0.33 + _DistanceClose ("Distance Close", Range(0,10)) = 0.4 + _DistanceFar ("Distance Far", Range(0,10)) = 3.4 + } + SubShader { + Tags {"Queue"="Geometry-10" "RenderType"="Transparent" } + LOD 100 + + Pass { + ZWrite On + ColorMask 0 + + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert + #pragma fragment frag + + struct v2f { + float4 pos : SV_POSITION; + }; + + v2f vert (appdata_base v) { + v2f o; + o.pos = UnityObjectToClipPos(v.vertex); + return o; + } + + half4 frag (v2f i) : COLOR { + return half4 (0,0,0,0); + } + ENDCG + } + + Pass { + Blend SrcAlpha OneMinusSrcAlpha + + CGPROGRAM + #include "UnityCG.cginc" + #include "UnityLightingCommon.cginc" + #pragma vertex vert + #pragma fragment frag + + struct v2f { + float4 pos : SV_POSITION; + fixed4 color : COLOR0; + fixed4 diff : COLOR1; + }; + + fixed _Alpha; + half _DistanceClose; + half _DistanceFar; + + v2f vert (appdata_base v) { + v2f o; + o.pos = UnityObjectToClipPos(v.vertex); + half3 normal = UnityObjectToWorldNormal(v.normal); + half l = min(1.0, max(0.0, (length(ObjSpaceViewDir(v.vertex)) - _DistanceClose) / (_DistanceFar - _DistanceClose))); + o.color.rgb = lerp(abs(normal), fixed3(1,1,1), min(l*1.2, 1.0)); + o.color.a = lerp(_Alpha, 0.0, l); + half nl = max(0.0, dot(normal, _WorldSpaceLightPos0.xyz)); + o.diff = nl * _LightColor0; + o.diff.a = 1.0; + return o; + } + + fixed4 frag (v2f i) : SV_Target { + return (i.diff * i.color + i.color) * 0.5; + } + ENDCG + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/Extensions/Meshing/Materials/MeshNormal.shader.meta b/Assets/ARDK/Extensions/Meshing/Materials/MeshNormal.shader.meta new file mode 100644 index 0000000..cdc3f77 --- /dev/null +++ b/Assets/ARDK/Extensions/Meshing/Materials/MeshNormal.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 66723c52c76144edca126b78c7da4abb +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Meshing/Materials/MeshNormalFresnel.mat b/Assets/ARDK/Extensions/Meshing/Materials/MeshNormalFresnel.mat new file mode 100644 index 0000000..469f761 --- /dev/null +++ b/Assets/ARDK/Extensions/Meshing/Materials/MeshNormalFresnel.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: MeshNormalFresnel + m_Shader: {fileID: 4800000, guid: f18e8b2ba6b041fea5a8d57349ee65e1, type: 3} + m_ShaderKeywords: + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _Alpha: 0.488 + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DistanceClose: 2 + - _DistanceFar: 15 + - _DstBlend: 0 + - _FresnelBias: -1.13 + - _FresnelPower: 2 + - _FresnelScale: 1.04 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 1, g: 1, b: 1, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + - _FresnelColor: {r: 1, g: 1, b: 1, a: 0.6156863} diff --git a/Assets/ARDK/Extensions/Meshing/Materials/MeshNormalFresnel.mat.meta b/Assets/ARDK/Extensions/Meshing/Materials/MeshNormalFresnel.mat.meta new file mode 100644 index 0000000..3d45abf --- /dev/null +++ b/Assets/ARDK/Extensions/Meshing/Materials/MeshNormalFresnel.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 79e0fa18992a46989f2d95ff733901ad +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Meshing/Materials/MeshNormalFresnel.shader b/Assets/ARDK/Extensions/Meshing/Materials/MeshNormalFresnel.shader new file mode 100644 index 0000000..4db42d6 --- /dev/null +++ b/Assets/ARDK/Extensions/Meshing/Materials/MeshNormalFresnel.shader @@ -0,0 +1,67 @@ +Shader "ARDK/Meshing/NormalFresnel" { + Properties { + _Alpha ("Alpha", Range(0,1)) = 0.33 + _DistanceClose ("Distance Close", Range(0,10)) = 1.0 + _DistanceFar ("Distance Far", Range(0,30)) = 15.0 + _FresnelColor ("Fresnel Color", Color) = (1,1,1,1) + _FresnelBias ("Fresnel Bias", Range(-3,3)) = 0 + _FresnelScale ("Fresnel Scale", Range(0,2)) = 1 + _FresnelPower ("Fresnel Power", Range(-10,10)) = 1 + } + SubShader { + Tags { "Queue"="Geometry-10" "RenderType"="Transparent" } + LOD 100 + + Pass { + ZWrite On + ColorMask 0 + } + + Pass { + Blend SrcAlpha OneMinusSrcAlpha + + CGPROGRAM + #include "UnityCG.cginc" + #include "UnityLightingCommon.cginc" + #pragma vertex vert + #pragma fragment frag + + struct v2f { + float4 pos : SV_POSITION; + fixed4 color : COLOR0; // normal color + float fresnel : TEXCOORD0; // fresnel value + }; + + fixed _Alpha; + half _DistanceClose; + half _DistanceFar; + fixed4 _FresnelColor; + fixed _FresnelBias; + fixed _FresnelScale; + fixed _FresnelPower; + + v2f vert (appdata_base v) { + v2f o; + o.pos = UnityObjectToClipPos(v.vertex); + // calculate the fresnel factor. + float3 i = normalize(ObjSpaceViewDir(v.vertex)); + o.fresnel = _FresnelBias + _FresnelScale * pow(1 + dot(i, v.normal), _FresnelPower); + // map geometry normal to cyan-magenta-yellow + half3 normal = half3(1,1,1) - abs(UnityObjectToWorldNormal(v.normal)); + // calculate distance factor (0 = close, 1 = far) + half closeFar = max(0.1, _DistanceFar - _DistanceClose); + half vertexDist = length(ObjSpaceViewDir(v.vertex)); + half l = clamp((vertexDist - _DistanceClose) / closeFar, 0.0, 1.0); + // set the color as the normal CMY + distance transparency factor + o.color = half4(normal, lerp(_Alpha, 0.0, l)); + return o; + } + + fixed4 frag (v2f i) : SV_Target { + fixed4 f = lerp(_FresnelColor, i.color, i.fresnel); + return f; + } + ENDCG + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/Extensions/Meshing/Materials/MeshNormalFresnel.shader.meta b/Assets/ARDK/Extensions/Meshing/Materials/MeshNormalFresnel.shader.meta new file mode 100644 index 0000000..ee19d5e --- /dev/null +++ b/Assets/ARDK/Extensions/Meshing/Materials/MeshNormalFresnel.shader.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f18e8b2ba6b041fea5a8d57349ee65e1 +timeCreated: 1601404736 \ No newline at end of file diff --git a/Assets/ARDK/Extensions/Meshing/MeshChunk.prefab b/Assets/ARDK/Extensions/Meshing/MeshChunk.prefab new file mode 100644 index 0000000..8c3647f --- /dev/null +++ b/Assets/ARDK/Extensions/Meshing/MeshChunk.prefab @@ -0,0 +1,81 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &2988715159741781419 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2984845114046203985} + - component: {fileID: 2955497416138822353} + - component: {fileID: 2965882294894145647} + m_Layer: 0 + m_Name: MeshChunk + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2984845114046203985 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2988715159741781419} + m_LocalRotation: {x: 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} +--- !u!33 &2955497416138822353 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2988715159741781419} + m_Mesh: {fileID: 0} +--- !u!23 &2965882294894145647 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2988715159741781419} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 0 + m_RayTracingMode: 2 + m_RenderingLayerMask: 4294967295 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 79e0fa18992a46989f2d95ff733901ad, 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 diff --git a/Assets/ARDK/Extensions/Meshing/MeshChunk.prefab.meta b/Assets/ARDK/Extensions/Meshing/MeshChunk.prefab.meta new file mode 100644 index 0000000..0ac8310 --- /dev/null +++ b/Assets/ARDK/Extensions/Meshing/MeshChunk.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: b79f4734d3e2462186a55d546e80cfb4 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Meshing/MeshColliderChunk.prefab b/Assets/ARDK/Extensions/Meshing/MeshColliderChunk.prefab new file mode 100644 index 0000000..3a0a521 --- /dev/null +++ b/Assets/ARDK/Extensions/Meshing/MeshColliderChunk.prefab @@ -0,0 +1,91 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!64 &64788887852296080 +MeshCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4501392110370713671} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 4 + m_Convex: 0 + m_CookingOptions: 30 + m_Mesh: {fileID: 0} +--- !u!1001 &1657928140982298092 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 2984845114046203985, guid: b79f4734d3e2462186a55d546e80cfb4, + type: 3} + propertyPath: m_RootOrder + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2984845114046203985, guid: b79f4734d3e2462186a55d546e80cfb4, + type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2984845114046203985, guid: b79f4734d3e2462186a55d546e80cfb4, + type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2984845114046203985, guid: b79f4734d3e2462186a55d546e80cfb4, + type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2984845114046203985, guid: b79f4734d3e2462186a55d546e80cfb4, + type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 2984845114046203985, guid: b79f4734d3e2462186a55d546e80cfb4, + type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2984845114046203985, guid: b79f4734d3e2462186a55d546e80cfb4, + type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2984845114046203985, guid: b79f4734d3e2462186a55d546e80cfb4, + type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2984845114046203985, guid: b79f4734d3e2462186a55d546e80cfb4, + type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2984845114046203985, guid: b79f4734d3e2462186a55d546e80cfb4, + type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2984845114046203985, guid: b79f4734d3e2462186a55d546e80cfb4, + type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2988715159741781419, guid: b79f4734d3e2462186a55d546e80cfb4, + type: 3} + propertyPath: m_Name + value: MeshColliderChunk + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: b79f4734d3e2462186a55d546e80cfb4, type: 3} +--- !u!1 &4501392110370713671 stripped +GameObject: + m_CorrespondingSourceObject: {fileID: 2988715159741781419, guid: b79f4734d3e2462186a55d546e80cfb4, + type: 3} + m_PrefabInstance: {fileID: 1657928140982298092} + m_PrefabAsset: {fileID: 0} diff --git a/Assets/ARDK/Extensions/Meshing/MeshColliderChunk.prefab.meta b/Assets/ARDK/Extensions/Meshing/MeshColliderChunk.prefab.meta new file mode 100644 index 0000000..75ab310 --- /dev/null +++ b/Assets/ARDK/Extensions/Meshing/MeshColliderChunk.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 99a6454115a034b2e9add187cf73f9eb +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Meshing/MeshObjSaver.cs b/Assets/ARDK/Extensions/Meshing/MeshObjSaver.cs new file mode 100644 index 0000000..23ad6d5 --- /dev/null +++ b/Assets/ARDK/Extensions/Meshing/MeshObjSaver.cs @@ -0,0 +1,131 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; +using System.IO; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.ARSessionEventArgs; +using Niantic.ARDK.AR.Mesh; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; + +namespace ARDK.Assets.ARDK.Extensions.Meshing +{ + public class MeshObjSaver: MonoBehaviour + { + private string _meshDir; + private string _meshPath; + private IARSession _session; + + private void Start() + { + ARSessionFactory.SessionInitialized += OnSessionInitialized; + } + + private void OnDestroy() + { + ARSessionFactory.SessionInitialized -= OnSessionInitialized; + Teardown(); + } + + private void OnSessionInitialized(AnyARSessionInitializedArgs args) + { + if (_session != null) + return; + + _session = args.Session; + _meshDir = Application.persistentDataPath +"/meshobj/"; + _meshPath = _meshDir + DateTime.Now.ToString("yyyyMMdd-HHmmss"); + + _session.Deinitialized += OnDeinitialized; + } + + private void OnDeinitialized(ARSessionDeinitializedArgs args) + { + Teardown(); + _meshPath = null; + } + + private void Teardown() + { + if (_session != null) + { + _session.Deinitialized -= OnDeinitialized; + _session = null; + } + } + + public void SaveMeshObj() + { + if (_session == null) + { + ARLog._ErrorFormat("Failed to save mesh because no ARSession was initialized."); + return; + } + + if (string.IsNullOrEmpty(_meshPath)) + { + ARLog._ErrorFormat("Failed to save mesh because no mesh path was specified."); + return; + } + + var provider = _session.Mesh as _MeshDataParser; + + if (provider == null) + { + ARLog._Error("Mesh data was was not found in a form compatible with MeshSaver."); + return; + } + + if (provider.MeshBlockCount == 0) + { + ARLog._ErrorFormat("Failed to save mesh because no mesh blocks were found."); + return; + } + Directory.CreateDirectory(_meshPath); + + string filename = "mesh_" + provider.MeshVersion + ".obj"; + var filepath = _meshPath + "/" + filename; + + var vertexArray = provider.GetNativeVertexArray(); + var faceArray = provider.GetNativeFaceArray(); + + int numOfVertex = provider.MeshVertexCount; + int numOfFace = provider.MeshFaceCount; + + StreamWriter writer = new StreamWriter(filepath); + + for (int i=0; i< numOfVertex; i++) + { + writer.WriteLine("v {0} {1} {2}", vertexArray[i*3+0], vertexArray[i*3+1], vertexArray[i*3+2]); + } + + Debug.LogFormat("vertex length: " + numOfVertex + " " + vertexArray.Length); + + for (int i=0; i< numOfFace; i++) + { + writer.WriteLine("f {0} {1} {2}", faceArray[i*3+0] + 1, faceArray[i*3+1] + 1, faceArray[i*3+2] + 1); + } + + writer.Close(); + + ARLog._Debug("MeshObjSaver: successfully written to " + filename); + } + + /// Delete all saved mesh files. + public void DeleteFiles() + { + if (Directory.Exists(_meshDir)) + { + Directory.Delete(_meshDir, true); + ARLog._Debug("MeshObjSaver: successfully deleted all mesh files"); + } + else + { + ARLog._Debug("MeshObjSaver: No files to delete!"); + } + } + } +} diff --git a/Assets/ARDK/Extensions/Meshing/MeshObjSaver.cs.meta b/Assets/ARDK/Extensions/Meshing/MeshObjSaver.cs.meta new file mode 100644 index 0000000..6ebdcf7 --- /dev/null +++ b/Assets/ARDK/Extensions/Meshing/MeshObjSaver.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: deeca9a15c04d4ffd95dcba5f68c686b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Meshing/MeshObjectsClearedArgs.cs b/Assets/ARDK/Extensions/Meshing/MeshObjectsClearedArgs.cs new file mode 100644 index 0000000..98b94d6 --- /dev/null +++ b/Assets/ARDK/Extensions/Meshing/MeshObjectsClearedArgs.cs @@ -0,0 +1,11 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.Extensions.Meshing +{ + public struct MeshObjectsClearedArgs: + IArdkEventArgs + { + + } +} diff --git a/Assets/ARDK/Extensions/Meshing/MeshObjectsClearedArgs.cs.meta b/Assets/ARDK/Extensions/Meshing/MeshObjectsClearedArgs.cs.meta new file mode 100644 index 0000000..526e9e1 --- /dev/null +++ b/Assets/ARDK/Extensions/Meshing/MeshObjectsClearedArgs.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 1842be830e344c6dad1a8718b6d0040f +timeCreated: 1629897886 \ No newline at end of file diff --git a/Assets/ARDK/Extensions/Meshing/MeshObjectsGenerator.cs b/Assets/ARDK/Extensions/Meshing/MeshObjectsGenerator.cs new file mode 100644 index 0000000..f745f07 --- /dev/null +++ b/Assets/ARDK/Extensions/Meshing/MeshObjectsGenerator.cs @@ -0,0 +1,236 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; + +using Niantic.ARDK.AR.Mesh; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; + +namespace Niantic.ARDK.Extensions.Meshing +{ + public class MeshObjectsGenerator + { + private IARMesh _arMesh; + + private GameObject _root; + private GameObject _prefab; + + private Material _invisibleMaterial; + private bool _usingInvisibleMaterial; + + private int _colliderUpdateThrottle; + + private Dictionary _blockObjects = new Dictionary(); + + public IReadOnlyDictionary BlockObjects { get; } + + /// Called when all mesh blocks have been updated with info from the the latest mesh update. + public event ArdkEventHandler MeshObjectsUpdated; + + /// Called when all mesh blocks have been cleared. + public event ArdkEventHandler MeshObjectsCleared; + + public MeshObjectsGenerator + ( + IARMesh arMesh, + GameObject root, + GameObject prefab, + Material invisibleMaterial, + int colliderUpdateThrottle + ) + { + _arMesh = arMesh; + + _root = root; + _prefab = prefab; + _invisibleMaterial = invisibleMaterial; + _colliderUpdateThrottle = Math.Max(colliderUpdateThrottle, 0); + + BlockObjects = new ReadOnlyDictionary(_blockObjects); + } + + public void Clear() + { + if (_blockObjects.Count == 0) + return; + + foreach (var go in _blockObjects.Values) + GameObject.Destroy(go); + + _blockObjects.Clear(); + MeshObjectsCleared?.Invoke(new MeshObjectsClearedArgs()); + } + + public bool TryGetBlockObject(Vector3Int blockCoords, out GameObject blockObject) + { + return _blockObjects.TryGetValue(blockCoords, out blockObject); + } + + private List _updatedBlocks; + private List _updatedColliders; + public void UpdateMeshBlocks(MeshBlocksUpdatedArgs args) + { + _updatedBlocks = new List(); + _updatedColliders = new List(); + + foreach (var updatedBlock in args.BlocksUpdated) + OnMeshBlockUpdated(updatedBlock); + + foreach (var obsoletedBlock in args.BlocksObsoleted) + OnMeshBlockObsoleted(obsoletedBlock); + + MeshObjectsUpdated?.Invoke(new MeshObjectsUpdatedArgs(_updatedBlocks, _updatedColliders)); + } + + private void OnMeshBlockUpdated(Vector3Int blockCoords) + { + if (!_blockObjects.ContainsKey(blockCoords)) + AddMeshBlock(blockCoords); + + UpdateMeshObject(blockCoords); + _updatedBlocks.Add(_blockObjects[blockCoords]); + } + + private void OnMeshBlockObsoleted(Vector3Int blockCoords) + { + // User triggered Clears could have already removed the game object. + if (TryGetBlockObject(blockCoords, out var blockObject)) + { + GameObject.Destroy(blockObject.gameObject); + _blockObjects.Remove(blockCoords); + } + } + + public void SetUseInvisibleMaterial(bool useInvisible) + { + _usingInvisibleMaterial = useInvisible; + + Material newSharedMaterial = null; + if (!useInvisible) + { + if (_prefab == null) + { + ARLog._Error("Failed to change the mesh material because no mesh prefab was set."); + return; + } + + MeshRenderer meshRenderer = _prefab.GetComponent(); + if (meshRenderer == null) + { + ARLog._Error("Failed to change the mesh material because the mesh prefab lacks a MeshRenderer."); + return; + } + + newSharedMaterial = meshRenderer.sharedMaterial; + if (newSharedMaterial == null) + { + ARLog._Error + ( + "Failed to change the mesh material because the mesh prefab's MeshRenderer component " + + "lacks a shared material." + ); + + return; + } + } + else + { + newSharedMaterial = _invisibleMaterial; + if (newSharedMaterial == null) + { + ARLog._Error("Failed to change the mesh material because no invisible material was set."); + return; + } + } + + foreach (var blockObject in _blockObjects.Values) + { + var blockRenderer = blockObject.GetComponent(); + if (blockRenderer) + blockRenderer.material = newSharedMaterial; + } + } + + private void AddMeshBlock(Vector3Int blockCoords) + { + if (!_arMesh.Blocks.TryGetValue(blockCoords, out MeshBlock meshBlock)) + { + ARLog._Error("No MeshBlock found at block coordinates: " + blockCoords); + return; + } + + var go = GameObject.Instantiate(_prefab, _root.transform, true); + go.transform.localScale = Vector3.one; + go.name = _prefab.name + blockCoords; + + if (_usingInvisibleMaterial && _invisibleMaterial != null) + { + var meshRenderer = + go.GetComponent(); + + if (meshRenderer != null) + meshRenderer.material = _invisibleMaterial; + } + + _blockObjects[blockCoords] = go; + } + + private void UpdateMeshObject(Vector3Int blockCoords) + { + if (!_arMesh.Blocks.TryGetValue(blockCoords, out MeshBlock block)) + { + ARLog._Error("No MeshBlock found at block coordinates: " + blockCoords); + return; + } + + if (!_blockObjects.TryGetValue(blockCoords, out GameObject blockObject)) + { + ARLog._Error("No mesh GameObject found at block coordinates: " + blockCoords); + return; + } + + var meshFilter = blockObject.GetComponent(); + var meshCollider = blockObject.GetComponent(); + + if (block.Mesh == null) + { + block.Mesh = new Mesh(); + block.Mesh.MarkDynamic(); + } + + var mesh = block.Mesh; + mesh.Clear(); + mesh.SetVertices(block.Vertices); + mesh.SetNormals(block.Normals); + mesh.SetIndices(block.Triangles, MeshTopology.Triangles, 0); + + if (meshFilter != null) + meshFilter.sharedMesh = mesh; + + if (meshCollider != null) + { + // update the collider less often for optimal performance + int minColliderUpdateVersion = + block.ColliderVersion + + _colliderUpdateThrottle + + 1; + + var colliderNeedsUpdate = + block.ColliderVersion < 0 || + block.Version >= minColliderUpdateVersion; + + if (colliderNeedsUpdate) + { + meshCollider.sharedMesh = mesh; + block.ColliderVersion = block.Version; + + _updatedColliders.Add(blockObject); + } + } + } + } +} diff --git a/Assets/ARDK/Extensions/Meshing/MeshObjectsGenerator.cs.meta b/Assets/ARDK/Extensions/Meshing/MeshObjectsGenerator.cs.meta new file mode 100644 index 0000000..70adca9 --- /dev/null +++ b/Assets/ARDK/Extensions/Meshing/MeshObjectsGenerator.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a2bf1c8b3fe347ed912893df4f05433f +timeCreated: 1618240453 \ No newline at end of file diff --git a/Assets/ARDK/Extensions/Meshing/MeshObjectsUpdatedArgs.cs b/Assets/ARDK/Extensions/Meshing/MeshObjectsUpdatedArgs.cs new file mode 100644 index 0000000..3150428 --- /dev/null +++ b/Assets/ARDK/Extensions/Meshing/MeshObjectsUpdatedArgs.cs @@ -0,0 +1,30 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; + +using Niantic.ARDK.Utilities; + +using UnityEngine; + +namespace Niantic.ARDK.Extensions.Meshing +{ + public struct MeshObjectsUpdatedArgs: + IArdkEventArgs + { + public MeshObjectsUpdatedArgs + ( + IList blocksUpdated, + IList collidersUpdated + ) + { + BlocksUpdated = new ReadOnlyCollection(blocksUpdated); + CollidersUpdated = new ReadOnlyCollection(collidersUpdated); + } + + public ReadOnlyCollection BlocksUpdated { get; } + public ReadOnlyCollection CollidersUpdated { get; } + + } +} \ No newline at end of file diff --git a/Assets/ARDK/Extensions/Meshing/MeshObjectsUpdatedArgs.cs.meta b/Assets/ARDK/Extensions/Meshing/MeshObjectsUpdatedArgs.cs.meta new file mode 100644 index 0000000..a0ff8b6 --- /dev/null +++ b/Assets/ARDK/Extensions/Meshing/MeshObjectsUpdatedArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 55a39843d353749c9be153a626d8b158 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Meshing/MeshSaver.cs b/Assets/ARDK/Extensions/Meshing/MeshSaver.cs new file mode 100644 index 0000000..3977da4 --- /dev/null +++ b/Assets/ARDK/Extensions/Meshing/MeshSaver.cs @@ -0,0 +1,187 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.IO; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.ARSessionEventArgs; +using Niantic.ARDK.AR.Mesh; +using Niantic.ARDK.Utilities.Logging; +using Niantic.ARDK.Utilities.VersionUtilities; + +using UnityEngine; + +namespace Niantic.ARDK.Extensions.Meshing +{ + /// This helper can be placed in a scene to save mesh data into a binary file on demand plus a + /// MockMeshInfo json file containing meta data. + /// + /// HEADER: + /// The first 16 bytes are a "magic word" equal to the ASCII string "6DBLOCKMESH" (padded with 0) + /// The next 16 bytes are 3 Int32 values for block, vertex, and face buffer sizes + /// followed by 1 Float value for Mesh Block size + /// + /// BUFFERS: + /// Next is the block buffer (sizeof Int32 * block buffer size, no padding) + /// Vertex buffer (sizeof Float * vertex buffer size, no padding) + /// Face buffer (sizeof Int32 * face buffer size, no padding) + /// + /// MockMeshInfo JSON: + /// deviceModel: String + /// dateTime: String (Format "yyyyMMdd-HHmmss") + /// ardkVersion: String + /// vertices: int + /// faces: int + /// + /// More details on the byte layout can be found in IARMesh.cs. + /// Mesh files produced by this script can be loaded into the Unity Editor play mode + /// with Niantic.ARDK.VirtualStudio.AR.Mock.MockMesh (see MeshLoader example scene) + public class MeshSaver: + MonoBehaviour + { + [SerializeField] + private float sequentialSavingInterval = 5f; + + private string _meshesPath; + private string _sessionMeshesPath; + private IARSession _session; + private int _meshNumber = 0; + private MockMeshInfo _mockMeshInfo; + + private void Start() + { + ARSessionFactory.SessionInitialized += OnSessionInitialized; + } + + private void OnDestroy() + { + ARSessionFactory.SessionInitialized -= OnSessionInitialized; + Teardown(); + } + + private void OnSessionInitialized(AnyARSessionInitializedArgs args) + { + if (_session != null) + return; + + _session = args.Session; + _meshesPath = Application.persistentDataPath + "/meshes"; + _sessionMeshesPath = _meshesPath + "/" + DateTime.Now.ToString("yyyyMMdd-HHmmss"); + + _mockMeshInfo = new MockMeshInfo(SystemInfo.deviceModel, DateTime.Now.ToString("yyyyMMdd-HHmmss"), ARDKGlobalVersion.GetARDKVersion()); + + _session.Deinitialized += OnDeinitialized; + } + + private void OnDeinitialized(ARSessionDeinitializedArgs args) + { + Teardown(); + _sessionMeshesPath = null; + } + + private void Teardown() + { + if (_session != null) + { + _session.Deinitialized -= OnDeinitialized; + _session = null; + } + } + + public void SaveMeshSequentially() + { + InvokeRepeating(nameof(SaveMesh), sequentialSavingInterval, sequentialSavingInterval); + } + + public void StopSaveMeshSequentially() + { + CancelInvoke( nameof(SaveMesh)); + } + + /// Saves the current version of the mesh into a file plus meta information into a json. + public void SaveMesh() + { + if (_session == null) + { + ARLog._ErrorFormat("Failed to save mesh because no ARSession was initialized."); + return; + } + + if (string.IsNullOrEmpty(_sessionMeshesPath)) + { + ARLog._ErrorFormat("Failed to save mesh because no mesh path was specified."); + return; + } + + var provider = _session.Mesh as _MeshDataParser; + if (provider == null) + { + ARLog._Error("Mesh data was was not found in a form compatible with MeshSaver."); + return; + } + + if (provider.MeshBlockCount == 0) + { + ARLog._ErrorFormat("Failed to save mesh because no mesh blocks were found."); + return; + } + + Directory.CreateDirectory(_sessionMeshesPath); + + const string MESH_FILE_FORMAT = "mesh_{0}.bin"; + string filename = string.Format(MESH_FILE_FORMAT, _meshNumber); + var filepath = Path.Combine(_sessionMeshesPath, filename); + byte[] magicWord = _FileARMeshData.MagicWord; + + // Write MockMeshInfo into Json file + _mockMeshInfo.vertices = provider.MeshVertexCount; + _mockMeshInfo.faces = provider.MeshFaceCount; + + string info = JsonUtility.ToJson(_mockMeshInfo, true); + const string INFO_FILE_FORMAT = "meshinfo_{0}.json"; + string infoFilename = string.Format(INFO_FILE_FORMAT, _meshNumber); + var infoFilepath = Path.Combine(_sessionMeshesPath, infoFilename); + File.WriteAllText(infoFilepath, info); + + // Define variables of expected types here, to ensure the expected number of bytes is written. + int blockBufferSize = provider.MeshBlockCount * ARMeshConstants.INTS_PER_BLOCK; + int vertexBufferSize = provider.MeshVertexCount * ARMeshConstants.FLOATS_PER_VERTEX; + int faceBufferSize = provider.MeshFaceCount * ARMeshConstants.INTS_PER_FACE; + float blockSize = provider.MeshBlockSize; + + using (BinaryWriter writer = new BinaryWriter(File.Open(filepath, FileMode.Create))) + { + // 16 bytes: signature + writer.Write(magicWord); + + // 16 bytes: array lengths + writer.Write(blockBufferSize); + writer.Write(vertexBufferSize); + writer.Write(faceBufferSize); + writer.Write(blockSize); + + // bulk of the data: + writer.Write(provider.GetSerializedBlockArray()); + writer.Write(provider.GetSerializedVertexArray()); + writer.Write(provider.GetSerializedFaceArray()); + } + + _meshNumber++; + ARLog._Debug("MeshSaver: successfully written to " + filename); + } + + /// Delete all saved mesh files. + public void DeleteFiles() + { + if (Directory.Exists(_meshesPath)) + { + Directory.Delete(_meshesPath, true); + ARLog._Debug("MeshSaver: successfully deleted all mesh files"); + } + else + { + ARLog._Debug("MeshSaver: No files to delete!"); + } + } + } +} diff --git a/Assets/ARDK/Extensions/Meshing/MeshSaver.cs.meta b/Assets/ARDK/Extensions/Meshing/MeshSaver.cs.meta new file mode 100644 index 0000000..4447873 --- /dev/null +++ b/Assets/ARDK/Extensions/Meshing/MeshSaver.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ce2f17b7682ab48f58dea745d9e224de +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Meshing/MockMeshInfo.cs b/Assets/ARDK/Extensions/Meshing/MockMeshInfo.cs new file mode 100644 index 0000000..25c2d7d --- /dev/null +++ b/Assets/ARDK/Extensions/Meshing/MockMeshInfo.cs @@ -0,0 +1,22 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; + +namespace Niantic.ARDK.Extensions.Meshing +{ + [Serializable] + public class MockMeshInfo + { + public string deviceModel; + public string dateTime; + public string ardkVersion; + public int vertices; + public int faces; + + public MockMeshInfo(string deviceModel, string dateTime, string ardkVersion) + { + this.deviceModel = deviceModel; + this.dateTime = dateTime; + this.ardkVersion = ardkVersion; + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/Extensions/Meshing/MockMeshInfo.cs.meta b/Assets/ARDK/Extensions/Meshing/MockMeshInfo.cs.meta new file mode 100644 index 0000000..f703bdc --- /dev/null +++ b/Assets/ARDK/Extensions/Meshing/MockMeshInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8091522c4255249af9dfdd49a57cf3f0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/NetworkSessionManager.cs b/Assets/ARDK/Extensions/NetworkSessionManager.cs new file mode 100644 index 0000000..3607d5d --- /dev/null +++ b/Assets/ARDK/Extensions/NetworkSessionManager.cs @@ -0,0 +1,245 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Text; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.ARSessionEventArgs; +using Niantic.ARDK.Networking; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; +using UnityEngine.Serialization; +using UnityEngine.UI; + +namespace Niantic.ARDK.Extensions +{ + /// Initializes, connects, runs, and disposes a MultipeerNetworking object either according to + /// the Unity lifecycle of this component, or when scripted to do so. + /// + /// If ManageUsingUnityLifecycle is true: + /// OnAwake(): a MultipeerNetworking instance will be initialized + /// OnEnable(): the MultipeerNetworking will attempt to join a session + /// OnDisable(): the MultipeerNetworking will leave the session + /// OnDestroy(): the MultipeerNetworking will be disposed + /// Else: + /// Call Initialize() to initialize a MultipeerNetworking instance + /// Call EnableFeatures() to join a networking session + /// Call DisableFeatures() to leave the networking session + /// Call Deinitialize() to dispose the MultipeerNetworking instance + /// @note + /// A MultipeerNetworking instance cannot leave a session and be re-used to join a session + /// again, so OnEnable/EnableFeatures will initialize a new MultipeerNetworking instance + /// if the existing one has left a session. + [DisallowMultipleComponent] + public sealed class NetworkSessionManager + : UnityLifecycleDriver + { + /// If unspecified, will default to trying to create a live device session, then remote, then mock. + /// If specified, will throw an exception if the source is not supported on the current platform. + /// @note + /// Live device networking is supported in the Unity Editor, but it must be explicitly + /// specified here. + [FormerlySerializedAs("RuntimeEnvironment")] + [SerializeField] + private RuntimeEnvironment _runtimeEnvironment = RuntimeEnvironment.Default; + + /// Should be true if this ARSessionManager is being used in conjunction with an ARNetworkingManager. + [SerializeField] + private bool _useWithARNetworkingSession; + + /// The session identifier used when `Connect` is called. + /// @note If the `InputField` is not-null, its text value will override this field's current value. + [SerializeField] + [Tooltip("The session identifier used when `Connect` is called.")] + private string _sessionIdentifier = null; + + /// If not empty, the text value of this InputField will be used as the session + /// identifier when `Connect` is called. Leave empty to get the default behaviour. + [SerializeField] + [Tooltip("(Optional) InputField source for the session identifier.")] + private InputField _inputField = null; + + private IMultipeerNetworking _networking; + private bool _needToRecreate; + private Guid _stageIdentifier = default; + + /// @warning + /// Underlying object will change if this component is enabled (connected), disabled (disconnected), + /// and then connected again (reconnected). If subscribing to IMultipeerNetworking events, + /// you should listen to the MultipeerNetworkingFactory.NetworkingInitialized event + /// and add your IMultipeerNetworking event subscriptions to the latest initialized networking object. + public IMultipeerNetworking Networking + { + get { return _networking; } + } + + public RuntimeEnvironment RuntimeEnvironment + { + get => _runtimeEnvironment; + set + { + if (_networking != null) + throw new InvalidOperationException("Cannot set this property after this component has been initialized."); + + _runtimeEnvironment = value; + } + } + + public string SessionIdentifier + { + get => _sessionIdentifier; + set + { + if (_networking != null && _networking.IsConnected) + { + ARLog._WarnRelease + ( + "SessionIdentifier value changed but the networking instance is already in a session. " + + "The new value will be used the next time this manager is used to connect to a session." + ); + } + + _sessionIdentifier = value; + } + } + + protected override bool _CanReinitialize + { + get { return true; } + } + + protected override void InitializeImpl() + { + base.InitializeImpl(); + + Create(); + + if (_inputField != null) + { + _sessionIdentifier = _inputField.text; + _inputField.onEndEdit.AddListener(SetSessionIdentifier); + } + } + + internal void _InitializeWithIdentifier(Guid identifier) + { + _stageIdentifier = identifier; + Initialize(); + } + + protected override void DeinitializeImpl() + { + base.DeinitializeImpl(); + + _stageIdentifier = Guid.Empty; + + if (_inputField != null) + _inputField.onEndEdit.RemoveListener(SetSessionIdentifier); + + if (_networking != null) + { + _networking.Dispose(); + _networking = null; + } + } + + protected override void EnableFeaturesImpl() + { + base.EnableFeaturesImpl(); + + if (_networking != null && _needToRecreate) + { + // A networking, once left, is useless because it cannot be used to join/re-join a session. + // So it has to be disposed and a new one created. + _networking.Dispose(); + _networking = null; + Create(); + } + + Connect(); + } + + protected override void DisableFeaturesImpl() + { + base.DisableFeaturesImpl(); + + if (_networking != null) + { + if (_networking.IsConnected) + _networking.Leave(); + } + } + + public void SetSessionIdentifier(string sessionIdentifier) + { + _sessionIdentifier = sessionIdentifier; + + if (_inputField != null) + _inputField.text = sessionIdentifier; + } + + /// Initializes a new MultipeerNetworking object with the set RuntimeEnvironment(s), if one does + /// not yet exist. + private void Create() + { + if (_networking != null) + { + ARLog._Error + ( + "Failed to create a MultipeerNetworking session because one already exists. " + + "To create multiple sessions, use the MultipeerNetworkingFactory API instead." + ); + + return; + } + + if (_useWithARNetworkingSession) + { + if (_stageIdentifier == Guid.Empty) + { + ARLog._Error + ( + "Failed to create a MultipeerNetworking session because _useWithARNetworkingSession " + + "is true but no stage identifier was specified." + ); + + return; + } + + _networking = MultipeerNetworkingFactory.Create(_runtimeEnvironment, _stageIdentifier); + } + else + { + _networking = MultipeerNetworkingFactory.Create(_runtimeEnvironment); + } + + ARLog._DebugFormat("Created {0} MultipeerNetworking: {1}.", false, _networking.RuntimeEnvironment, _networking.StageIdentifier); + + // Just in case the dev disposes the networking themselves instead of through this manager + _networking.Deinitialized += _ => + { + _networking = null; + _needToRecreate = false; + }; + } + + /// Connects the existing MultipeerNetworking object to a session with the set SessionIdentifier. + private void Connect() + { + if (_networking == null) + { + ARLog._Error("Failed to connect MultipeerNetworking session because one was not initialized."); + return; + } + + if (string.IsNullOrEmpty(_sessionIdentifier) && _inputField != null) + _sessionIdentifier = _inputField.text; + + var sessionMetadata = Encoding.UTF8.GetBytes(_sessionIdentifier); + + _needToRecreate = true; + _networking.Join(sessionMetadata); + } + } +} diff --git a/Assets/ARDK/Extensions/NetworkSessionManager.cs.meta b/Assets/ARDK/Extensions/NetworkSessionManager.cs.meta new file mode 100644 index 0000000..ff37867 --- /dev/null +++ b/Assets/ARDK/Extensions/NetworkSessionManager.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f426bc7b950b4c17bd9decb32df6d152 +timeCreated: 1613412903 \ No newline at end of file diff --git a/Assets/ARDK/Extensions/Permissions.meta b/Assets/ARDK/Extensions/Permissions.meta new file mode 100644 index 0000000..39d75ff --- /dev/null +++ b/Assets/ARDK/Extensions/Permissions.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 20d23b2364f094a2fa318fc18ec6750e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Permissions/AndroidPermissionManager.cs b/Assets/ARDK/Extensions/Permissions/AndroidPermissionManager.cs new file mode 100644 index 0000000..4936f30 --- /dev/null +++ b/Assets/ARDK/Extensions/Permissions/AndroidPermissionManager.cs @@ -0,0 +1,29 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + + +using System; +#if UNITY_ANDROID +using Niantic.ARDK.Utilities.Permissions; +using UnityEngine.Android; + +namespace Niantic.ARDK.Extensions.Permissions +{ + /// Static helper for requesting permissions at runtime. + public static class AndroidPermissionManager + { + /// Request a single Android permission. + [Obsolete("Use PermissionRequester.RequestPermission(ARDKPermission permission, Action callback) instead.")] + public static void RequestPermission(ARDKPermission permission) + { + if (!Permission.HasUserAuthorizedPermission(PermissionRequester.AndroidPermissionString[permission])) + Permission.RequestUserPermission(PermissionRequester.AndroidPermissionString[permission]); + } + + [Obsolete("Use PermissionRequester.HasPermission(permission) instead.")] + public static bool HasPermission(ARDKPermission permission) + { + return PermissionRequester.HasPermission(permission); + } + } +} +#endif diff --git a/Assets/ARDK/Extensions/Permissions/AndroidPermissionManager.cs.meta b/Assets/ARDK/Extensions/Permissions/AndroidPermissionManager.cs.meta new file mode 100644 index 0000000..ce4286b --- /dev/null +++ b/Assets/ARDK/Extensions/Permissions/AndroidPermissionManager.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 884b3d54069a4d77b0a7e567ac78e0d6 +timeCreated: 1649082658 \ No newline at end of file diff --git a/Assets/ARDK/Extensions/Permissions/AndroidPermissionRequester.cs b/Assets/ARDK/Extensions/Permissions/AndroidPermissionRequester.cs new file mode 100644 index 0000000..111f71a --- /dev/null +++ b/Assets/ARDK/Extensions/Permissions/AndroidPermissionRequester.cs @@ -0,0 +1,53 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using UnityEngine; +using Niantic.ARDK.Utilities.Permissions; + +#if UNITY_ANDROID +using System.Threading.Tasks; + +using UnityEngine.Android; +#endif + +namespace Niantic.ARDK.Extensions.Permissions +{ + /// Quick solution for requesting permissions from an Android device. No permission request popup will + /// appear if the user has (1) already granted permission or (2) denied permission and requested + /// not to be asked again. + /// + /// @note Other MonoBehaviour's Start methods will get called before the permission flow finishes, + /// so it isn't safe to initialize ARDK resources in Start that depend on the result of this + /// request. + public class AndroidPermissionRequester: MonoBehaviour + { + // If we're not using these, we get warnings about them not being used. However, we don't want + // to completely hide the fields, because that might cause Unity to delete the serialized values + // on other platforms, which would reset the data on the prefab back to the defaults. So, we just + // squelch "unused variable" warnings here. +#pragma warning disable CS0414 + [SerializeField] + private ARDKPermission[] _permissions = null; + +#pragma warning restore CS0414 + +#if UNITY_ANDROID + async void Start() + { + await RequestPermissionsAsync(); + } + + private async Task RequestPermissionsAsync() + { + foreach (var permission in _permissions) + { + if (!PermissionRequester.HasPermission(permission)) + { + await PermissionRequester.RequestPermissionAsync(permission); + } + } + } +#endif + } +} diff --git a/Assets/ARDK/Extensions/Permissions/AndroidPermissionRequester.cs.meta b/Assets/ARDK/Extensions/Permissions/AndroidPermissionRequester.cs.meta new file mode 100644 index 0000000..f93ef51 --- /dev/null +++ b/Assets/ARDK/Extensions/Permissions/AndroidPermissionRequester.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 544755552afaf4436af235f6de9be0b1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Planefinding.meta b/Assets/ARDK/Extensions/Planefinding.meta new file mode 100644 index 0000000..fb10803 --- /dev/null +++ b/Assets/ARDK/Extensions/Planefinding.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: efb484e07c7a647d4a21dae367086f2e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Planefinding/ARPlaneManager.cs b/Assets/ARDK/Extensions/Planefinding/ARPlaneManager.cs new file mode 100644 index 0000000..d9a562b --- /dev/null +++ b/Assets/ARDK/Extensions/Planefinding/ARPlaneManager.cs @@ -0,0 +1,207 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.Anchors; +using Niantic.ARDK.AR.ARSessionEventArgs; +using Niantic.ARDK.AR.Configuration; +using Niantic.ARDK.External; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; + +namespace Niantic.ARDK.Extensions +{ + /// Instantiates, updates, and removes GameObjects for each detected + /// [PlaneAnchor](@ref Niantic.ARDK.AR.Anchors.IARPlaneAnchor]. This settings on this class + /// are the ultimate authority on the used IARWorldTrackingConfiguration.PlaneDetection value. + public sealed class ARPlaneManager: + ARSessionListener + { + /// The object to spawn and update when a plane is detected. + [SerializeField] + private GameObject _planePrefab; + + [SerializeField] + [EnumFlag] + private PlaneDetection _detectedPlaneTypes; + + // Used to track when the Inspector-public _detectedPlaneTypes is changed in OnValidate + private PlaneDetection _prevDetectedPlaneTypes; + + private readonly Dictionary _planeLookup = new Dictionary(); + + /// If this is null no plane prefabs will be created. + /// If this changes after planes have already been discovered existing instances won't be + /// changed. + public GameObject PlanePrefab + { + get => _planePrefab; + set => _planePrefab = value; + } + + public PlaneDetection DetectedPlaneTypes + { + get => _detectedPlaneTypes; + set + { + if (value != _detectedPlaneTypes) + { + _detectedPlaneTypes = value; + RaiseConfigurationChanged(); + } + } + } + + protected override void DeinitializeImpl() + { + base.DeinitializeImpl(); + + ClearAllPlanes(); + } + + protected override void EnableFeaturesImpl() + { + base.EnableFeaturesImpl(); + + _prevDetectedPlaneTypes = _detectedPlaneTypes; + RaiseConfigurationChanged(); + } + + protected override void DisableFeaturesImpl() + { + base.DisableFeaturesImpl(); + + RaiseConfigurationChanged(); + } + + protected override void OnSessionDeinitialized() + { + ClearAllPlanes(); + } + + public override void ApplyARConfigurationChange + ( + ARSessionChangesCollector.ARSessionRunProperties properties + ) + { + if (properties.ARConfiguration is IARWorldTrackingConfiguration worldConfig) + worldConfig.PlaneDetection = AreFeaturesEnabled ? DetectedPlaneTypes : PlaneDetection.None; + } + + protected override void ListenToSession() + { + ARSession.AnchorsAdded += OnAnchorsAdded; + ARSession.AnchorsUpdated += OnAnchorsUpdated; + ARSession.AnchorsRemoved += OnAnchorsRemoved; + ARSession.AnchorsMerged += OnAnchorsMerged; + } + + protected override void StopListeningToSession() + { + ARSession.AnchorsAdded -= OnAnchorsAdded; + ARSession.AnchorsUpdated -= OnAnchorsUpdated; + ARSession.AnchorsRemoved -= OnAnchorsRemoved; + ARSession.AnchorsMerged -= OnAnchorsMerged; + } + + private void OnAnchorsMerged(AnchorsMergedArgs args) + { + var anchorsToRemove = args.Children; + var anchorToUpdate = args.Parent; + + foreach (var anchor in anchorsToRemove) + { + RemoveAnchor(anchor); + } + + if (!_planeLookup.ContainsKey(anchorToUpdate.Identifier)) + { + ARLog._Error("Anchors merged onto an anchor that does not already exist."); + CreateAnchorPrefab(anchorToUpdate as IARPlaneAnchor); + } + RefreshAnchor(anchorToUpdate as IARPlaneAnchor); + } + + private void OnAnchorsAdded(AnchorsArgs args) + { + foreach (var anchor in args.Anchors) + { + if (anchor is IARPlaneAnchor planeAnchor) + { + CreateAnchorPrefab(anchor as IARPlaneAnchor); + RefreshAnchor(planeAnchor); + } + } + } + + private void CreateAnchorPrefab(IARPlaneAnchor anchor) + { + if (_planePrefab == null) + return; + + var plane = Instantiate(_planePrefab); + plane.name = "Plane-" + anchor.Identifier.ToString().Substring(0, 5); + _planeLookup.Add(anchor.Identifier, plane); + } + + private void OnAnchorsUpdated(AnchorsArgs args) + { + foreach (var anchor in args.Anchors) + { + if (anchor is IARPlaneAnchor planeAnchor) + RefreshAnchor(planeAnchor); + } + } + + private void OnAnchorsRemoved(AnchorsArgs args) + { + foreach (var anchor in args.Anchors) + { + if (anchor.AnchorType != AnchorType.Plane || + anchor.IsDisposed()) + continue; + + RemoveAnchor(anchor); + } + } + + private void RemoveAnchor(IARAnchor anchor) + { + Destroy(_planeLookup[anchor.Identifier]); + _planeLookup.Remove(anchor.Identifier); + } + + private void RefreshAnchor(IARPlaneAnchor anchor) + { + if (_planeLookup.TryGetValue(anchor.Identifier, out GameObject go)) + { + // ARKit plane anchors will not change transform but will update the center value + // ARCore plane anchors will update the transform + go.transform.position = anchor.Transform.ToPosition() + anchor.Center; + go.transform.rotation = anchor.Transform.ToRotation(); + go.transform.localScale = anchor.Extent; + } + } + + private void ClearAllPlanes() + { + foreach (var go in _planeLookup.Values) + Destroy(go); + + _planeLookup.Clear(); + } + + private void OnValidate() + { + if (_detectedPlaneTypes != _prevDetectedPlaneTypes) + { + _prevDetectedPlaneTypes = _detectedPlaneTypes; + RaiseConfigurationChanged(); + } + } + } +} diff --git a/Assets/ARDK/Extensions/Planefinding/ARPlaneManager.cs.meta b/Assets/ARDK/Extensions/Planefinding/ARPlaneManager.cs.meta new file mode 100644 index 0000000..4d73013 --- /dev/null +++ b/Assets/ARDK/Extensions/Planefinding/ARPlaneManager.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: b019f0c4dd824101a0a664f35dcb7ace +timeCreated: 1614020655 \ No newline at end of file diff --git a/Assets/ARDK/Extensions/Planefinding/DebugPlane.prefab b/Assets/ARDK/Extensions/Planefinding/DebugPlane.prefab new file mode 100644 index 0000000..ff65e06 --- /dev/null +++ b/Assets/ARDK/Extensions/Planefinding/DebugPlane.prefab @@ -0,0 +1,126 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &1405100059131706 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4157410134710906} + - component: {fileID: 65556479390564900} + m_Layer: 0 + m_Name: DebugPlane + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4157410134710906 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1405100059131706} + m_LocalRotation: {x: 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: 4271641018457536} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!65 &65556479390564900 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1405100059131706} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1.0000001, y: 1.0000001, z: 0.001} + m_Center: {x: 0, y: 0, z: 0} +--- !u!1 &1519743309438326 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4271641018457536} + - component: {fileID: 33904064599386444} + - component: {fileID: 23411711001071826} + m_Layer: 0 + m_Name: Plane + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4271641018457536 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1519743309438326} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0.1, y: 0.1, z: 0.1} + m_Children: [] + m_Father: {fileID: 4157410134710906} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &33904064599386444 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1519743309438326} + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &23411711001071826 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1519743309438326} + 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_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 0} + 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 diff --git a/Assets/ARDK/Extensions/Planefinding/DebugPlane.prefab.meta b/Assets/ARDK/Extensions/Planefinding/DebugPlane.prefab.meta new file mode 100644 index 0000000..264db29 --- /dev/null +++ b/Assets/ARDK/Extensions/Planefinding/DebugPlane.prefab.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 4acc747cb290c4a2ab62bc6239fee1b2 +timeCreated: 1530563905 +licenseType: Pro +NativeFormatImporter: + mainObjectFileID: 100100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Planefinding/PlanePrefab.prefab b/Assets/ARDK/Extensions/Planefinding/PlanePrefab.prefab new file mode 100644 index 0000000..df48189 --- /dev/null +++ b/Assets/ARDK/Extensions/Planefinding/PlanePrefab.prefab @@ -0,0 +1,127 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &1092543363889104 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4865402471339338} + - component: {fileID: 114832692748979186} + m_Layer: 0 + m_Name: PlanePrefab + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4865402471339338 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1092543363889104} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -3.737105, y: -4.27312, z: -1.645819} + m_LocalScale: {x: 0.82, y: 0, z: 0.5898479} + m_Children: + - {fileID: 4622817021425230} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &114832692748979186 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1092543363889104} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 8e13d51c041f449099317b4cd93a4b25, type: 3} + m_Name: + m_EditorClassIdentifier: + _renderer: {fileID: 23712623700508092} + textureScale: 2 +--- !u!1 &1726738585101718 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4622817021425230} + - component: {fileID: 33000257549983730} + - component: {fileID: 23712623700508092} + m_Layer: 0 + m_Name: Plane + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4622817021425230 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1726738585101718} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0.1, y: 0.1, z: 0.1} + m_Children: [] + m_Father: {fileID: 4865402471339338} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &33000257549983730 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1726738585101718} + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &23712623700508092 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1726738585101718} + 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_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 086d9a479bba14014af77a02085e3e0d, 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 diff --git a/Assets/ARDK/Extensions/Planefinding/PlanePrefab.prefab.meta b/Assets/ARDK/Extensions/Planefinding/PlanePrefab.prefab.meta new file mode 100644 index 0000000..7c001e6 --- /dev/null +++ b/Assets/ARDK/Extensions/Planefinding/PlanePrefab.prefab.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 98e455e2ba6ba413287f8cd497d4b08e +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 100100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Planefinding/PlaneRenderer.prefab b/Assets/ARDK/Extensions/Planefinding/PlaneRenderer.prefab new file mode 100644 index 0000000..ecb0304 --- /dev/null +++ b/Assets/ARDK/Extensions/Planefinding/PlaneRenderer.prefab @@ -0,0 +1,49 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &1563025144840004 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4785573950329876} + - component: {fileID: 7649453184476356976} + m_Layer: 0 + m_Name: PlaneRenderer + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4785573950329876 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1563025144840004} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0.24679995, y: -0.16400003, z: 0.28600025} + 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!114 &7649453184476356976 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1563025144840004} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b019f0c4dd824101a0a664f35dcb7ace, type: 3} + m_Name: + m_EditorClassIdentifier: + _manageUsingUnityLifecycle: 0 + _planePrefab: {fileID: 1092543363889104, guid: 98e455e2ba6ba413287f8cd497d4b08e, + type: 3} + _detectedPlaneTypes: 3 diff --git a/Assets/ARDK/Extensions/Planefinding/PlaneRenderer.prefab.meta b/Assets/ARDK/Extensions/Planefinding/PlaneRenderer.prefab.meta new file mode 100644 index 0000000..941ed88 --- /dev/null +++ b/Assets/ARDK/Extensions/Planefinding/PlaneRenderer.prefab.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f743302a2f9034b29bb74934bb56402b +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 100100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Planefinding/PlanefindingGrid.cs b/Assets/ARDK/Extensions/Planefinding/PlanefindingGrid.cs new file mode 100644 index 0000000..a270411 --- /dev/null +++ b/Assets/ARDK/Extensions/Planefinding/PlanefindingGrid.cs @@ -0,0 +1,43 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace Niantic.ARDK.Extensions { + [ExecuteInEditMode] + public class PlanefindingGrid : MonoBehaviour { + + [SerializeField] + private Renderer _renderer = null; + + [SerializeField] + private MaterialPropertyBlock propBlock = null; + + [SerializeField] + private float textureScale = 0.0f; + + private void Awake() { + propBlock = new MaterialPropertyBlock(); + + // Get the current value of the material properties in the renderer. + _renderer.GetPropertyBlock(propBlock); + } + + private void Update() { + if (transform.hasChanged) { + // Assign our new value. + var targetVector = new Vector4( + transform.localScale.x, + transform.localScale.z, + -transform.localScale.x * 0.5f, + -transform.localScale.z * 0.5f); + + propBlock.SetVector("_MainTex_ST", targetVector * textureScale); + _renderer.SetPropertyBlock(propBlock); + + transform.hasChanged = false; + } + } + } +} diff --git a/Assets/ARDK/Extensions/Planefinding/PlanefindingGrid.cs.meta b/Assets/ARDK/Extensions/Planefinding/PlanefindingGrid.cs.meta new file mode 100644 index 0000000..9a94dbc --- /dev/null +++ b/Assets/ARDK/Extensions/Planefinding/PlanefindingGrid.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8e13d51c041f449099317b4cd93a4b25 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Planefinding/PlanefindingGrid.mat b/Assets/ARDK/Extensions/Planefinding/PlanefindingGrid.mat new file mode 100644 index 0000000..2849395 --- /dev/null +++ b/Assets/ARDK/Extensions/Planefinding/PlanefindingGrid.mat @@ -0,0 +1,89 @@ +%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: PlanefindingGrid + m_Shader: {fileID: 4800000, guid: a49c079036efc4cb1b47c6d5c42aabed, type: 3} + m_ShaderKeywords: + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 2800000, guid: be98d61473f61478a94ecbeaf5e45bd8, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MaskTex: + m_Texture: {fileID: 2800000, guid: 98a5c30ad090e427e84419292ecd227b, 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} + - _WarpTex: + m_Texture: {fileID: 2800000, guid: 081be73d5e04849379894bbbea8524ea, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _ScrollXSpeed: 2 + - _ScrollYSpeed: 3 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _TexScale: 4.78 + - _UVSec: 0 + - _WarpStrength: 0.08 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 1, g: 1, b: 1, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/Assets/ARDK/Extensions/Planefinding/PlanefindingGrid.mat.meta b/Assets/ARDK/Extensions/Planefinding/PlanefindingGrid.mat.meta new file mode 100644 index 0000000..629f70c --- /dev/null +++ b/Assets/ARDK/Extensions/Planefinding/PlanefindingGrid.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 086d9a479bba14014af77a02085e3e0d +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Planefinding/PlanefindingGrid.shader b/Assets/ARDK/Extensions/Planefinding/PlanefindingGrid.shader new file mode 100644 index 0000000..4fe0c02 --- /dev/null +++ b/Assets/ARDK/Extensions/Planefinding/PlanefindingGrid.shader @@ -0,0 +1,87 @@ +Shader "Unlit/PlanefindingGrid" +{ + Properties + { + _MainTex ("Texture", 2D) = "white" {} + _MaskTex("Mask", 2D) = "white" {} + + // distortion warp stuff + _ScrollXSpeed("Warp Horizontal Scrolling", Range(-10,10)) = 2 + _ScrollYSpeed("Warp Vertical Scrolling", Range(-10,10)) = 3 + _WarpTex ("Warp Texture", 2D) = "bump" {} + _WarpStrength ("Warp Strength", float) = 1.0 + } + SubShader + { + Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"} + LOD 100 + ZWrite Off + Blend SrcAlpha OneMinusSrcAlpha + + Pass + { + CGPROGRAM + // Upgrade NOTE: excluded shader from DX11; has structs without semantics (struct appdata members wor) + #pragma exclude_renderers d3d11 + #pragma vertex vert + #pragma fragment frag + + #include "UnityCG.cginc" + + struct appdata + { + float4 vertex : POSITION; + float2 uv : TEXCOORD0; + float2 uv2: TEXCOORD1; + }; + + struct v2f + { + float2 uv : TEXCOORD0; + float2 uv2 :TEXCOORD1; + float4 vertex : SV_POSITION; + float2 warpcoord : TEXCOORD3; + }; + + sampler2D _MainTex; + float4 _MainTex_ST; + sampler2D _MaskTex; + float4 _MaskTex_ST; + fixed _ScrollXSpeed; + fixed _ScrollYSpeed; + + sampler2D _WarpTex; + float4 _WarpTex_ST; + fixed _WarpStrength; + + v2f vert (appdata v) + { + v2f o; + o.vertex = UnityObjectToClipPos(v.vertex); + o.uv = TRANSFORM_TEX(v.uv, _MainTex); + o.uv2 = TRANSFORM_TEX(v.uv2, _MaskTex); + o.warpcoord = TRANSFORM_TEX(v.uv, _WarpTex); + return o; + } + + fixed4 frag (v2f i) : SV_Target + { + + fixed2 scrolledUV = i.warpcoord; + fixed xScrollValue = _ScrollXSpeed * _Time; + fixed yScrollValue = _ScrollYSpeed * _Time; + scrolledUV += fixed2(xScrollValue, yScrollValue); + fixed4 warp = (tex2D(_WarpTex, scrolledUV) - 0.5) * _WarpStrength; + + // sample the texture + fixed4 col = tex2D(_MainTex, i.uv + warp.rg); + fixed4 mask = tex2D(_MaskTex, i.uv2); + + col.a = mask.r * col.a; + + return col; + } + ENDCG + } + } +} diff --git a/Assets/ARDK/Extensions/Planefinding/PlanefindingGrid.shader.meta b/Assets/ARDK/Extensions/Planefinding/PlanefindingGrid.shader.meta new file mode 100644 index 0000000..6596f76 --- /dev/null +++ b/Assets/ARDK/Extensions/Planefinding/PlanefindingGrid.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: a49c079036efc4cb1b47c6d5c42aabed +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Planefinding/PlanefindingGrid00.png b/Assets/ARDK/Extensions/Planefinding/PlanefindingGrid00.png new file mode 100644 index 0000000..6d1b7a1 Binary files /dev/null and b/Assets/ARDK/Extensions/Planefinding/PlanefindingGrid00.png differ diff --git a/Assets/ARDK/Extensions/Planefinding/PlanefindingGrid00.png.meta b/Assets/ARDK/Extensions/Planefinding/PlanefindingGrid00.png.meta new file mode 100644 index 0000000..3a8c284 --- /dev/null +++ b/Assets/ARDK/Extensions/Planefinding/PlanefindingGrid00.png.meta @@ -0,0 +1,92 @@ +fileFormatVersion: 2 +guid: be98d61473f61478a94ecbeaf5e45bd8 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 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: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Planefinding/PlanefindingGrid01.png b/Assets/ARDK/Extensions/Planefinding/PlanefindingGrid01.png new file mode 100644 index 0000000..19675ce Binary files /dev/null and b/Assets/ARDK/Extensions/Planefinding/PlanefindingGrid01.png differ diff --git a/Assets/ARDK/Extensions/Planefinding/PlanefindingGrid01.png.meta b/Assets/ARDK/Extensions/Planefinding/PlanefindingGrid01.png.meta new file mode 100644 index 0000000..38c65f8 --- /dev/null +++ b/Assets/ARDK/Extensions/Planefinding/PlanefindingGrid01.png.meta @@ -0,0 +1,92 @@ +fileFormatVersion: 2 +guid: 98a5c30ad090e427e84419292ecd227b +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 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: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Planefinding/PlanefindingGridNormal.png b/Assets/ARDK/Extensions/Planefinding/PlanefindingGridNormal.png new file mode 100644 index 0000000..c236b5b Binary files /dev/null and b/Assets/ARDK/Extensions/Planefinding/PlanefindingGridNormal.png differ diff --git a/Assets/ARDK/Extensions/Planefinding/PlanefindingGridNormal.png.meta b/Assets/ARDK/Extensions/Planefinding/PlanefindingGridNormal.png.meta new file mode 100644 index 0000000..46ce20d --- /dev/null +++ b/Assets/ARDK/Extensions/Planefinding/PlanefindingGridNormal.png.meta @@ -0,0 +1,92 @@ +fileFormatVersion: 2 +guid: 081be73d5e04849379894bbbea8524ea +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 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: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Prefabs.meta b/Assets/ARDK/Extensions/Prefabs.meta new file mode 100644 index 0000000..c30674c --- /dev/null +++ b/Assets/ARDK/Extensions/Prefabs.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 9992f3d5b489e4d0c8ec6312ddfc163b +folderAsset: yes +timeCreated: 1525206402 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Prefabs/ARCameraPositionHistory.prefab b/Assets/ARDK/Extensions/Prefabs/ARCameraPositionHistory.prefab new file mode 100644 index 0000000..dc34516 --- /dev/null +++ b/Assets/ARDK/Extensions/Prefabs/ARCameraPositionHistory.prefab @@ -0,0 +1,142 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &1044493878083797825 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8984671168269382745} + - component: {fileID: 114627100251146290} + - component: {fileID: 6388393528893122830} + m_Layer: 0 + m_Name: BreadcrumbLine + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &8984671168269382745 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1044493878083797825} + m_LocalRotation: {x: 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} +--- !u!114 &114627100251146290 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1044493878083797825} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 71dba49f71604f6f938280a32784fe29, type: 3} + m_Name: + m_EditorClassIdentifier: + _breadcrumbInterval: 0 + _breadcrumbPrefab: {fileID: 0} + _breadcrumbsRoot: {fileID: 0} +--- !u!120 &6388393528893122830 +LineRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1044493878083797825} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 0 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10306, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 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_Positions: [] + m_Parameters: + serializedVersion: 3 + widthMultiplier: 0.1 + widthCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0.23684195 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + colorGradient: + serializedVersion: 2 + key0: {r: 1, g: 0, b: 0, a: 1} + key1: {r: 1, g: 0.4166667, b: 0, a: 1} + key2: {r: 1, g: 0.8333334, b: 0, a: 0} + key3: {r: 1, g: 0.95, b: 0, a: 0} + key4: {r: 0.6333333, g: 1, b: 0, a: 0} + key5: {r: 0, g: 1, b: 0.4666667, a: 0} + key6: {r: 0, g: 0.3833332, b: 1, a: 0} + key7: {r: 0.6499996, g: 0, b: 1, a: 0} + ctime0: 0 + ctime1: 9362 + ctime2: 18724 + ctime3: 28086 + ctime4: 37449 + ctime5: 47609 + ctime6: 56173 + ctime7: 65535 + atime0: 0 + atime1: 65535 + atime2: 0 + atime3: 0 + atime4: 0 + atime5: 0 + atime6: 0 + atime7: 0 + m_Mode: 0 + m_NumColorKeys: 8 + m_NumAlphaKeys: 2 + numCornerVertices: 5 + numCapVertices: 10 + alignment: 0 + textureMode: 0 + shadowBias: 0.5 + generateLightingData: 0 + m_UseWorldSpace: 0 + m_Loop: 0 diff --git a/Assets/ARDK/Extensions/Prefabs/ARCameraPositionHistory.prefab.meta b/Assets/ARDK/Extensions/Prefabs/ARCameraPositionHistory.prefab.meta new file mode 100644 index 0000000..2864846 --- /dev/null +++ b/Assets/ARDK/Extensions/Prefabs/ARCameraPositionHistory.prefab.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 628426794e4144aeae64e95766e3e760 +timeCreated: 1611860217 \ No newline at end of file diff --git a/Assets/ARDK/Extensions/Prefabs/ARNetworkingSceneManager.prefab b/Assets/ARDK/Extensions/Prefabs/ARNetworkingSceneManager.prefab new file mode 100644 index 0000000..10df828 --- /dev/null +++ b/Assets/ARDK/Extensions/Prefabs/ARNetworkingSceneManager.prefab @@ -0,0 +1,183 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &2658963035307697238 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6997646801401058201} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f426bc7b950b4c17bd9decb32df6d152, type: 3} + m_Name: + m_EditorClassIdentifier: + _manageUsingUnityLifecycle: 0 + _arInfoSource: 0 + _useWithARNetworkingSession: 1 + _sessionIdentifier: + _inputField: {fileID: 0} +--- !u!114 &5150496722276672610 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6997646801401058201} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: bfedfd6646c94b53b5ae944005ee7e76, type: 3} + m_Name: + m_EditorClassIdentifier: + _manageUsingUnityLifecycle: 1 + _isSharedExperienceEnabled: 1 +--- !u!1001 &331271225392198807 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 2660146979434066321, guid: e91d6d15f11cc4ad29bb1a41ae9aa381, + type: 3} + propertyPath: PlaneDetection + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 2660146979434066321, guid: e91d6d15f11cc4ad29bb1a41ae9aa381, + type: 3} + propertyPath: IsAutoFocusEnabled + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 2660146979434066321, guid: e91d6d15f11cc4ad29bb1a41ae9aa381, + type: 3} + propertyPath: IsLightEstimationEnabled + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 2660146979434066321, guid: e91d6d15f11cc4ad29bb1a41ae9aa381, + type: 3} + propertyPath: IsSharedExperienceEnabled + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 2989438510040242303, guid: e91d6d15f11cc4ad29bb1a41ae9aa381, + type: 3} + propertyPath: _runWhenEnabled + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2989438510040242303, guid: e91d6d15f11cc4ad29bb1a41ae9aa381, + type: 3} + propertyPath: _useExistingStage + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 2989438510040242303, guid: e91d6d15f11cc4ad29bb1a41ae9aa381, + type: 3} + propertyPath: _manageUsingUnityLifecycle + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2989438510040242303, guid: e91d6d15f11cc4ad29bb1a41ae9aa381, + type: 3} + propertyPath: _useWithARNetworkingSession + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5400245468795486348, guid: e91d6d15f11cc4ad29bb1a41ae9aa381, + type: 3} + propertyPath: m_RootOrder + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5400245468795486348, guid: e91d6d15f11cc4ad29bb1a41ae9aa381, + type: 3} + propertyPath: m_LocalPosition.x + value: 402 + objectReference: {fileID: 0} + - target: {fileID: 5400245468795486348, guid: e91d6d15f11cc4ad29bb1a41ae9aa381, + type: 3} + propertyPath: m_LocalPosition.y + value: 288 + objectReference: {fileID: 0} + - target: {fileID: 5400245468795486348, guid: e91d6d15f11cc4ad29bb1a41ae9aa381, + type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5400245468795486348, guid: e91d6d15f11cc4ad29bb1a41ae9aa381, + type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5400245468795486348, guid: e91d6d15f11cc4ad29bb1a41ae9aa381, + type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5400245468795486348, guid: e91d6d15f11cc4ad29bb1a41ae9aa381, + type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5400245468795486348, guid: e91d6d15f11cc4ad29bb1a41ae9aa381, + type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5400245468795486348, guid: e91d6d15f11cc4ad29bb1a41ae9aa381, + type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5400245468795486348, guid: e91d6d15f11cc4ad29bb1a41ae9aa381, + type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5400245468795486348, guid: e91d6d15f11cc4ad29bb1a41ae9aa381, + type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7315055104982771470, guid: e91d6d15f11cc4ad29bb1a41ae9aa381, + type: 3} + propertyPath: m_Name + value: ARNetworkingSceneManager + objectReference: {fileID: 0} + - target: {fileID: 7636423979006713103, guid: e91d6d15f11cc4ad29bb1a41ae9aa381, + type: 3} + propertyPath: Success.m_PersistentCalls.m_Calls.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7636423979006713103, guid: e91d6d15f11cc4ad29bb1a41ae9aa381, + type: 3} + propertyPath: Success.m_PersistentCalls.m_Calls.Array.data[0].m_Mode + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 7636423979006713103, guid: e91d6d15f11cc4ad29bb1a41ae9aa381, + type: 3} + propertyPath: Success.m_PersistentCalls.m_Calls.Array.data[0].m_Target + value: + objectReference: {fileID: 0} + - target: {fileID: 7636423979006713103, guid: e91d6d15f11cc4ad29bb1a41ae9aa381, + type: 3} + propertyPath: Success.m_PersistentCalls.m_Calls.Array.data[0].m_CallState + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 7636423979006713103, guid: e91d6d15f11cc4ad29bb1a41ae9aa381, + type: 3} + propertyPath: Success.m_PersistentCalls.m_Calls.Array.data[0].m_MethodName + value: set_interactable + objectReference: {fileID: 0} + - target: {fileID: 7636423979006713103, guid: e91d6d15f11cc4ad29bb1a41ae9aa381, + type: 3} + propertyPath: Success.m_PersistentCalls.m_Calls.Array.data[0].m_Arguments.m_BoolArgument + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7636423979006713103, guid: e91d6d15f11cc4ad29bb1a41ae9aa381, + type: 3} + propertyPath: Success.m_PersistentCalls.m_Calls.Array.data[0].m_Arguments.m_ObjectArgumentAssemblyTypeName + value: UnityEngine.Object, UnityEngine + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: e91d6d15f11cc4ad29bb1a41ae9aa381, type: 3} +--- !u!1 &6997646801401058201 stripped +GameObject: + m_CorrespondingSourceObject: {fileID: 7315055104982771470, guid: e91d6d15f11cc4ad29bb1a41ae9aa381, + type: 3} + m_PrefabInstance: {fileID: 331271225392198807} + m_PrefabAsset: {fileID: 0} diff --git a/Assets/ARDK/Extensions/Prefabs/ARNetworkingSceneManager.prefab.meta b/Assets/ARDK/Extensions/Prefabs/ARNetworkingSceneManager.prefab.meta new file mode 100644 index 0000000..d226f52 --- /dev/null +++ b/Assets/ARDK/Extensions/Prefabs/ARNetworkingSceneManager.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 903492e152bd34b2b8e964fe195297e8 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Prefabs/ARSceneCamera.prefab b/Assets/ARDK/Extensions/Prefabs/ARSceneCamera.prefab new file mode 100644 index 0000000..7920d45 --- /dev/null +++ b/Assets/ARDK/Extensions/Prefabs/ARSceneCamera.prefab @@ -0,0 +1,127 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &1917084503044084 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4121737292843690} + - component: {fileID: 20333895847132536} + - component: {fileID: 124606558890110090} + - component: {fileID: 81267771042147026} + - component: {fileID: 8041774839936287112} + - component: {fileID: 1021606229365629317} + m_Layer: 0 + m_Name: ARSceneCamera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4121737292843690 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1917084503044084} + m_LocalRotation: {x: 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} +--- !u!20 &20333895847132536 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1917084503044084} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 2 + m_BackGroundColor: {r: 0, g: 0, b: 0, 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.01 + far clip plane: 100 + 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!124 &124606558890110090 +Behaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1917084503044084} + m_Enabled: 1 +--- !u!81 &81267771042147026 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1917084503044084} + m_Enabled: 1 +--- !u!114 &8041774839936287112 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1917084503044084} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: da5ec3a3669946bf90ad10bf4ffab8a8, type: 3} + m_Name: + m_EditorClassIdentifier: + Camera: {fileID: 20333895847132536} +--- !u!114 &1021606229365629317 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1917084503044084} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5d39c0b3c66c44c10b52d0b316fcdea5, type: 3} + m_Name: + m_EditorClassIdentifier: + _manageUsingUnityLifecycle: 1 + _renderTargetId: 0 + _camera: {fileID: 20333895847132536} + _targetTexture: {fileID: 0} + _nearClippingPlane: 0.1 + _farClippingPlane: 100 diff --git a/Assets/ARDK/Extensions/Prefabs/ARSceneCamera.prefab.meta b/Assets/ARDK/Extensions/Prefabs/ARSceneCamera.prefab.meta new file mode 100644 index 0000000..957fe0e --- /dev/null +++ b/Assets/ARDK/Extensions/Prefabs/ARSceneCamera.prefab.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 924a7268bfe9947e095cce9a99ed0458 +timeCreated: 1525206782 +licenseType: Pro +NativeFormatImporter: + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/Prefabs/ARSceneManager.prefab b/Assets/ARDK/Extensions/Prefabs/ARSceneManager.prefab new file mode 100644 index 0000000..906cbe4 --- /dev/null +++ b/Assets/ARDK/Extensions/Prefabs/ARSceneManager.prefab @@ -0,0 +1,136 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &7315055104982771470 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5400245468795486348} + - component: {fileID: 2989438510040242303} + - component: {fileID: 7636423979006713103} + m_Layer: 0 + m_Name: ARSceneManager + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &5400245468795486348 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7315055104982771470} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 402, y: 288, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 3381041692372307289} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &2989438510040242303 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7315055104982771470} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 00203f13141804260a205f7c8a71dc60, type: 3} + m_Name: + m_EditorClassIdentifier: + _manageUsingUnityLifecycle: 1 + RuntimeEnvironment: 0 + _runOptions: 0 + _useWithARNetworkingSession: 0 + _isLightEstimationEnabled: 0 + _isAutoFocusEnabled: 0 + _worldAlignment: 0 +--- !u!114 &7636423979006713103 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7315055104982771470} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 043ecbfe80cd44fca08dc8e0ee10100e, type: 3} + m_Name: + m_EditorClassIdentifier: + _manageUsingUnityLifecycle: 1 + Success: + m_PersistentCalls: + m_Calls: [] + Failure: + m_PersistentCalls: + m_Calls: [] +--- !u!1001 &3379242557800286195 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 5400245468795486348} + m_Modifications: + - target: {fileID: 1917084503044084, guid: 924a7268bfe9947e095cce9a99ed0458, type: 3} + propertyPath: m_Name + value: ARSceneCamera + objectReference: {fileID: 0} + - target: {fileID: 4121737292843690, guid: 924a7268bfe9947e095cce9a99ed0458, type: 3} + propertyPath: m_RootOrder + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4121737292843690, guid: 924a7268bfe9947e095cce9a99ed0458, type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4121737292843690, guid: 924a7268bfe9947e095cce9a99ed0458, type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4121737292843690, guid: 924a7268bfe9947e095cce9a99ed0458, type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4121737292843690, guid: 924a7268bfe9947e095cce9a99ed0458, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4121737292843690, guid: 924a7268bfe9947e095cce9a99ed0458, type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4121737292843690, guid: 924a7268bfe9947e095cce9a99ed0458, type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4121737292843690, guid: 924a7268bfe9947e095cce9a99ed0458, type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4121737292843690, guid: 924a7268bfe9947e095cce9a99ed0458, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4121737292843690, guid: 924a7268bfe9947e095cce9a99ed0458, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4121737292843690, guid: 924a7268bfe9947e095cce9a99ed0458, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 924a7268bfe9947e095cce9a99ed0458, type: 3} +--- !u!4 &3381041692372307289 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 4121737292843690, guid: 924a7268bfe9947e095cce9a99ed0458, + type: 3} + m_PrefabInstance: {fileID: 3379242557800286195} + m_PrefabAsset: {fileID: 0} diff --git a/Assets/ARDK/Extensions/Prefabs/ARSceneManager.prefab.meta b/Assets/ARDK/Extensions/Prefabs/ARSceneManager.prefab.meta new file mode 100644 index 0000000..9c8dc3b --- /dev/null +++ b/Assets/ARDK/Extensions/Prefabs/ARSceneManager.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: e91d6d15f11cc4ad29bb1a41ae9aa381 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/SavedRenderingSettings.cs b/Assets/ARDK/Extensions/SavedRenderingSettings.cs new file mode 100644 index 0000000..a5a2938 --- /dev/null +++ b/Assets/ARDK/Extensions/SavedRenderingSettings.cs @@ -0,0 +1,35 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using UnityEngine; + +namespace Niantic.ARDK.Extensions +{ + internal class SavedRenderingSettings + { + /// The previous Game target frame rate before this script initialized -- used to restore + /// the previous frame rate when the script is destroyed. + private int _targetFrameRate; + + /// The previous Game sleep timeout before this script initialized -- used to restore + /// the previous sleep timeout when the script is destroyed. + private int _sleepTimeout; + + /// We need to override VSyncCount as well to use Application.targetFrameRate + /// https://docs.unity3d.com/ScriptReference/QualitySettings-vSyncCount.html + private int _vSyncCount; + + public SavedRenderingSettings(int targetFrameRate, int sleepTimeout, int vSyncCount) + { + _targetFrameRate = targetFrameRate; + _sleepTimeout = sleepTimeout; + _vSyncCount = vSyncCount; + } + + public void Apply() + { + QualitySettings.vSyncCount = _vSyncCount; + Application.targetFrameRate = _targetFrameRate; + Screen.sleepTimeout = _sleepTimeout; + } + } + +} diff --git a/Assets/ARDK/Extensions/SavedRenderingSettings.cs.meta b/Assets/ARDK/Extensions/SavedRenderingSettings.cs.meta new file mode 100644 index 0000000..1f2d6c1 --- /dev/null +++ b/Assets/ARDK/Extensions/SavedRenderingSettings.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 48bef88e525642cbab4952460690ffd4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Extensions/UnityLifecycleDriver.cs b/Assets/ARDK/Extensions/UnityLifecycleDriver.cs new file mode 100644 index 0000000..d002882 --- /dev/null +++ b/Assets/ARDK/Extensions/UnityLifecycleDriver.cs @@ -0,0 +1,251 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Security.Cryptography; + +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; + +namespace Niantic.ARDK.Extensions +{ + // Stub class to allow sealing of Unity lifecycle methods + public abstract class UnityLifecycleDriverBase: + MonoBehaviour + { + protected virtual void Awake() + { + } + + protected virtual void Start() + { + } + + protected virtual void OnDestroy() + { + } + + protected virtual void OnEnable() + { + } + + protected virtual void OnDisable() + { + } + } + + /// Base class for ARDK's extension MonoBehaviour extension classes. All Unity lifecycle + /// methods are sealed to prevent child classes from implementing functionality in them; + /// functionality is instead kept inside virtual methods so the class can be controlled both + /// by the Unity lifecycle and independently (via pure scripting). + public abstract class UnityLifecycleDriver: + UnityLifecycleDriverBase + { + /// If true, this component's lifecycle will be tied to Unity's lifecycle methods. + /// * Unity's Awake calls Initialize + /// * Unity's OnDestroy calls Remove + /// * Unity's OnEnable calls EnableFeatures + /// * Unity's OnDisable calls Disable + /// @note + /// Setting this to false means solely application code is in charge of calling the Initialize, + /// EnableFeatures, and DisableFeatures methods. The Deinitialize method will always be called + /// when this component is destroyed. + /// @note + /// False by default so that EnableFeatures isn't automatically called if this + /// component is instantiated in script. + [SerializeField] + [Tooltip("If true, this component's lifecycle will be tied to Unity's lifecycle methods.")] + private bool _manageUsingUnityLifecycle = false; + + private _ThreadCheckedObject _threadChecker; + private bool _initialized = false; + private bool _deinitialized; + + /// Value is true if this component has been initialized. + public bool Initialized + { + get + { + return _initialized; + } + private set + { + _initialized = value; + } + } + + /// Value is true if this component can be validly initialized. + public bool CanInitialize + { + get { return !Initialized && (!_deinitialized || (_deinitialized && _CanReinitialize)); } + } + + private bool _areFeaturesEnabled = false; + + /// Value is true if this component is enabled. A subclass may gate certain behaviours based + /// on this value. + public bool AreFeaturesEnabled + { + get + { + return _areFeaturesEnabled; + } + private set + { + _areFeaturesEnabled = value; + } + } + + // For use in internal testing only + internal bool _ManageUsingUnityLifecycle + { + get { return _manageUsingUnityLifecycle; } + set { _manageUsingUnityLifecycle = value; } + } + + protected virtual bool _CanReinitialize + { + get { return false; } + } + +#region LifecycleManagementMethods + /// Prepares the instance for use. This is where it will gather all the resources it needs as + /// defined by a subclass in InitializeImpl. + public void Initialize() + { + _threadChecker?._CheckThread(); + + if (Initialized) + { + ARLog._Warn("This component is already initialized."); + return; + } + + if (_deinitialized && !_CanReinitialize) + { + ARLog._Warn("Once deinitialized, this component cannot be re-initialized."); + return; + } + + Initialized = true; + InitializeImpl(); + } + + /// Releases any resources held by the instance as defined by a subclass in DeinitializeImpl. + /// Once this is called, Initialize can't be called. Instead a new instance must be made. + public void Deinitialize() + { + _threadChecker?._CheckThread(); + + if (!Initialized) + return; + + DisableFeatures(); + + Initialized = false; + _deinitialized = true; + + DeinitializeImpl(); + } + + /// Enabled any features controlled by this instance as defined by a subclass in + /// EnableFeaturesImpl. This will initialize the instance if it wasn't already. + public void EnableFeatures() + { + _threadChecker?._CheckThread(); + + // Allow this function to be called multiple times without repeating side effects. + if (AreFeaturesEnabled) + return; + + // Ensure this object is already initialized and fail if it can't. + Initialize(); + + if (!Initialized) + return; + + AreFeaturesEnabled = true; + + EnableFeaturesImpl(); + } + + /// Disable any features controlled by the instance as defined by a subclass in + /// DisableFeaturesImpl. + public void DisableFeatures() + { + _threadChecker?._CheckThread(); + + if (!AreFeaturesEnabled) + return; + + // There is no need to check the initialization state as an enabled instance is by definition + // initialized. + + AreFeaturesEnabled = false; + + DisableFeaturesImpl(); + } +#endregion + +#region UnityLifecycleIntegration + protected sealed override void Awake() + { + _threadChecker = new _ThreadCheckedObject(); + + if (_ManageUsingUnityLifecycle) + Initialize(); + } + + protected sealed override void Start() + { + } + + protected sealed override void OnDestroy() + { + Deinitialize(); + } + + protected sealed override void OnEnable() + { + if (_ManageUsingUnityLifecycle) + EnableFeatures(); + } + + protected sealed override void OnDisable() + { + if (_ManageUsingUnityLifecycle) + DisableFeatures(); + } +#endregion + + /// @note If overriding in a subclass, make sure to call this base method. + protected virtual void InitializeImpl() + { + _threadChecker?._CheckThread(); + } + + protected virtual void DeinitializeImpl() + { + _threadChecker?._CheckThread(); + } + + protected virtual void EnableFeaturesImpl() + { + _threadChecker?._CheckThread(); + } + + protected virtual void DisableFeaturesImpl() + { + _threadChecker?._CheckThread(); + } + + // 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. + // Used to give good default values in the Inspector. + protected virtual void Reset() + { + _manageUsingUnityLifecycle = true; + } + } +} diff --git a/Assets/ARDK/Extensions/UnityLifecycleDriver.cs.meta b/Assets/ARDK/Extensions/UnityLifecycleDriver.cs.meta new file mode 100644 index 0000000..3aa93bb --- /dev/null +++ b/Assets/ARDK/Extensions/UnityLifecycleDriver.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 28da8ed818ec4acdad907cb6aedd53c5 +timeCreated: 1614019206 \ No newline at end of file diff --git a/Assets/ARDK/Extensions/_ExtensionsExecutionOrder.cs b/Assets/ARDK/Extensions/_ExtensionsExecutionOrder.cs new file mode 100644 index 0000000..c5f48e7 --- /dev/null +++ b/Assets/ARDK/Extensions/_ExtensionsExecutionOrder.cs @@ -0,0 +1,10 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +namespace Niantic.ARDK.Extensions +{ + internal static class _ExtensionsExecutionOrder + { + public const int CapabilityChecker = 1; + + public const int ARSessionManager = CapabilityChecker + 1; + } +} diff --git a/Assets/ARDK/Extensions/_ExtensionsExecutionOrder.cs.meta b/Assets/ARDK/Extensions/_ExtensionsExecutionOrder.cs.meta new file mode 100644 index 0000000..6507e99 --- /dev/null +++ b/Assets/ARDK/Extensions/_ExtensionsExecutionOrder.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 55324de229974f45a995b00389d3e9b9 +timeCreated: 1619630982 \ No newline at end of file diff --git a/Assets/ARDK/External.meta b/Assets/ARDK/External.meta new file mode 100644 index 0000000..5dafc15 --- /dev/null +++ b/Assets/ARDK/External.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a61a939e106d049f7aec2e5aa22d3877 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/External/EnumFlagAttribute.cs b/Assets/ARDK/External/EnumFlagAttribute.cs new file mode 100644 index 0000000..592f826 --- /dev/null +++ b/Assets/ARDK/External/EnumFlagAttribute.cs @@ -0,0 +1,17 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +// https://gist.github.com/ikriz/b0f9d96205629e19859e +using UnityEngine; + +namespace Niantic.ARDK.External { + + public class EnumFlagAttribute : PropertyAttribute { + public string enumName; + + public EnumFlagAttribute() { } + + public EnumFlagAttribute(string name) { + enumName = name; + } + } + +} \ No newline at end of file diff --git a/Assets/ARDK/External/EnumFlagAttribute.cs.meta b/Assets/ARDK/External/EnumFlagAttribute.cs.meta new file mode 100644 index 0000000..433397c --- /dev/null +++ b/Assets/ARDK/External/EnumFlagAttribute.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 0ea53cc9808ab4d5f9ccf6576240f8c7 +timeCreated: 1525206682 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/External/EnumFlagDrawer.cs b/Assets/ARDK/External/EnumFlagDrawer.cs new file mode 100644 index 0000000..6bb824c --- /dev/null +++ b/Assets/ARDK/External/EnumFlagDrawer.cs @@ -0,0 +1,46 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +// Not sure if copied or inspired by https://gist.github.com/ikriz/b0f9d96205629e19859e + +#if UNITY_EDITOR +using System; +using System.Reflection; +using UnityEditor; +using UnityEngine; + +namespace Niantic.ARDK.External { + + [CustomPropertyDrawer(typeof(EnumFlagAttribute))] + public class EnumFlagDrawer : PropertyDrawer { + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { + System.Type propertyType = fieldInfo.FieldType; + string[] enumNames = System.Enum.GetNames(propertyType); + int[] enumValues = System.Enum.GetValues(propertyType) as int[]; + + int currentVal = property.intValue; + int enumMask = 0; + for (int i = 0; i < enumValues.Length; i++) { + // If the value isn't 0 (aka none) + if (enumValues[i] != 0) { + if ((enumValues[i] & currentVal) == enumValues[i]) { + enumMask |= (1 << i); + } + } + } + + int newEnumMask = EditorGUI.MaskField(position, label, enumMask, enumNames); + if (newEnumMask != enumMask) { + int newVal = 0; + for (int i = 0; i < enumValues.Length; i++) { + if ((newEnumMask & (1 << i)) != 0) { + newVal |= enumValues[i]; + } + } + + property.intValue = newVal; + } + } + } + +} + +#endif diff --git a/Assets/ARDK/External/EnumFlagDrawer.cs.meta b/Assets/ARDK/External/EnumFlagDrawer.cs.meta new file mode 100644 index 0000000..a0f11a2 --- /dev/null +++ b/Assets/ARDK/External/EnumFlagDrawer.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: a39ee86ef6a79412e857ffd60a04b766 +timeCreated: 1525206682 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/External/Plugins.meta b/Assets/ARDK/External/Plugins.meta new file mode 100644 index 0000000..4d137aa --- /dev/null +++ b/Assets/ARDK/External/Plugins.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fdf2e6ee7fea1420198141519c25b63d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/External/Plugins/zxing.unity.dll b/Assets/ARDK/External/Plugins/zxing.unity.dll new file mode 100644 index 0000000..8459dfb Binary files /dev/null and b/Assets/ARDK/External/Plugins/zxing.unity.dll differ diff --git a/Assets/ARDK/External/Plugins/zxing.unity.dll.meta b/Assets/ARDK/External/Plugins/zxing.unity.dll.meta new file mode 100644 index 0000000..322f5d7 --- /dev/null +++ b/Assets/ARDK/External/Plugins/zxing.unity.dll.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: d6c7b04f102c14963b1cb0cfaa576b07 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + 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/ARDK/Internals.meta b/Assets/ARDK/Internals.meta new file mode 100644 index 0000000..9b1ce7b --- /dev/null +++ b/Assets/ARDK/Internals.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c34ee818b988a426f8284c6bb6bc760b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Internals/EditorUtilities.meta b/Assets/ARDK/Internals/EditorUtilities.meta new file mode 100644 index 0000000..96ea5a2 --- /dev/null +++ b/Assets/ARDK/Internals/EditorUtilities.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 27f53365149154b659be4a021220f178 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Internals/EditorUtilities/_AutofillAttribute.cs b/Assets/ARDK/Internals/EditorUtilities/_AutofillAttribute.cs new file mode 100644 index 0000000..132d44e --- /dev/null +++ b/Assets/ARDK/Internals/EditorUtilities/_AutofillAttribute.cs @@ -0,0 +1,49 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using UnityEngine; + +namespace Niantic.ARDK.Internals.EditorUtilities +{ + /// + /// This attribute sets an object field to be set while the gameobject is selected in the editor + /// by grabbing the appropritate component to fill this property with. Grabbing it during + /// Editor-time saves us from having to call GetComponent on a bunch of objects as we're + /// creating them at runtime, and this helps save us from forgetting to set or having to do a + /// bunch of unnecessary drag-and-drop. This should typically be combined with [SerializeField] + /// + internal class _AutofillAttribute: PropertyAttribute + { + /// + /// Local enum for the different fill types. + /// + public enum AutofillType + { + Self, + Parent, + Children + } + + /// + /// This attribute's autofill type. + /// + public readonly AutofillType autofillType; + + /// + /// Default attribute option, just does a plain GetComponent + /// + public _AutofillAttribute() + : this(AutofillType.Self) + {} + + /// + /// Attribute option with a different fill type. Should only really be used if the value isn't + /// AutofillType.Self + /// + /// The variant on GetComponent that should be used + /// to fill this field + public _AutofillAttribute(AutofillType autofillType) + { + this.autofillType = autofillType; + } + } +} diff --git a/Assets/ARDK/Internals/EditorUtilities/_AutofillAttribute.cs.meta b/Assets/ARDK/Internals/EditorUtilities/_AutofillAttribute.cs.meta new file mode 100644 index 0000000..f8536ed --- /dev/null +++ b/Assets/ARDK/Internals/EditorUtilities/_AutofillAttribute.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: befa6157daf08473e9cfa052a56f79c5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Internals/EditorUtilities/_AutofillDrawer.cs b/Assets/ARDK/Internals/EditorUtilities/_AutofillDrawer.cs new file mode 100644 index 0000000..90e6317 --- /dev/null +++ b/Assets/ARDK/Internals/EditorUtilities/_AutofillDrawer.cs @@ -0,0 +1,57 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +#if UNITY_EDITOR +using System; + +using UnityEditor; +using UnityEngine; + +namespace Niantic.ARDK.Internals.EditorUtilities +{ + /// + /// This drawer does the actual autofilling by grabbing the appropritate component to fill this + /// property with. The fact that this is a property drawer means that it's limited to being able + /// to work on the actively selected GameObject. + /// + [CustomPropertyDrawer(typeof(_AutofillAttribute))] + internal class _AutofillDrawer: PropertyDrawer + { + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + //Only run if we don't have an object filled + if (property.propertyType == SerializedPropertyType.ObjectReference && + property.objectReferenceValue == null) + { + //Use the autofill type to decide which kind of GetComponent we call to fill the field + switch (((_AutofillAttribute) attribute).autofillType) + { + case _AutofillAttribute.AutofillType.Self: + property.objectReferenceValue = + Selection.activeGameObject.GetComponent(fieldInfo.FieldType); + + break; + + case _AutofillAttribute.AutofillType.Parent: + property.objectReferenceValue = + Selection.activeGameObject.GetComponentInParent(fieldInfo.FieldType); + + break; + + case _AutofillAttribute.AutofillType.Children: + property.objectReferenceValue = + Selection.activeGameObject.GetComponentInChildren(fieldInfo.FieldType); + + break; + + default: + + throw new ArgumentOutOfRangeException(); + } + } + + //Still use the normal property field to show the UI + EditorGUI.PropertyField(position, property); + } + } +} +#endif diff --git a/Assets/ARDK/Internals/EditorUtilities/_AutofillDrawer.cs.meta b/Assets/ARDK/Internals/EditorUtilities/_AutofillDrawer.cs.meta new file mode 100644 index 0000000..63a1d95 --- /dev/null +++ b/Assets/ARDK/Internals/EditorUtilities/_AutofillDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8c4aab24914d1457ca64c22a4e8ef9d3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Internals/StartupSystems.cs b/Assets/ARDK/Internals/StartupSystems.cs new file mode 100644 index 0000000..528bb7e --- /dev/null +++ b/Assets/ARDK/Internals/StartupSystems.cs @@ -0,0 +1,425 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +#if UNITY_STANDALONE_OSX || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_WIN +#define UNITY_STANDALONE_DESKTOP +#endif +#if (UNITY_IOS || UNITY_ANDROID || UNITY_STANDALONE_DESKTOP) && !UNITY_EDITOR +#define AR_NATIVE_SUPPORT +#endif + +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.InteropServices; + +using Niantic.ARDK.Configuration.Authentication; + +using Niantic.ARDK.Configuration; +using Niantic.ARDK.Configuration.Internal; +using Niantic.ARDK.Networking; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Logging; +#if UNITY_EDITOR +using UnityEditor; +#endif +using UnityEngine; + + +namespace Niantic.ARDK.Internals +{ + /// Controls the startup systems for ARDK. + public static class StartupSystems + { + // Add a destructor to this class to try and catch editor reloads + private static readonly _Destructor Finalise = new _Destructor(); + + // The pointer to the C++ NarSystemBase handling functionality at the native level + private static IntPtr _nativeHandle = IntPtr.Zero; + + private const string FileDisablingSuffix = ".DISABLED"; + +#if UNITY_EDITOR_OSX + [InitializeOnLoadMethod] + private static void EditorStartup() + { + EnforceRosettaBasedCompatibility(); + +#if !REQUIRE_MANUAL_STARTUP + ManualStartup(); +#endif + } +#endif + + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + private static void Startup() + { +#if AR_NATIVE_SUPPORT +#if !REQUIRE_MANUAL_STARTUP + ManualStartup(); +#endif +#endif + } + + /// + /// Starts up the ARDK startup systems if they haven't been started yet. + /// + public static void ManualStartup() + { +#if (AR_NATIVE_SUPPORT || UNITY_EDITOR_OSX) + try + { + // TODO(sxian): Remove the _ROR_CREATE_STARTUP_SYSTEMS() after moving the functionalities to + // NARSystemBase class. + // Note, don't put any code before calling _NARSystemBase_Initialize() below, since Narwhal C++ + // _NARSystemBase_Initialize() should be the first API to be called before other components are initialized. + _ROR_CREATE_STARTUP_SYSTEMS(); + } + catch (DllNotFoundException e) + { + ARLog._DebugFormat("Failed to create ARDK startup systems: {0}", false, e); + } + + if (_nativeHandle == IntPtr.Zero) { + _nativeHandle = _InitialiseNarBaseSystemBasedOnOS(); + _CallbackQueue.ApplicationWillQuit += OnApplicationQuit; + } else { + ARLog._Error("_nativeHandle is not null, ManualStartup is called twice"); + } + + // The initialization of C# components should happen below. + SetAuthenticationParameters(); + SetDeviceMetadata(); +#endif + } + + private static void OnApplicationQuit() + { +#if (AR_NATIVE_SUPPORT || UNITY_EDITOR_OSX) + if (_nativeHandle != IntPtr.Zero) + { + _NARSystemBase_Release(_nativeHandle); + _nativeHandle = IntPtr.Zero; + } +#endif + } + + private const string AUTH_DOCS_MSG = + "For more information, visit the niantic.dev/docs/authentication.html site."; + + private static void SetAuthenticationParameters() + { + // We always try to find an api key + var apiKey = ""; + var authConfigs = Resources.LoadAll("ARDK/ArdkAuthConfig"); + + if (authConfigs.Length > 1) + { + var errorMessage = "There are multiple ArdkAuthConfigs in Resources/ARDK/ " + + "directories, loading the first API key found. Remove extra" + + " ArdkAuthConfigs to prevent API key problems. " + AUTH_DOCS_MSG; + ARLog._Error(errorMessage); + } + else if (authConfigs.Length == 0) + { + ARLog._Error + ( + "Could not load an ArdkAuthConfig, please add one in a Resources/ARDK/ directory. " + + AUTH_DOCS_MSG + ); + } + else + { + var authConfig = authConfigs[0]; + apiKey = authConfig.ApiKey; + if (!string.IsNullOrEmpty(apiKey)) + ArdkGlobalConfig.SetApiKey(apiKey); + } + + authConfigs = null; + Resources.UnloadUnusedAssets(); + + //Only continue if needed + if (!ServerConfiguration.AuthRequired) + return; + + if (string.IsNullOrEmpty(ServerConfiguration.ApiKey)) + { + + if (!string.IsNullOrEmpty(apiKey)) + { + ServerConfiguration.ApiKey = apiKey; + } + else + { + ARLog._ErrorFormat + ( + "No API Key was found. Add it to the {0} file. {1}", +#if UNITY_EDITOR + AssetDatabase.GetAssetPath(authConfigs[0]), +#else + "Resources/ARDK/ArdkAuthConfig.asset", +#endif + AUTH_DOCS_MSG + ); + } + } + + var authUrl = ArdkGlobalConfig.GetAuthenticationUrl(); + if (string.IsNullOrEmpty(authUrl)) + { + ArdkGlobalConfig.SetAuthenticationUrl(ArdkGlobalConfig._DEFAULT_AUTH_URL); + authUrl = ArdkGlobalConfig.GetAuthenticationUrl(); + } + + ServerConfiguration.AuthenticationUrl = authUrl; + +#if UNITY_EDITOR + if (!string.IsNullOrEmpty(apiKey)) + { + var authResult = ArdkGlobalConfig._VerifyApiKeyWithFeature("feature:unity_editor", isAsync: false); + if(authResult == NetworkingErrorCode.Ok) + ARLog._Debug("Successfully authenticated ARDK Api Key"); + else + { + ARLog._Error("Attempted to authenticate ARDK Api Key, but got error: " + authResult); + } + } +#endif + + var installMode = Application.installMode; + var installModeString = string.Format("install_mode:{0}", installMode.ToString()); + if (!string.IsNullOrEmpty(apiKey)) + ArdkGlobalConfig._VerifyApiKeyWithFeature(installModeString, isAsync: true); + } + + private static void SetDeviceMetadata() + { + ArdkGlobalConfig._Internal.SetApplicationId(Application.identifier); + + var guid = Guid.NewGuid(); + // Formats as a hex string without "0x" (ie: 0123456789ABCDEF0123456789ABCDEF) + var guidAsHexString = $"{guid.ToString("N").ToUpper()}"; + ArdkGlobalConfig._Internal.SetArdkInstanceId(guidAsHexString); + } + + // TODO(bpeake): Find a way to shutdown gracefully and add shutdown here. + + private static IntPtr _InitialiseNarBaseSystemBasedOnOS() + { + // prioritise android and ios to always initialise base nar system +#if (UNITY_IOS || UNITY_ANDROID) && !UNITY_EDITOR + return _InitialiseNarSystem(); +#else + // Macbooks which are M1 processors or are Catalina and below need to use IntPtr.Zero right now + + bool hasM1ProcessorOrHasOSBelowBigSur = _IsM1Processor() || !_IsOperatingSystemBigSurAndAbove(); + bool isMacNotCompatibleForNative = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && hasM1ProcessorOrHasOSBelowBigSur; + + if (isMacNotCompatibleForNative || + RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + // return 0 as native handler for windows, m1 macbooks and macbooks below BigSur + return IntPtr.Zero; + } + + // for everything else initialise nar base system + return _InitialiseNarSystem(); +#endif + } + + private static IntPtr _InitialiseNarSystem() + { +#if (AR_NATIVE_SUPPORT || UNITY_EDITOR_OSX) + return _NARSystemBase_Initialize(); +#else + return IntPtr.Zero; +#endif + } + + private static readonly Dictionary _rosettaFiles = new Dictionary() + { + {"mcs", "/ARDK/mcs.rsp"}, + {"csc", "/ARDK/csc.rsp"}, + }; + private static bool _rosettaCompatibilityCheckPerformed = false; + + private static void EnforceRosettaBasedCompatibility() + { + if (_rosettaCompatibilityCheckPerformed) + return; + +#if UNITY_EDITOR + if (_IsUsingRosetta()) + { + _EnableRosettaFiles(); + } + else + { + _DisableRosettaFiles(); + } +#endif + _rosettaCompatibilityCheckPerformed = true; + } + +#if UNITY_EDITOR + private static void _EnableRosettaFiles() + { + ARLog._Debug("Enabling the files for rosetta compatibility"); + + foreach (var rosettaFile in _rosettaFiles) + { + var disabledFileName = rosettaFile.Value + FileDisablingSuffix; + var absolutePath = _GetPathForFile(rosettaFile.Key, disabledFileName); + + if (!string.IsNullOrWhiteSpace(absolutePath)) + _EnableFileWithRename(absolutePath); + } + } + + private static void _DisableRosettaFiles() + { + ARLog._Debug("Disabling the files for rosetta compatibility"); + + foreach (var rosettaFile in _rosettaFiles) + { + var absolutePath = _GetPathForFile(rosettaFile.Key, rosettaFile.Value); + + if (!string.IsNullOrWhiteSpace(absolutePath)) + _DisableFileWithRename(absolutePath); + } + } + + private static void _EnableFileWithRename(string sourcePath) + { + string newPath = sourcePath.Substring(0, sourcePath.Length - FileDisablingSuffix.Length); + + if (File.Exists(newPath)) + { + ARLog._Debug($"File with name {newPath} already exists. So cleaning it up"); + File.Delete(newPath); + } + + File.Move(sourcePath, newPath); + + RemoveMetaFile(sourcePath); + } + + private static void _DisableFileWithRename(string sourcePath) + { + string newPath = sourcePath + FileDisablingSuffix; + + if (File.Exists(newPath)) + { + ARLog._Debug($"File with name {newPath} already exists. So cleaning it up"); + File.Delete(newPath); + } + + File.Move(sourcePath, newPath); + + RemoveMetaFile(sourcePath); + } + + private static void RemoveMetaFile(string sourcePath) + { + string metaFilePath = sourcePath + ".meta"; + + if(File.Exists(metaFilePath)) + File.Delete(metaFilePath); + } + + private static string _GetPathForFile(string searchString, string pathInArdk) + { + var possibleAssetsGuids = AssetDatabase.FindAssets(searchString); + foreach (var possibleAssetGuid in possibleAssetsGuids) + { + var path = AssetDatabase.GUIDToAssetPath(possibleAssetGuid); + + // sanity check + if (path.Length < pathInArdk.Length) + continue; + + // Get the last characters to compare with the pathInArdk string + var finalSubstring = path.Substring(path.Length - pathInArdk.Length); + if (finalSubstring.Equals(pathInArdk)) + { + return path; + } + } + + return null; + } + +#endif + + private sealed class _Destructor + { + ~_Destructor() + { + OnApplicationQuit(); + } + } + +#if (AR_NATIVE_SUPPORT || UNITY_EDITOR_OSX) + + // TODO AR-10581 Consolidate OS branching logic from here and from ArdkGlobalConfig + private static bool _IsOperatingSystemBigSurAndAbove() + { + // https://en.wikipedia.org/wiki/Darwin_%28operating_system%29#Release_history + // 20.0.0 Darwin is the first version of BigSur + return Environment.OSVersion.Version >= new Version(20, 0, 0); + } + + private static bool _IsUsingRosetta() + { + return + _IsM1Processor() && + RuntimeInformation.ProcessArchitecture == Architecture.X64; + } + + private static bool _IsM1Processor() + { + /* + * https://developer.apple.com/documentation/apple-silicon/about-the-rosetta-translation-environment + * From sysctl.proc_translated, + * Intel/iPhone => -1 + * M1 => 0 + */ + int _; + var size = (IntPtr)4; + var param = "sysctl.proc_translated"; + var result = sysctlbyname(param, out _, ref size, IntPtr.Zero, (IntPtr)0); + + return result >= 0; + } + + [DllImport("libSystem.dylib")] + private static extern int sysctlbyname ([MarshalAs(UnmanagedType.LPStr)]string name, out int int_val, ref IntPtr length, IntPtr newp, IntPtr newlen); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _ROR_CREATE_STARTUP_SYSTEMS(); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NARSystemBase_Initialize(); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARSystemBase_Release(IntPtr nativeHandle); +#else + + private static bool _IsUsingRosetta() + { + return false; + } + + private static bool _IsM1Processor() + { + return false; + } + + private static bool _IsOperatingSystemBigSurAndAbove() + { + return false; + } + +#endif + } +} diff --git a/Assets/ARDK/Internals/StartupSystems.cs.meta b/Assets/ARDK/Internals/StartupSystems.cs.meta new file mode 100644 index 0000000..423d7ae --- /dev/null +++ b/Assets/ARDK/Internals/StartupSystems.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a51ed10cb806742d1af4a136c8a0bc3e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Internals/_ARDKLibrary.cs b/Assets/ARDK/Internals/_ARDKLibrary.cs new file mode 100644 index 0000000..5a8ac30 --- /dev/null +++ b/Assets/ARDK/Internals/_ARDKLibrary.cs @@ -0,0 +1,27 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +namespace Niantic.ARDK.Internals +{ + internal static class _ARDKLibrary + { +#if UNITY_EDITOR + #if IN_ROSETTA + internal const string libraryName = "TODO_DOES_NOT_EXIST"; + #else + internal const string libraryName = "ardk_client_platform"; + #endif + +#elif UNITY_STANDALONE_OSX + internal const string libraryName = "ardk_client_platform"; + +#elif UNITY_IOS + internal const string libraryName = "__Internal"; + +#elif UNITY_ANDROID + internal const string libraryName = "ardk_client_platform"; + +#else + // TODO: Windows and Linux library name + support + internal const string libraryName = "TODO_DOES_NOT_EXIST"; +#endif + } +} diff --git a/Assets/ARDK/Internals/_ARDKLibrary.cs.meta b/Assets/ARDK/Internals/_ARDKLibrary.cs.meta new file mode 100644 index 0000000..4ab8ff3 --- /dev/null +++ b/Assets/ARDK/Internals/_ARDKLibrary.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 30d09d20d71ed4ab6b05cef3d33e698a +timeCreated: 1537212008 +licenseType: Pro +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/LICENSE b/Assets/ARDK/LICENSE new file mode 100644 index 0000000..a9f4d4e --- /dev/null +++ b/Assets/ARDK/LICENSE @@ -0,0 +1,485 @@ +Copyright 2022 Niantic, Inc. All Rights Reserved. + +The following Open Source Software and 3rd Party Libraries went in to the making of ARDK: + +*RocksDB* +Apache 2.0 License +Copyright (c) 2011-present, Facebook, Inc. +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 +https://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. + +*OpenSSL* +Apache 2.0 License +Copyright (c) 1998-2021 The OpenSSL Project. +Copyright (c) 1995-1998 Eric A. Young, Tim J. Hudson +All rights reserved. +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 +https://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. + +*Folly* +Apache 2.0 License +Copyright (c) 2011-present, Facebook, Inc. +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 +https://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. + +*Flatbuffers* +Apache 2.0 License +Copyright (c) 2016 Google Inc. +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 +https://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. + +*Google Cloud CPP* +Apache 2.0 License +Copyright (c) 2017 Google Inc. +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 +https://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. + +*FindOpenGLES.cmake* +Apache 2.0 License +Copyright (c) 2013 Pixar +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 +https://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. + +*OpenCV* +Apache 2.0 License +Copyright (C) 2015-2021, OpenCV Foundation. All rights reserved. +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 +https://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. + +*Open-VCDiff* +Apache 2.0 License +Copyright (c) 2008 The open-vcdiff Authors. All Rights Reserved. +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 +https://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. + +*Tokenizer* +Apache 2.0 License +Copyright (c) 2014-2018 Diomidis Spinellis. +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 +https://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. + +*Google Benchmark* +Apache 2.0 License +Copyright (c) 2015-present gRPC Authors. All rights reserved. +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 +https://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. + +*gRPC* +Apache 2.0 License +Copyright (c) 2015-present gRPC Authors. All rights reserved. +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 +https://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. + +*TensorFlow* +Apache 2.0 License +Copyright (c) 2019 The TensorFlow Authors. All rights reserved. +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 +https://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. + +*s2Geometry* +Apache 2.0 License +Copyright 2010 Google. All rights reserved. +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 +https://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. + +*Datastax CPP-Driver* +Apache 2.0 License +Copyright 2014-2015 DataStax. All rights reserved. +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 +https://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. + + +*Draco* +Apache 2.0 License +Copyright 2016 The Draco Authors. All rights reserved. +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 +https://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. + +*Vectorclass Version2* +Apache 2.0 License +Copyright (C) 2012-2019 Agner Fog. +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 +https://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. + +*DBow2* +DBow2 uses a BSD style license: +Copyright (c) 2015 Dorian Galvez-Lopez. http://doriangalvez.com All rights reserved. +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +3. The original author of the work must be notified of any redistribution of source code or in binary form. +4. Neither the name of copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*cpuid* +Cpuid uses a BSD style license: +Copyright (c) 2017-2019 Samy Al Bahra. All Rights Reserved. +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*g2o* +g2o uses a BSD style license: +Copyright (C) 2011 Rainer Kuemmerle, Giorgio Grisetti, Hauke Strasdat, Kurt Konolige, and Wolfram Burgard. All rights reserved. +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*Concurrent Queue* +Concurrent Queue uses a BSD style license: +Copyright (c) 2013-2016, Cameron Desrochers. All rights reserved. +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*Polynomial* +Polynomial uses a BSD style license: +Copyright (c) 2015, Jonathan Ventura. All rights reserved. +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*Web RTC* +Web RTC uses a BSD style license: +Copyright (c) 2011 The WebRTC Project Authors. All rights reserved. +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +3. Neither the name of Google nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*HIREDIS-VIP* +HIREDIS-VIP uses a BSD style license: +Copyright (c) 2009-2011, Salvatore Sanfilippo. All rights reserved. +Copyright (c) 2010-2011, Pieter Noordhuis. All rights reserved. +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +3. Neither the name of Redis nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*Zstandard* +Zstandard uses a BSD style license: +Copyright (c) 2016-present, Facebook, Inc. All rights reserved. +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +3. Neither the name of Facebook nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*Libjpeg-turbo Project* +Libjpeg-turbo Project uses a BSD style license: +Copyright (c) 2009-2021 D. R. Commander. All Rights Reserved. +Copyright (c) 2015 Viktor Szathmáry. All Rights Reserved. +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +3. Neither the name of libjpeg-turbo Project nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*Point Cloud Library (PCL)* +PCL uses a BSD style license: +Copyright (c) 2009-2012, Willow Garage, Inc. +Copyright (c) 2012-, Open Perception, Inc. +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +3. Neither the name of copyright holder(s) nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*libarchive* +Libarchive uses a BSD style license: +Copyright (c) 2003-2018 Tim Kientzle. All rights reserved. +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*LibYuv* +LibYuv uses a BSD style license: +Copyright (c) 2011 The LibYuv Project Authors. All rights reserved. +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +3. Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*Boost CMake* +Boost CMake uses a BSD style license: +Copyright (c) 2016, Florent Castelli. All rights reserved. +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +3. Neither the name of Phalcon nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*Google Test* +Google Test uses a BSD style license: +Copyright (c) 2008, Google Inc. All rights reserved. +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +3. Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*LibVPX* +LibVPX uses a BSD style license: +Copyright (c) 2010, The WebM Project authors. All rights reserved. +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +3. Neither the name of Google Inc. nor WebM Project, nor the names of its contributors, may be used to endorse or promote products derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*LibWebM* +LibWebM uses a BSD style license: +Copyright (c) 2010, The WebM Project authors. All rights reserved. +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +3. Neither the name of Google Inc. nor WebM Project, nor the names of its contributors, may be used to endorse or promote products derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*Protobuf* +Protobuf uses a BSD style license: +Copyright (c) 2008 Google Inc. All rights reserved. +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +3. Neither the name of Google Inc. nor the names of its contributors, may be used to endorse or promote products derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*GSlang* +GSlang uses a BSD style license: +Copyright (c) 2015-2018 Google Inc. All rights reserved. +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +3. Neither the name of 3Dlabs Inc. Ltd. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*Curl* +This software is distributed under The MIT License (MIT). +Copyright (c) 1996 - 2021, Daniel Stenberg, , and many contributors, see the THANKS file. +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. + +*Nlohmann json* +This software is distributed under The MIT License (MIT). +Copyright (c) 2013-2021 Niels Lohmann. +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. + +*FakeIt* +This software is distributed under The MIT License (MIT). +Copyright (c) 2013 Eran Pe'er. +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. + +*Pugixml* +This software is distributed under The MIT License (MIT). +Copyright (c) 2006-2020 Arseny Kapoulkine. +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. + +*STB* +This software is distributed under The MIT License (MIT). +Copyright (c) 2017 Sean Barrett +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. + +*CPP Utils* +This software is distributed under The MIT License (MIT). +Copyright (c) 2016 Benji Smith +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. + +*Easy Profiler* +This software is distributed under The MIT License (MIT). +Copyright (c) 2016-2019 Sergey Yagovtsev, Victor Zarubkin +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. + +*Redis Modules SDK* +This software is distributed under The MIT License (MIT). +Copyright (c) 2016 Redis Labs +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. + +*Robin Hood Hashing* +This software is distributed under The MIT License (MIT). +Copyright (c) 2018-2019 Martin Ankerl +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. + +*Backward CPP* +This software is distributed under The MIT License (MIT). +Copyright (c) 2013 Google Inc. +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. + +*Continuable* +This software is distributed under The MIT License (MIT). +Copyright (c) 2015 - 2019 Denis Blan +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. + +*Libuv* +This software is distributed under The MIT License (MIT). +Copyright (c) 2015-present libuv project 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. + +*PicoHTTPParser* +This software is distributed under The MIT License (MIT). +Copyright (c) 2009-2014 Kazuho Oku, Tokuhiro Matsuno, Daisuke Murase, Shigeo Mitsunari. +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. + +*SPDLog* +This software is distributed under The MIT License (MIT). +Copyright (c) 2016 Gabi Melman. +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. + +*JWT-CPP* +This software is distributed under The MIT License (MIT). +Copyright (c) 2018 Dominik Thalhammer. +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. + +*Prometheus-CPP* +This software is distributed under The MIT License (MIT). +Copyright (c) 2016-2019 Jupp Mueller +Copyright (c) 2017-2019 Gregor Jasny +And many contributors, see https://github.com/jupp0r/prometheus-cpp/graphs/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. + +*Mobile RCNN* +This software is distributed under The MIT License (MIT). +Copyright (c) 2019 Active Vision Lab, Department of Engineering Science, University of Oxford. +And many contributors, see https://github.com/jupp0r/prometheus-cpp/graphs/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. + +*Half* +This software is distributed under The MIT License (MIT). +Copyright (c) 2012-2020 Christian Rau. +And many contributors, see https://github.com/jupp0r/prometheus-cpp/graphs/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. + +*Catch2* +Catch2 uses the Boost Software License - Version 1.0 - August 17th, 2003 +Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: +The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. +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, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*Function2* +Function2 uses the Boost Software License - Version 1.0 - August 17th, 2003 +Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: +The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. +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, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*Plusaes* +Plusaes uses the Boost Software License - Version 1.0 - August 17th, 2003 +Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: +The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. +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, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + + +*Boost* +Boost uses the Boost Software License - Version 1.0 - August 17th, 2003 +Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: +The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. +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, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*LibSodium* +LibSodium uses the ISC License. +Copyright (c) 2013-2021 Frank Denis +Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE + +*CZMQ* +CZMQ is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, you can obtain one at https://mozilla.org/MPL/2.0/. + +*Eigen* +Eigen is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, you can obtain one at https://mozilla.org/MPL/2.0/. + +*LibPNG* +LibPNG uses the PNG Reference Library License version 2 +Copyright (c) 1995-2019 The PNG Reference Library Authors. +Copyright (c) 2018-2019 Cosmin Truta. +Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson. +Copyright (c) 1996-1997 Andreas Dilger. +Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. +The software is supplied "as is", without warranty of any kind, express or implied, including, without limitation, the warranties of merchantability, fitness for a particular purpose, title, and non-infringement. In no event shall the Copyright owners, or anyone distributing the software, be liable for any damages or other liability, whether in contract, tort or otherwise, arising from, out of, or in connection with the software, or the use or other dealings in the software, even if advised of the possibility of such damage. +Permission is hereby granted to use, copy, modify, and distribute this software, or portions hereof, for any purpose, without fee, subject to the following restrictions: +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated, but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This Copyright notice may not be removed or altered from any source or altered source distribution. + +*zlib* +Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler. +This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. diff --git a/Assets/ARDK/LICENSE.meta b/Assets/ARDK/LICENSE.meta new file mode 100644 index 0000000..f06a27e --- /dev/null +++ b/Assets/ARDK/LICENSE.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: af8e99739a6974828aee48e0935585e4 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/LocationService.meta b/Assets/ARDK/LocationService.meta new file mode 100644 index 0000000..6ee4a71 --- /dev/null +++ b/Assets/ARDK/LocationService.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5f9ee63573cfd489196a07c5f210326a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/LocationService/CompassUpdatedArgs.cs b/Assets/ARDK/LocationService/CompassUpdatedArgs.cs new file mode 100644 index 0000000..17fce04 --- /dev/null +++ b/Assets/ARDK/LocationService/CompassUpdatedArgs.cs @@ -0,0 +1,38 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Utilities; + +using UnityEngine; + +namespace Niantic.ARDK.LocationService +{ + public struct CompassUpdatedArgs: + IArdkEventArgs + { + /// The heading in degrees relative to the geographic North Pole. + public readonly float TrueHeading; + + /// Accuracy of heading reading in degrees. + /// Negative value mean unreliable reading. + /// If accuracy is not supported or not available, 0 is returned. + /// Not all platforms support this pricise accuracy, + /// so the value may vary between few constant values. + public readonly float HeadingAccuracy; + + /// POSIX Timestamp (in seconds since 1970) when the heading was last time updated. + public readonly double Timestamp; + + public CompassUpdatedArgs + ( + float trueHeading, + float headingAccuracy, + double timestamp + ) + { + TrueHeading = trueHeading; + HeadingAccuracy = headingAccuracy; + Timestamp = timestamp; + } + + } +} diff --git a/Assets/ARDK/LocationService/CompassUpdatedArgs.cs.meta b/Assets/ARDK/LocationService/CompassUpdatedArgs.cs.meta new file mode 100644 index 0000000..a3dd9a7 --- /dev/null +++ b/Assets/ARDK/LocationService/CompassUpdatedArgs.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d658b26657ab4d0c8f0b6aad077b2ba0 +timeCreated: 1627071629 \ No newline at end of file diff --git a/Assets/ARDK/LocationService/ILocationService.cs b/Assets/ARDK/LocationService/ILocationService.cs new file mode 100644 index 0000000..61a82d8 --- /dev/null +++ b/Assets/ARDK/LocationService/ILocationService.cs @@ -0,0 +1,50 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.LocationService +{ + /// An object that manages location updates. Use the LocationServiceFactory to create an + /// implementation for the desired runtime environment. + /// + /// The native implementation of this interface uses Unity's Input.location service, and so + /// is only available on mobile devices. + /// + /// The in-editor implementation of this interface (SpoofLocationService) will start in + /// San Francisco, California, USA unless SpoofLocationService.SetLocation is called to specify + /// a different location. See the SpoofLocationService API for more methods to mock location and + /// location movement in the Unity Editor. + /// + /// @note + /// In order to use LocationServices on iOS 10+, the "Location Usage Description" box in + /// the Player Settings > iOS > Other Settings panel must be filled out. If location permission + /// has not yet been granted, the permission request popup will automatically be launched by iOS + /// when Start is called. + /// + /// @note + /// For Android players, Location permissions must be requested prior to calling Start in order + /// for the call to succeed. Use or reference the[PermissionRequester](@ref Niantic.ARDK.Utilities.Permissions.PermissionRequester) + /// in order to do so. + public interface ILocationService + { + LocationServiceStatus Status { get; } + LocationInfo LastData { get; } + + /// Starts location service updates. + void Start(); + + void Start(float desiredAccuracyInMeters, float updateDistanceInMeters); + + /// Stops location service updates. This could be useful for saving battery life. + void Stop(); + + /// Informs subscribers when the session status changes. + event ArdkEventHandler StatusUpdated; + + /// Informs subscribers when there is an update to the device's location. + event ArdkEventHandler LocationUpdated; + + /// Informs subscribers when there is an update to the device's compass. + event ArdkEventHandler CompassUpdated; + } +} diff --git a/Assets/ARDK/LocationService/ILocationService.cs.meta b/Assets/ARDK/LocationService/ILocationService.cs.meta new file mode 100644 index 0000000..0b4fe31 --- /dev/null +++ b/Assets/ARDK/LocationService/ILocationService.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a2ec5bf8d39814cbca489845eccb330a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/LocationService/LatLng.cs b/Assets/ARDK/LocationService/LatLng.cs new file mode 100644 index 0000000..8730296 --- /dev/null +++ b/Assets/ARDK/LocationService/LatLng.cs @@ -0,0 +1,183 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using UnityEngine; + +namespace Niantic.ARDK.LocationService +{ + /// + /// Latitude and Longitude, location on a globe + /// + [Serializable] + public struct LatLng : IEquatable + { + [SerializeField] + private double lat_degrees; + public double Latitude { get { return lat_degrees; } } + + [SerializeField] + private double lng_degrees; + public double Longitude { get { return lng_degrees; } } + + public LatLng(double latitude, double longtitude) + { + if (latitude > 90.0 || latitude < -90.0) + { + throw new ArgumentOutOfRangeException("latitude", "Argument must be in range of -90 to 90"); + } + + if (longtitude > 180.0 || longtitude < -180.0) + { + throw new ArgumentOutOfRangeException("longitude", "Argument must be in range of -180 to 180"); + } + + lat_degrees = latitude; + lng_degrees = longtitude; + } + + public LatLng(LocationInfo locationInfo) + : this (locationInfo.Coordinates.Latitude, locationInfo.Coordinates.Longitude) + { + } + + public LatLng(UnityEngine.LocationInfo locationInfo) + : this (locationInfo.latitude, locationInfo.longitude) + { + } + + // LatLng objects that are equivalent have the same hash code. + public override int GetHashCode() + { + unchecked { + var hash = 31; + hash += Latitude.GetHashCode(); + hash *= 397; + hash += Longitude.GetHashCode(); + + return hash; + } + } + + public override string ToString() + { + return $"[Latitude: {Latitude}, Longitude: {Longitude}]"; + } + + public override bool Equals(object obj) + { + if (!(obj is LatLng)) + return false; + + return Equals((LatLng)obj); + } + + public bool Equals(LatLng other) + { + return this == other; + } + + /// Calculates "as-the-crow-flies" distance between points using the Haversine formula. + /// @returns Distance between points in meters. + public double Distance(LatLng other) + { + if (Equals(other)) + return 0; + + if (double.IsNaN(Latitude) || double.IsNaN(Latitude) || double.IsNaN(other.Latitude) || + double.IsNaN(other.Longitude)) + { + throw new ArgumentException("Latitude or longitude is NaN"); + } + + var rad1 = ToRadian(); + var rad2 = other.ToRadian(); + + double latDelta = rad2.Latitude - rad1.Latitude; + double lngDelta = rad2.Longitude - rad1.Longitude; + + double a = + Math.Pow(Math.Sin(latDelta / 2.0), 2.0) + + Math.Cos(rad1.Latitude) * Math.Cos(rad2.Latitude) * Math.Pow(Math.Sin(lngDelta / 2.0), 2.0); + + return 2.0 * EarthRadius * Math.Asin(Math.Sqrt(a)); + } + + /// Calculates "as-the-crow-flies" distance between points using the Haversine formula. + /// @returns Distance between points in meters. + public static double Distance(LatLng l1, LatLng l2) + { + return l1.Distance(l2); + } + + /// Calculates the initial bearing (sometimes referred to as forward azimuth) which if + /// followed in a straight line along a great-circle arc will take you from the l1 to l2 points. + /// @returns Initial bearing in degrees + public static double Bearing(LatLng l1, LatLng l2) + { + var rad1 = l1.ToRadian(); + var rad2 = l2.ToRadian(); + + double lngDelta = rad2.Longitude - rad1.Longitude; + + double y = Math.Sin(lngDelta) * Math.Cos(rad2.Latitude); + double x = + Math.Cos(rad1.Latitude) * Math.Sin(rad2.Latitude) - + Math.Sin(rad1.Latitude) * Math.Cos(rad2.Latitude) * Math.Cos(lngDelta); + + double r = Math.Atan2(y, x); + + return (r * 180.0/Math.PI + 360) % 360.0; + } + + /// @param bearing Bearing in degrees, clockwise from north + /// @param distance Distance travelled in meters + public LatLng Add(double bearing, double distance) + { + var rad = ToRadian(); + + bearing *= DegToRad; + var angularDistance = distance / EarthRadius; + + var lat = + Math.Asin + ( + Math.Sin(rad.Latitude) * Math.Cos(angularDistance) + + Math.Cos(rad.Latitude) * Math.Sin(angularDistance) * Math.Cos(bearing) + ); + + var lng = + rad.Longitude + + Math.Atan2 + ( + Math.Sin(bearing) * Math.Sin(angularDistance) * Math.Cos(rad.Latitude), + Math.Cos(angularDistance) - Math.Sin(rad.Latitude) * Math.Sin(lat) + ); + + return (new LatLng(lat, lng)).ToDegrees(); + } + + public static bool operator ==(LatLng l1, LatLng l2) + { + return l1.Latitude.Equals(l2.Latitude) && l1.Longitude.Equals(l2.Longitude); + } + + public static bool operator !=(LatLng l1, LatLng l2) + { + return !l1.Latitude.Equals(l2.Latitude) || !l1.Longitude.Equals(l2.Longitude); + } + + const double EarthRadius = 6371009.0; + const double DegToRad = Math.PI / 180.0; + const double RadToDeg = 180.0 / Math.PI; + public LatLng ToRadian() + { + return new LatLng(Latitude * DegToRad, Longitude * DegToRad); + } + + public LatLng ToDegrees() + { + return new LatLng(Latitude * RadToDeg, Longitude * RadToDeg); + } + } +} diff --git a/Assets/ARDK/LocationService/LatLng.cs.meta b/Assets/ARDK/LocationService/LatLng.cs.meta new file mode 100644 index 0000000..a20f3e1 --- /dev/null +++ b/Assets/ARDK/LocationService/LatLng.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: daa53b20d683b490ca8c3eae9e58769e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/LocationService/LocationInfo.cs b/Assets/ARDK/LocationService/LocationInfo.cs new file mode 100644 index 0000000..6d2ef9b --- /dev/null +++ b/Assets/ARDK/LocationService/LocationInfo.cs @@ -0,0 +1,116 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; + +namespace Niantic.ARDK.LocationService +{ + public struct LocationInfo + { + /// Altitude relative to sea level, in meters. + public readonly double Altitude; + + /// Geographical device location coordinates in degrees. + public readonly LatLng Coordinates; + + /// Horizontal accuracy of the location. + public readonly double HorizontalAccuracy; + + /// Vertical accuracy of the location. + public readonly double VerticalAccuracy; + + /// POSIX Timestamp (in seconds since 1970) when location was recorded. + public readonly double Timestamp; + + public LocationInfo(UnityEngine.LocationInfo info) + : this + ( + info.latitude, + info.longitude, + info.altitude, + info.horizontalAccuracy, + info.verticalAccuracy, + info.timestamp + ) + { + } + + public LocationInfo(LatLng coordinates): this(coordinates.Latitude, coordinates.Longitude) + { + } + + public LocationInfo + ( + double latitude, + double longitude, + double altitude = double.NaN, + double horizontalAccuracy = double.NaN, + double verticalAccuracy = double.NaN, + double timestamp = double.NaN + ) + { + Coordinates = new LatLng(latitude, longitude); + Altitude = altitude; + HorizontalAccuracy = horizontalAccuracy; + VerticalAccuracy = verticalAccuracy; + Timestamp = timestamp; + } + + // LocationInfo objects that are equivalent have the same hash code. + public override int GetHashCode() + { + unchecked { + var hash = 31; + hash *= 97 + Coordinates.GetHashCode(); + hash *= 97 + Altitude.GetHashCode(); + hash *= 97 + HorizontalAccuracy.GetHashCode(); + hash *= 97 + VerticalAccuracy.GetHashCode(); + hash *= 97 + Timestamp.GetHashCode(); + + return hash; + } + } + + public override bool Equals(object obj) + { + if (!(obj is LocationInfo)) + return false; + + return Equals((LocationInfo)obj); + } + + public bool Equals(LocationInfo other) + { + return this == other; + } + + public static bool operator ==(LocationInfo l1, LocationInfo l2) + { + return + l1.Coordinates == l2.Coordinates && + ApproximatelyEquals(l1.Altitude, l2.Altitude) && + ApproximatelyEquals(l1.HorizontalAccuracy, l2.HorizontalAccuracy) && + ApproximatelyEquals(l1.VerticalAccuracy, l2.VerticalAccuracy) && + ApproximatelyEquals(l1.Timestamp, l2.Timestamp); + } + + public static bool operator !=(LocationInfo l1, LocationInfo l2) + { + return !(l1 == l2); + } + + public override string ToString() + { + return $"{Coordinates.Latitude}°, {Coordinates.Longitude}° (Altitude: {Altitude}, Horizontal Accuracy: {HorizontalAccuracy}, Vertical Accuracy: {VerticalAccuracy}"; + } + + private static bool ApproximatelyEquals(double x, double y) + { + if (double.IsNaN(x)) + return double.IsNaN(y); + + if (double.IsNaN(y)) + return false; + + return Math.Abs(x - y) < double.Epsilon; + } + } +} diff --git a/Assets/ARDK/LocationService/LocationInfo.cs.meta b/Assets/ARDK/LocationService/LocationInfo.cs.meta new file mode 100644 index 0000000..2a91184 --- /dev/null +++ b/Assets/ARDK/LocationService/LocationInfo.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 449e4683edc545c9a6704d7ae7327fef +timeCreated: 1647376455 \ No newline at end of file diff --git a/Assets/ARDK/LocationService/LocationServiceFactory.cs b/Assets/ARDK/LocationService/LocationServiceFactory.cs new file mode 100644 index 0000000..d80d197 --- /dev/null +++ b/Assets/ARDK/LocationService/LocationServiceFactory.cs @@ -0,0 +1,64 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; +using System.Collections.Generic; +using System.ComponentModel; + +using Niantic.ARDK.AR; + +namespace Niantic.ARDK.LocationService +{ + public class LocationServiceFactory + { + public static ILocationService Create() + { + return _Create(null); + } + + public static ILocationService Create(RuntimeEnvironment env) + { + switch (env) + { + case RuntimeEnvironment.Default: + return Create(); + + case RuntimeEnvironment.LiveDevice: +#if !UNITY_EDITOR + return new _UnityLocationService(); +#else + return null; +#endif + + case RuntimeEnvironment.Remote: + return null; + + case RuntimeEnvironment.Mock: + return new SpoofLocationService(); + + default: + throw new InvalidEnumArgumentException(nameof(env), (int)env, env.GetType()); + } + } + + private static ILocationService _Create(IEnumerable envs = null) + { + bool triedAtLeast1 = false; + + if (envs != null) + { + foreach (var env in envs) + { + var possibleResult = Create(env); + if (possibleResult != null) + return possibleResult; + + triedAtLeast1 = true; + } + } + + if (!triedAtLeast1) + return _Create(ARSessionFactory._defaultBestMatches); + + throw new NotSupportedException("None of the provided envs are supported by this build."); + } + } +} diff --git a/Assets/ARDK/LocationService/LocationServiceFactory.cs.meta b/Assets/ARDK/LocationService/LocationServiceFactory.cs.meta new file mode 100644 index 0000000..dd4eb22 --- /dev/null +++ b/Assets/ARDK/LocationService/LocationServiceFactory.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 0411830fc3174486b0234f7725cb75d6 +timeCreated: 1647442199 \ No newline at end of file diff --git a/Assets/ARDK/LocationService/LocationServiceStatus.cs b/Assets/ARDK/LocationService/LocationServiceStatus.cs new file mode 100644 index 0000000..2206f6e --- /dev/null +++ b/Assets/ARDK/LocationService/LocationServiceStatus.cs @@ -0,0 +1,28 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.LocationService +{ + /// Describes location session status. + public enum LocationServiceStatus + { + /// Location service is not active + Stopped, + + /// Location service has been activated, but is not yet running + Initializing, + + /// Location service is running, and location can be queried + Running, + + /// Location service failed to initialize, due to the user denying + /// app permission to device's location service + PermissionFailure, + + /// Location service failed to initialize, due to user disabling + /// location services at a device level + DeviceAccessError, + + /// Unknown reason for Unity's location service failure + UnknownError + } +} diff --git a/Assets/ARDK/LocationService/LocationServiceStatus.cs.meta b/Assets/ARDK/LocationService/LocationServiceStatus.cs.meta new file mode 100644 index 0000000..d635d81 --- /dev/null +++ b/Assets/ARDK/LocationService/LocationServiceStatus.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 66f8e12dd295541aa9d9ecd4a034e39c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/LocationService/LocationStatusUpdatedArgs.cs b/Assets/ARDK/LocationService/LocationStatusUpdatedArgs.cs new file mode 100644 index 0000000..3b17125 --- /dev/null +++ b/Assets/ARDK/LocationService/LocationStatusUpdatedArgs.cs @@ -0,0 +1,17 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.LocationService +{ + public struct LocationStatusUpdatedArgs: + IArdkEventArgs + { + public readonly LocationServiceStatus Status; + + public LocationStatusUpdatedArgs(LocationServiceStatus status) + { + Status = status; + } + } +} diff --git a/Assets/ARDK/LocationService/LocationStatusUpdatedArgs.cs.meta b/Assets/ARDK/LocationService/LocationStatusUpdatedArgs.cs.meta new file mode 100644 index 0000000..c08645b --- /dev/null +++ b/Assets/ARDK/LocationService/LocationStatusUpdatedArgs.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5b9608d661dc456e83ccd4f65b1bed5c +timeCreated: 1603981554 \ No newline at end of file diff --git a/Assets/ARDK/LocationService/LocationUpdatedArgs.cs b/Assets/ARDK/LocationService/LocationUpdatedArgs.cs new file mode 100644 index 0000000..3921a9d --- /dev/null +++ b/Assets/ARDK/LocationService/LocationUpdatedArgs.cs @@ -0,0 +1,17 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.LocationService +{ + public struct LocationUpdatedArgs: + IArdkEventArgs + { + public LocationInfo LocationInfo; + + public LocationUpdatedArgs(LocationInfo info) + { + LocationInfo = info; + } + } +} diff --git a/Assets/ARDK/LocationService/LocationUpdatedArgs.cs.meta b/Assets/ARDK/LocationService/LocationUpdatedArgs.cs.meta new file mode 100644 index 0000000..d9b4029 --- /dev/null +++ b/Assets/ARDK/LocationService/LocationUpdatedArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1aa7c4bda176f424697493b520651c6d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/LocationService/SpoofLocationService.cs b/Assets/ARDK/LocationService/SpoofLocationService.cs new file mode 100644 index 0000000..8955c62 --- /dev/null +++ b/Assets/ARDK/LocationService/SpoofLocationService.cs @@ -0,0 +1,233 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Logging; +using Niantic.ARDK.VPSCoverage; + +using UnityEngine; + +namespace Niantic.ARDK.LocationService +{ + /// @note + /// Will start near front of the Ferry Building in San Francisco, California, USA + /// unless SetLocation is called before Start to specify a different starting location. + public sealed class SpoofLocationService + : ILocationService + { + public LocationServiceStatus Status { get; private set; } = LocationServiceStatus.Stopped; + + public event ArdkEventHandler StatusUpdated; + public event ArdkEventHandler LocationUpdated; + public event ArdkEventHandler CompassUpdated; + + // Default location, if not set, is front of San Francisco Ferry Building + private LocationInfo _prevData = new LocationInfo(37.795215, -122.394073); + + public LocationInfo LastData + { + get + { + if (Status == LocationServiceStatus.Running) + return _prevData; + + ARLog._WarnRelease("Location service updates are not enabled. Check LocationService.status before querying last location."); + return new LocationInfo(); + } + } + + private float _updateDistance; + + private LatLng _travelStart; + private LatLng _travelEnd; + + private double _travelSeconds; + private double _t; + + internal SpoofLocationService() + { + } + + public void Start() + { + Start + ( + _UnityLocationService._DefaultAccuracyMeters, + _UnityLocationService._DefaultDistanceMeters + ); + } + + public void Start(float desiredAccuracyInMeters, float updateDistanceInMeters) + { + _updateDistance = updateDistanceInMeters; + + SetStatus(LocationServiceStatus.Initializing); + + _UpdateLoop.Tick += OnUpdate; + } + + public void Stop() + { + _UpdateLoop.Tick -= OnUpdate; + + SetStatus(LocationServiceStatus.Stopped); + } + + private void OnUpdate() + { + if (Status == LocationServiceStatus.Initializing) + { + SetStatus(LocationServiceStatus.Running); + + var handler = LocationUpdated; + if (handler != null) + { + var startInfo = new LocationInfo + ( + _prevData.Coordinates.Latitude, + _prevData.Coordinates.Longitude, + _prevData.Altitude, + _prevData.HorizontalAccuracy, + _prevData.VerticalAccuracy, + DateTimeOffset.Now.ToUnixTimeSeconds() + ); + + handler(new LocationUpdatedArgs(startInfo)); + } + + return; + } + + if (Status != LocationServiceStatus.Running) + return; + + if (_travelSeconds < 1) + return; + + _t += Time.deltaTime; + var alpha = _t / _travelSeconds; + + if (alpha > 1.0) + { + ARLog._Debug("Finished travel."); + _travelSeconds = 0; + _t = 0f; + } + + var currLatLng = Lerp(_travelStart, _travelEnd, alpha); + + if (currLatLng.Distance(_prevData.Coordinates) > _updateDistance) + { + SetLocation + ( + currLatLng.Latitude, + currLatLng.Longitude, + _prevData.Altitude, + _prevData.HorizontalAccuracy, + _prevData.VerticalAccuracy + ); + } + } + + public void SetStatus(LocationServiceStatus status) + { + Status = status; + + var handler = StatusUpdated; + handler?.Invoke(new LocationStatusUpdatedArgs(status)); + } + + public void SetLocation(LatLng coordinates) + { + SetLocation(coordinates.Latitude, coordinates.Longitude); + } + + public void SetLocation + ( + double latitude, + double longitude, + double altitude = double.NaN, + double horizontalAccuracy = double.NaN, + double verticalAccuracy = double.NaN + ) + { + var info = + new LocationInfo + ( + latitude, + longitude, + altitude, + horizontalAccuracy, + verticalAccuracy, + DateTimeOffset.Now.ToUnixTimeSeconds() + ); + + var heading = LatLng.Bearing(_prevData.Coordinates, info.Coordinates); + SetCompass((float)heading, DateTimeOffset.Now.ToUnixTimeSeconds()); + + _prevData = info; + + if (Status == LocationServiceStatus.Running) + { + var handler = LocationUpdated; + handler?.Invoke(new LocationUpdatedArgs(info)); + } + } + + public void SetCompass + ( + float trueHeading, + double timestamp = double.NaN + ) + { + float headingAccuracy = float.NaN; + + if (Status == LocationServiceStatus.Running) + { + var handler = CompassUpdated; + if (handler != null) + { + var args = new CompassUpdatedArgs(headingAccuracy, trueHeading, timestamp); + handler(args); + } + } + } + + /// Uses linear interpolation to travel from the current location to the specified location at + /// a constant speed. Noticeable errors may appear when locations are close to the poles. Travel + /// will only commence when the location service's status is Running. + /// @param bearing In degrees, clockwise from north + /// @param distance In meters + /// @param speed Meters per second + public void StartTravel(double bearing, double distance, float speed) + { + _travelStart = _prevData.Coordinates; + _travelEnd = _travelStart.Add(bearing, distance); + + _travelSeconds = distance / speed; + + if (_travelSeconds < 1) + { + ARLog._WarnRelease("Travel time is less than one second. This may cause no location updates to surface."); + } + + ARLog._Debug($"Starting travel of {distance} meters"); + } + + public void StartTravel(LatLng destination, float speed) + { + var bearing = LatLng.Bearing(_prevData.Coordinates, destination); + var distance = _prevData.Coordinates.Distance(destination); + StartTravel(bearing, distance, speed); + } + + private LatLng Lerp(LatLng a, LatLng b, double t) + { + var lat = a.Latitude * (1 - t) + b.Latitude * t; + var lng = a.Longitude * (1 - t) + b.Longitude * t; + + return new LatLng(lat, lng); + } + } +} diff --git a/Assets/ARDK/LocationService/SpoofLocationService.cs.meta b/Assets/ARDK/LocationService/SpoofLocationService.cs.meta new file mode 100644 index 0000000..0e83082 --- /dev/null +++ b/Assets/ARDK/LocationService/SpoofLocationService.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e04928235a734db2a544e5b9e3ecbe96 +timeCreated: 1604594286 \ No newline at end of file diff --git a/Assets/ARDK/LocationService/_NativeLocationServiceAdapter.cs b/Assets/ARDK/LocationService/_NativeLocationServiceAdapter.cs new file mode 100644 index 0000000..6ff196d --- /dev/null +++ b/Assets/ARDK/LocationService/_NativeLocationServiceAdapter.cs @@ -0,0 +1,130 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Runtime.InteropServices; + +using Niantic.ARDK.Internals; + +using UnityEngine; + +namespace Niantic.ARDK.LocationService +{ + internal sealed class _NativeLocationServiceAdapter: + IDisposable + { + private ILocationService _wrapper; + + // Private handles and code to deal with native callbacks and initialization + private IntPtr _nativeHandle = IntPtr.Zero; + + public _NativeLocationServiceAdapter + ( + Guid stageIdentifier, + ILocationService wrapper + ) + { + // Setup native C++ session + _nativeHandle = _LocationServiceSession_Init(stageIdentifier.ToByteArray()); + } + + public void AssignWrapper(ILocationService wrapper) + { + if (_wrapper != null) + { + _wrapper.StatusUpdated -= UpdateNativeStatus; + _wrapper.LocationUpdated -= UpdateNativeLocation; + _wrapper.CompassUpdated -= UpdateNativeCompass; + } + + _wrapper = wrapper; + wrapper.StatusUpdated += UpdateNativeStatus; + wrapper.LocationUpdated += UpdateNativeLocation; + wrapper.CompassUpdated += UpdateNativeCompass; + } + + ~_NativeLocationServiceAdapter() + { + Dispose(); + } + + public void Dispose() + { + if (_nativeHandle == IntPtr.Zero) + return; + + _LocationServiceSession_Release(_nativeHandle); + _nativeHandle = IntPtr.Zero; + + GC.SuppressFinalize(this); + } + + private void UpdateNativeLocation(LocationUpdatedArgs args) + { + if (_nativeHandle != IntPtr.Zero) + { + var info = args.LocationInfo; + _LocationServiceSession_LocationUpdate + ( + _nativeHandle, + (float)info.Altitude, + (float)info.HorizontalAccuracy, + (float)info.Coordinates.Latitude, + (float)info.Coordinates.Longitude, + info.Timestamp, + (float)info.VerticalAccuracy + ); + } + } + + private void UpdateNativeStatus(LocationStatusUpdatedArgs args) + { + if (_nativeHandle != IntPtr.Zero) + _LocationServiceSession_StatusUpdate(_nativeHandle, (UInt64) args.Status); + } + + private void UpdateNativeCompass(CompassUpdatedArgs args) + { + if (_nativeHandle != IntPtr.Zero) + { + _LocationServiceSession_CompassUpdate + ( + _nativeHandle, + args.TrueHeading, + args.HeadingAccuracy, + args.Timestamp + ); + } + } + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _LocationServiceSession_Init(byte[] stageIdentifier); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _LocationServiceSession_StatusUpdate + (IntPtr nativeHandle, UInt64 status); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _LocationServiceSession_LocationUpdate + ( + IntPtr nativeHandle, + float altitude, + float horizontalAccuracy, + float latitude, + float longitude, + double timestamp, + float verticalAccuracy + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _LocationServiceSession_CompassUpdate + ( + IntPtr nativeHandle, + float trueHeading, + float headingAccuracy, + double timestamp + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _LocationServiceSession_Release(IntPtr nativeHandle); + } +} diff --git a/Assets/ARDK/LocationService/_NativeLocationServiceAdapter.cs.meta b/Assets/ARDK/LocationService/_NativeLocationServiceAdapter.cs.meta new file mode 100644 index 0000000..27c6813 --- /dev/null +++ b/Assets/ARDK/LocationService/_NativeLocationServiceAdapter.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 8e7871c65d6d47738c50de3b11e10f71 +timeCreated: 1603979813 \ No newline at end of file diff --git a/Assets/ARDK/LocationService/_UnityLocationService.cs b/Assets/ARDK/LocationService/_UnityLocationService.cs new file mode 100644 index 0000000..b14067d --- /dev/null +++ b/Assets/ARDK/LocationService/_UnityLocationService.cs @@ -0,0 +1,183 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Logging; +using Niantic.ARDK.Utilities.Permissions; + +using UnityEngine; +using UnityLocationServiceStatus = UnityEngine.LocationServiceStatus; + +namespace Niantic.ARDK.LocationService +{ + /// Controls and surfaces location updates from the device. + /// @note This is currently not supported with Remote Connection. + internal sealed class _UnityLocationService: + ILocationService + { + private LocationServiceStatus _prevStatus = LocationServiceStatus.Stopped; + public LocationServiceStatus Status { get { return _prevStatus; } } + + private LocationInfo _prevData; + public LocationInfo LastData { get { return _prevData; } } + + internal const float _DefaultAccuracyMeters = 10f; + internal const float _DefaultDistanceMeters = 10f; + + private float _prevCompassHeading; + private float _prevCompassAccuracy; + + public void Start() + { + Start(_DefaultAccuracyMeters, _DefaultDistanceMeters); + } + + public void Start(float desiredAccuracyInMeters, float updateDistanceInMeters) + { + if (!Input.location.isEnabledByUser) + { + ARLog._WarnRelease("Device's location services are not enabled."); + CheckAndPublishStatusChange(LocationServiceStatus.DeviceAccessError); + return; + } + + // Start service + Input.location.Start(desiredAccuracyInMeters, updateDistanceInMeters); + Input.compass.enabled = true; + + _UpdateLoop.Tick += OnUpdate; + } + + public void Stop() + { + Input.location.Stop(); + + // Stop update loop + _UpdateLoop.Tick -= OnUpdate; + } + + // Check for location updates every frame + private void OnUpdate() + { + var currentStatus = ConvertToCompatibleStatus(Input.location.status); + CheckAndPublishStatusChange(currentStatus); + + switch (currentStatus) + { + case LocationServiceStatus.Initializing: + case LocationServiceStatus.Stopped: + // Do nothing + return; + + case LocationServiceStatus.PermissionFailure: + case LocationServiceStatus.DeviceAccessError: + Stop(); + return; + + case LocationServiceStatus.Running: + CheckAndPublishLocationChange(Input.location.lastData); + CheckAndPublishCompassChange(Input.compass); + return; + } + } + + // Convert between Unity location status and native location status + private LocationServiceStatus ConvertToCompatibleStatus(UnityLocationServiceStatus unityStatus) + { + switch (unityStatus) + { + case UnityLocationServiceStatus.Initializing: + return LocationServiceStatus.Initializing; + + case UnityLocationServiceStatus.Stopped: + return LocationServiceStatus.Stopped; + + case UnityLocationServiceStatus.Running: + return LocationServiceStatus.Running; + + case UnityLocationServiceStatus.Failed: + { +#if UNITY_ANDROID + if (!PermissionRequester.HasPermission(ARDKPermission.FineLocation)) + return LocationServiceStatus.PermissionFailure; + + if (!Input.location.isEnabledByUser) + return LocationServiceStatus.DeviceAccessError; + + return LocationServiceStatus.UnknownError; +#else + return LocationServiceStatus.PermissionFailure; +#endif + } + + default: + var message = + "No ARDK.LocationService.LocationServiceStatus compatible with " + + "UnityEngine.LocationServiceStatus {0} could be found."; + + throw new ArgumentOutOfRangeException(nameof(unityStatus), message); + } + } + + // Publish change in status of location service if needed + private void CheckAndPublishStatusChange(LocationServiceStatus newStatus) + { + if (_prevStatus == newStatus) + return; + + _prevStatus = newStatus; + + var handler = StatusUpdated; + if (handler != null) + handler(new LocationStatusUpdatedArgs(newStatus)); + } + + // Publish update in location if needed + private void CheckAndPublishLocationChange(UnityEngine.LocationInfo info) + { + if (_prevData == new LocationInfo(info)) + return; + + _prevData = new LocationInfo(info); + + var handler = LocationUpdated; + if (handler != null) + { + var args = new LocationUpdatedArgs(new LocationInfo(info)); + handler(args); + } + } + + private void CheckAndPublishCompassChange(Compass compass) + { + if (Equals(compass.trueHeading, _prevCompassHeading) && + Equals(compass.headingAccuracy, _prevCompassAccuracy)) + { + return; + } + + _prevCompassHeading = compass.trueHeading; + _prevCompassAccuracy = compass.headingAccuracy; + + var handler = CompassUpdated; + if (handler != null) + { + var args = new CompassUpdatedArgs + ( + compass.trueHeading, + compass.headingAccuracy, + compass.timestamp + ); + + handler(args); + } + } + + public event ArdkEventHandler StatusUpdated; + + public event ArdkEventHandler LocationUpdated; + + public event ArdkEventHandler CompassUpdated; + } +} diff --git a/Assets/ARDK/LocationService/_UnityLocationService.cs.meta b/Assets/ARDK/LocationService/_UnityLocationService.cs.meta new file mode 100644 index 0000000..c194f88 --- /dev/null +++ b/Assets/ARDK/LocationService/_UnityLocationService.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0fbd4757c80a844419067b31bf2cebe4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Networking.meta b/Assets/ARDK/Networking.meta new file mode 100644 index 0000000..2235c78 --- /dev/null +++ b/Assets/ARDK/Networking.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: e28065bef106a4099a276b359b11f82d +folderAsset: yes +timeCreated: 1536268520 +licenseType: Pro +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Networking/ARSim.meta b/Assets/ARDK/Networking/ARSim.meta new file mode 100644 index 0000000..4c96849 --- /dev/null +++ b/Assets/ARDK/Networking/ARSim.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7aba22d1c18d40e7872cd8f74bba015d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Networking/ARSim/ArmMessageStream.cs b/Assets/ARDK/Networking/ARSim/ArmMessageStream.cs new file mode 100644 index 0000000..6d6ddf9 --- /dev/null +++ b/Assets/ARDK/Networking/ARSim/ArmMessageStream.cs @@ -0,0 +1,299 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.IO; + +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.BinarySerialization; +using Niantic.ARDK.Networking.MultipeerNetworkingEventArgs; + +using UnityEngine; + +namespace Niantic.ARDK.Networking.ARSim +{ + public sealed class ArmMessageStream : IArmMessageStream + { + private readonly object _executorsLock = new object(); + private readonly Dictionary _executors = + new Dictionary(_ReferenceComparer.Instance); + + private readonly object _typeTagDictLock = new object(); + private readonly Dictionary _tagToTypeDict = new Dictionary(); + private readonly Dictionary _typeToTagDict = new Dictionary(); + private readonly MemoryStream _cachedMemoryStream = new MemoryStream(100); + private IMultipeerNetworking _networking; + + [Flags] + public enum MessageSource : ushort + { + Unknown = 0, + Server = 1, + Peer = 2, + } + + public ArmMessageStream(IMultipeerNetworking networking) + { + Initialize(networking); + } + + public void Initialize(IMultipeerNetworking networking) + { + if(_networking != null) + return; + + _networking = networking; + networking.PeerDataReceived += _MessageReceived; + networking.DataReceivedFromArm += _MessageReceivedFromArm; + } + + public void RegisterTypeToTag(uint tag, Type type) + { + lock (_typeTagDictLock) + { + if (_tagToTypeDict.ContainsKey(tag)) + throw new Exception("Already registered tag: " + tag); + + if (_typeToTagDict.ContainsKey(type)) + throw new Exception("Already registered type: " + type); + + _tagToTypeDict[tag] = type; + _typeToTagDict[type] = tag; + } + } + + // Returns an object that, when disposed, unregisters the actual registration. + public IDisposable RegisterHandler(Action messageExecutor, MessageSource sender) + { + if (!typeof(T).IsSealed) + throw new InvalidOperationException(typeof(T).FullName + " must be a sealed type."); + + if (messageExecutor == null) + throw new ArgumentNullException(nameof(messageExecutor)); + + lock (_executorsLock) + { + if (_executors.ContainsKey(typeof(T))) + { + string message = + "There's another message executor already registered for:" + typeof(T).FullName; + + throw new ArgumentException(message, nameof(messageExecutor)); + } + + var messageExecutorHelper = new _MessageExecutor(messageExecutor, sender); + _executors.Add(typeof(T), messageExecutorHelper); + return new _Disposer(typeof(T), messageExecutorHelper, _executorsLock, _executors); + } + } + + // Unregisters any handler for type T. Usually it is preferred to store the IDisposable + // object returned from Register and invoke it instead (in that case you only unregister + // the handler if it is your handler). + // Returns whether there was a registration for type T (which was unregistered) or not. + public bool Unregister() + { + lock (_executorsLock) + return _executors.Remove(typeof(T)); + } + + public void Send(object message, List targets, bool sendToArmServer) + { + if (message == null) + throw new ArgumentNullException(nameof(message)); + + var type = message.GetType(); + if (!type.IsSealed) + { + string errorMessage = + "message must be from a sealed type, but type " + type.FullName + " is not sealed."; + + throw new ArgumentException(errorMessage, nameof(message)); + } + + uint tag; + + lock (_typeTagDictLock) + { + if (!_typeToTagDict.ContainsKey(type)) + throw new Exception("Have not registered a tag for type: " + type); + + tag = _typeToTagDict[type]; + } + + var serializer = GlobalSerializer.GetItemSerializerOrThrow(type); + + _cachedMemoryStream.Position = 0; + _cachedMemoryStream.SetLength(0); + + using (var binarySerializer = new BinarySerializer(_cachedMemoryStream)) + serializer.Serialize(binarySerializer, message); + + var data = _cachedMemoryStream.ToArray(); + if (targets != null && targets.Count > 0) + { + _networking.SendDataToPeers + ( + tag, + data, + targets, + TransportType.UnreliableUnordered + ); + } + + if (sendToArmServer) + _networking.SendDataToArm(tag, data); + } + + public void Dispose() + { + if (_networking != null) + { + _networking.PeerDataReceived -= _MessageReceived; + _networking.DataReceivedFromArm -= _MessageReceivedFromArm; + } + } + + // Private implementation details + private void _MessageReceived(PeerDataReceivedArgs args) + { + Type type; + lock (_typeTagDictLock) + { + if (!_tagToTypeDict.ContainsKey(args.Tag)) + return; + + type = _tagToTypeDict[args.Tag]; + } + + var deserializer = GlobalSerializer.GetItemSerializerOrThrow(type); + + object message; + using (var binaryDeserializer = new BinaryDeserializer(args.CreateDataReader())) + message = deserializer.Deserialize(binaryDeserializer); + + if (message == null) + throw new ArgumentException("args had a null message. That shouldn't happen.", nameof(args)); + + _InvokeExecutor(message, MessageSource.Peer); + } + + // Private implementation details + private void _MessageReceivedFromArm(DataReceivedFromArmArgs args) + { + Type type; + lock (_typeTagDictLock) + { + if (!_tagToTypeDict.ContainsKey(args.Tag)) + return; + + type = _tagToTypeDict[args.Tag]; + } + + var deserializer = GlobalSerializer.GetItemSerializerOrThrow(type); + + object message; + using (var binaryDeserializer = new BinaryDeserializer(args.CreateDataReader())) + message = deserializer.Deserialize(binaryDeserializer); + + if (message == null) + throw new ArgumentException("args had a null message. That shouldn't happen.", nameof(args)); + + _InvokeExecutor(message, MessageSource.Server); + } + + private void _InvokeExecutor(object message, MessageSource sender) + { + var type = message.GetType(); + + _IMessageExecutor executor; + lock (_executorsLock) + _executors.TryGetValue(type, out executor); + + if (executor != null) + { + if((executor.Source & sender) != MessageSource.Unknown) + executor.Execute(message); + else + { + var warning = + "Received a message of type: {0} from source: {1}, which is not a valid sender"; + Debug.LogWarningFormat(warning, type, sender); + } + } + else + Debug.LogWarning("No executor found for message of type: " + type.FullName + "."); + } + + // To avoid using a slow DynamicInvoke on an Action, we use this interface + helper class. + private interface _IMessageExecutor + { + void Execute(object message); + MessageSource Source { get; } + } + private sealed class _MessageExecutor: + _IMessageExecutor + { + private readonly Action _action; + + private _MessageExecutor() + { + } + + internal _MessageExecutor(Action action, MessageSource source) + : this() + { + _action = action; + Source = source; + } + + public void Execute(object message) + { + T typedMessage = (T)message; + _action(typedMessage); + } + + public MessageSource Source + { + get; + private set; + } + } + + private sealed class _Disposer: + IDisposable + { + private readonly Type _type; + private readonly _IMessageExecutor _executor; + private readonly object _sharedExecutorLock; + private readonly Dictionary _sharedExecutors; + + internal _Disposer + ( + Type type, + _IMessageExecutor executor, + object sharedExecutorLock, + Dictionary sharedExecutors + ) + { + _type = type; + _executor = executor; + _sharedExecutorLock = sharedExecutorLock; + _sharedExecutors = sharedExecutors; + } + + // Only removes the existing registration if it is the same that was registered. + public void Dispose() + { + lock (_sharedExecutorLock) + { + _IMessageExecutor existingExecutor; + _sharedExecutors.TryGetValue(_type, out existingExecutor); + + if (_executor == existingExecutor) + _sharedExecutors.Remove(_type); + } + } + } + } +} diff --git a/Assets/ARDK/Networking/ARSim/ArmMessageStream.cs.meta b/Assets/ARDK/Networking/ARSim/ArmMessageStream.cs.meta new file mode 100644 index 0000000..7b1a8de --- /dev/null +++ b/Assets/ARDK/Networking/ARSim/ArmMessageStream.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d0cbd93f95ca4494a222bfee0a4e5044 +timeCreated: 1587591961 \ No newline at end of file diff --git a/Assets/ARDK/Networking/ARSim/IArmMessageStream.cs b/Assets/ARDK/Networking/ARSim/IArmMessageStream.cs new file mode 100644 index 0000000..e1f2ff0 --- /dev/null +++ b/Assets/ARDK/Networking/ARSim/IArmMessageStream.cs @@ -0,0 +1,29 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; + +/// @namespace Niantic.ARDK.Networking.ARSim +/// @brief A set of tools to support server-authoritative AR gameplay. +/// @note Currently in internal development, and not useable +namespace Niantic.ARDK.Networking.ARSim { + /// + /// A message stream that handles tagging and serialization of objects, and automatically executing + /// an Action upon receiving the correct object type. Handles messages from peers in the session + /// as well as the server. + /// @note Currently in internal development, and not useable + /// + public interface IArmMessageStream : + IDisposable + { + IDisposable RegisterHandler(Action handler, ArmMessageStream.MessageSource sender); + + bool Unregister(); + + void Send(object message, List targets, bool sendToArmServer); + + void Initialize(IMultipeerNetworking networking); + + void RegisterTypeToTag(uint tag, Type type); + } +} diff --git a/Assets/ARDK/Networking/ARSim/IArmMessageStream.cs.meta b/Assets/ARDK/Networking/ARSim/IArmMessageStream.cs.meta new file mode 100644 index 0000000..4f0687e --- /dev/null +++ b/Assets/ARDK/Networking/ARSim/IArmMessageStream.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 79b9b99f6c7b452d8dadfd668db8f22f +timeCreated: 1587591442 \ No newline at end of file diff --git a/Assets/ARDK/Networking/ARSim/Spawning.meta b/Assets/ARDK/Networking/ARSim/Spawning.meta new file mode 100644 index 0000000..8640a4d --- /dev/null +++ b/Assets/ARDK/Networking/ARSim/Spawning.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ece89a6328b0482e8d83a817ee61c6a2 +timeCreated: 1597184953 \ No newline at end of file diff --git a/Assets/ARDK/Networking/ARSim/Spawning/AddressablePrefabManifest.cs b/Assets/ARDK/Networking/ARSim/Spawning/AddressablePrefabManifest.cs new file mode 100644 index 0000000..e2dc3c9 --- /dev/null +++ b/Assets/ARDK/Networking/ARSim/Spawning/AddressablePrefabManifest.cs @@ -0,0 +1,34 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.Collections.Generic; + +using Niantic.ARDK.Utilities.Collections; + +using UnityEngine; + +namespace Niantic.ARDK.Networking.ARSim.Spawning +{ + public sealed class AddressablePrefabManifest : IAddressablePrefabManifest + { + public IReadOnlyDictionary PrefabManifest { get; private set; } + private readonly Dictionary _prefabManifest; + + public AddressablePrefabManifest() + { + _prefabManifest = new Dictionary(); + PrefabManifest = new _ReadOnlyDictionary(_prefabManifest); + } + + public bool RegisterPrefab(string identifier, GameObject prefab) + { + if (_prefabManifest.ContainsKey(identifier)) + { + Debug.LogWarning("PrefabManifest already contains key: " + identifier); + return false; + } + + _prefabManifest[identifier] = prefab; + return true; + } + } +} diff --git a/Assets/ARDK/Networking/ARSim/Spawning/AddressablePrefabManifest.cs.meta b/Assets/ARDK/Networking/ARSim/Spawning/AddressablePrefabManifest.cs.meta new file mode 100644 index 0000000..45f3950 --- /dev/null +++ b/Assets/ARDK/Networking/ARSim/Spawning/AddressablePrefabManifest.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 2ac62e061c6b4e1a82f6ae930a4edf91 +timeCreated: 1591235072 \ No newline at end of file diff --git a/Assets/ARDK/Networking/ARSim/Spawning/GameObjectSpawning.meta b/Assets/ARDK/Networking/ARSim/Spawning/GameObjectSpawning.meta new file mode 100644 index 0000000..dd29e05 --- /dev/null +++ b/Assets/ARDK/Networking/ARSim/Spawning/GameObjectSpawning.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: cb2ed474668d4c79a565cdc36eaf779b +timeCreated: 1598051032 \ No newline at end of file diff --git a/Assets/ARDK/Networking/ARSim/Spawning/GameObjectSpawning/IGameObjectInstantiator.cs b/Assets/ARDK/Networking/ARSim/Spawning/GameObjectSpawning/IGameObjectInstantiator.cs new file mode 100644 index 0000000..881f650 --- /dev/null +++ b/Assets/ARDK/Networking/ARSim/Spawning/GameObjectSpawning/IGameObjectInstantiator.cs @@ -0,0 +1,32 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using UnityEngine; + +namespace Niantic.ARDK.Networking.ARSim.Spawning.GameObjectSpawning +{ + /// + /// An interface wrapping Unity's Instantiate and Destroy methods, to support alternative spawning + /// patterns (Zenject, object pools, etc). + /// + public interface IGameObjectInstantiator + { + GameObject Instantiate(GameObject original); + + GameObject Instantiate + ( + GameObject original, + Transform parent, + bool instantiateInWorldSpace = false + ); + + GameObject Instantiate + ( + GameObject original, + Vector3 position, + Quaternion rotation, + Transform parent = null + ); + + void Destroy(GameObject obj, float timeToDelay = 0.0f); + } +} diff --git a/Assets/ARDK/Networking/ARSim/Spawning/GameObjectSpawning/IGameObjectInstantiator.cs.meta b/Assets/ARDK/Networking/ARSim/Spawning/GameObjectSpawning/IGameObjectInstantiator.cs.meta new file mode 100644 index 0000000..5efcc0a --- /dev/null +++ b/Assets/ARDK/Networking/ARSim/Spawning/GameObjectSpawning/IGameObjectInstantiator.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5068b93a2f6347bab74110ae870b6fdc +timeCreated: 1598051044 \ No newline at end of file diff --git a/Assets/ARDK/Networking/ARSim/Spawning/GameObjectSpawning/UnityGameObjectInstantiator.cs b/Assets/ARDK/Networking/ARSim/Spawning/GameObjectSpawning/UnityGameObjectInstantiator.cs new file mode 100644 index 0000000..75cb084 --- /dev/null +++ b/Assets/ARDK/Networking/ARSim/Spawning/GameObjectSpawning/UnityGameObjectInstantiator.cs @@ -0,0 +1,50 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using UnityEngine; + +namespace Niantic.ARDK.Networking.ARSim.Spawning.GameObjectSpawning +{ + /// + /// Implementation of an IGameObjectInstantiator that uses basic UnityEngine calls. + /// + public sealed class UnityGameObjectInstantiator : + IGameObjectInstantiator + { + /// + public GameObject Instantiate(GameObject original) + { + return UnityEngine.Object.Instantiate(original); + } + + /// + public GameObject Instantiate + ( + GameObject original, + Transform parent, + bool instantiateInWorldSpace = false + ) + { + return UnityEngine.Object.Instantiate(original, parent, instantiateInWorldSpace); + } + + /// + public GameObject Instantiate + ( + GameObject original, + Vector3 position, + Quaternion rotation, + Transform parent = null + ) + { + return parent != null ? + UnityEngine.Object.Instantiate(original, position, rotation, parent) : + UnityEngine.Object.Instantiate(original, position, rotation); + } + + /// + public void Destroy(GameObject obj, float timeToDelay = 0.0f) + { + UnityEngine.Object.Destroy(obj, timeToDelay); + } + } +} diff --git a/Assets/ARDK/Networking/ARSim/Spawning/GameObjectSpawning/UnityGameObjectInstantiator.cs.meta b/Assets/ARDK/Networking/ARSim/Spawning/GameObjectSpawning/UnityGameObjectInstantiator.cs.meta new file mode 100644 index 0000000..e3788d0 --- /dev/null +++ b/Assets/ARDK/Networking/ARSim/Spawning/GameObjectSpawning/UnityGameObjectInstantiator.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a4456ae798f943ff8aa5b79d4e025f6f +timeCreated: 1598051485 \ No newline at end of file diff --git a/Assets/ARDK/Networking/ARSim/Spawning/IAddressablePrefabManifest.cs b/Assets/ARDK/Networking/ARSim/Spawning/IAddressablePrefabManifest.cs new file mode 100644 index 0000000..8192465 --- /dev/null +++ b/Assets/ARDK/Networking/ARSim/Spawning/IAddressablePrefabManifest.cs @@ -0,0 +1,19 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.Collections.Generic; + +using UnityEngine; + +namespace Niantic.ARDK.Networking.ARSim.Spawning +{ + /// + /// Contains a dictionary mapping string identifiers to prefabs, so that prefabs can be dynamically + /// registered and spawned. + /// @note Currently in internal development, and not useable + /// + public interface IAddressablePrefabManifest + { + IReadOnlyDictionary PrefabManifest { get; } + bool RegisterPrefab(string identifier, GameObject prefab); + } +} diff --git a/Assets/ARDK/Networking/ARSim/Spawning/IAddressablePrefabManifest.cs.meta b/Assets/ARDK/Networking/ARSim/Spawning/IAddressablePrefabManifest.cs.meta new file mode 100644 index 0000000..3cef28b --- /dev/null +++ b/Assets/ARDK/Networking/ARSim/Spawning/IAddressablePrefabManifest.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 45f821097dce47c3a4f9bb7610b3b780 +timeCreated: 1591234941 \ No newline at end of file diff --git a/Assets/ARDK/Networking/ARSim/Spawning/IServerAuthoritativeSpawner.cs b/Assets/ARDK/Networking/ARSim/Spawning/IServerAuthoritativeSpawner.cs new file mode 100644 index 0000000..e343ff1 --- /dev/null +++ b/Assets/ARDK/Networking/ARSim/Spawning/IServerAuthoritativeSpawner.cs @@ -0,0 +1,41 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.Networking.ARSim.Spawning.GameObjectSpawning; +using Niantic.ARDK.Networking.ARSim.Spawning.ServerSpawningEventArgs; +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.Networking.ARSim.Spawning +{ + /// + /// Interface for a server authoritative spawner. Raises events when an object is spawned or + /// despawned, and should handle all internal logic related to spawning/despawning. + /// @note Currently in internal development, and not useable + /// + public interface IServerAuthoritativeSpawner : + IDisposable + { + // Event that is called when the server spawns an object + event ArdkEventHandler DidSpawnObject; + + // Event that is called when the server despawns an object + event ArdkEventHandler WillDespawnObject; + + // Load an IAddressablePrefabManifest to this spawner, to map prefabIDs to prefabs + void LoadPrefabManifest(IAddressablePrefabManifest manifest); + + // Spawn an object with the specified parameters + // @note Public for now to allow for catchup spawning. Once spawn messages are guaranteed (KV), + // this will be internal + void Spawn(ServerAuthoritativeSpawnerBase.ServerSpawnParams spawnParams); + + /// + /// Set the instantiator that the spawner will use to create gameobjects. Different + /// IGameObjectInstantiators can be implemented to use custom spawning behaviour, such as + /// dependency injection or object pooling. + /// + /// + void SetGameObjectInstantiator(IGameObjectInstantiator instantiator); + } +} diff --git a/Assets/ARDK/Networking/ARSim/Spawning/IServerAuthoritativeSpawner.cs.meta b/Assets/ARDK/Networking/ARSim/Spawning/IServerAuthoritativeSpawner.cs.meta new file mode 100644 index 0000000..09af9bf --- /dev/null +++ b/Assets/ARDK/Networking/ARSim/Spawning/IServerAuthoritativeSpawner.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d7a02e9dd2aa4103ba52eb27d7969a4b +timeCreated: 1597186016 \ No newline at end of file diff --git a/Assets/ARDK/Networking/ARSim/Spawning/ServerAuthoritativeSpawnerBase.cs b/Assets/ARDK/Networking/ARSim/Spawning/ServerAuthoritativeSpawnerBase.cs new file mode 100644 index 0000000..89009da --- /dev/null +++ b/Assets/ARDK/Networking/ARSim/Spawning/ServerAuthoritativeSpawnerBase.cs @@ -0,0 +1,192 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.Collections.Generic; + +using Niantic.ARDK.Networking.ARSim.Spawning.GameObjectSpawning; +using Niantic.ARDK.Networking.ARSim.Spawning.ServerSpawningEventArgs; +using Niantic.ARDK.Utilities; + +using UnityEngine; + +namespace Niantic.ARDK.Networking.ARSim.Spawning +{ + /// + /// Abstract base for a server authoritative spawner. Contains base implementation for maintaining + /// and verifying spawning objects, despawning objects, and updating the positions of spawned + /// objects. + /// + public abstract class ServerAuthoritativeSpawnerBase : + IServerAuthoritativeSpawner + { + // Structs that contains spawning/despawning/updating parameters + + // @note This is public for catch-up spawning. Will be made internal after spawning is guaranteed. + public struct ServerSpawnParams + { + public string ObjectId { get; set; } + public string PrefabId { get; set; } + public Vector3 Location { get; set; } + public Vector3 Rotation { get; set; } + } + + protected struct UpdatePositionParams + { + public string ObjectId { get; set; } + public Vector3 Location { get; set; } + public Vector3 Rotation { get; set; } + } + + protected struct ServerDespawnParams + { + public string ObjectId { get; set; } + } + + private bool _haveSpawnedObject; + + private IAddressablePrefabManifest _manifest; + private readonly Dictionary _spawnedObjects = + new Dictionary(); + private readonly Dictionary _cachedUpdateParams = + new Dictionary(); + + protected IGameObjectInstantiator Instantiator; + + /// + public event ArdkEventHandler DidSpawnObject; + /// + public event ArdkEventHandler WillDespawnObject; + + /// + public abstract void Dispose(); + + /// + public void LoadPrefabManifest(IAddressablePrefabManifest manifest) + { + _manifest = manifest; + } + + /// + /// Spawn an object with the specified parameters + /// @note This is public for catch-up spawning. Will be made internal after + /// spawning is guaranteed. + /// + /// Details of the object to spawn + public void Spawn(ServerSpawnParams spawnParams) + { + if (_manifest == null) + { + Debug.LogError("Got a spawn message, but have not loaded a manifest"); + return; + } + + if (!_manifest.PrefabManifest.ContainsKey(spawnParams.PrefabId)) + { + Debug.Log("Manifest does not contain prefab with ID: " + spawnParams.PrefabId); + return; + } + + var id = spawnParams.ObjectId; + if (_spawnedObjects.ContainsKey(id)) + { + Debug.LogFormat("Object of id {0} has already been spawned", id); + return; + } + + Vector3 location, rotation; + + if (_cachedUpdateParams.ContainsKey(id)) + { + var param = _cachedUpdateParams[id]; + location = param.Location; + rotation = param.Rotation; + _cachedUpdateParams.Remove(id); + } + else + { + location = spawnParams.Location; + rotation = spawnParams.Rotation; + } + + var quat = Quaternion.Euler(rotation); + if(Instantiator == null) + Instantiator = new UnityGameObjectInstantiator(); + + var obj = Instantiator.Instantiate(_manifest.PrefabManifest[spawnParams.PrefabId], location, quat); + _haveSpawnedObject = true; + _spawnedObjects[id] = obj; + + var handler = DidSpawnObject; + if (handler != null) + { + var args = new ServerSpawnedArgs(id, obj); + handler(args); + } + } + + /// + /// Set the instantiator that the spawner will use to create gameobjects. Different + /// IGameObjectInstantiators can be implemented to use custom spawning behaviour, such as + /// dependency injection or object pooling. + /// @note If no instantiator is provided by the first spawn call, a UnityGameObjectInstantiator + /// will be used. + /// + public void SetGameObjectInstantiator(IGameObjectInstantiator instantiator) + { + Instantiator = instantiator; + if (_haveSpawnedObject) + { + Debug.LogWarning + ( + "Set a new instantiator after an object has been spawned. Object management" + + "may not work as intended." + ); + } + } + + /// + /// Update the position of a specified object. If the object has not been spawned yet, cache the + /// parameters until it is spawned, then update its position on spawn. + /// + /// Details of the object to update + protected void UpdatePosition(UpdatePositionParams updateParams) + { + string id = updateParams.ObjectId; + if (!_spawnedObjects.ContainsKey(id)) + { + _cachedUpdateParams[id] = updateParams; + return; + } + _spawnedObjects[id].transform.position = updateParams.Location; + _spawnedObjects[id].transform.rotation = Quaternion.Euler(updateParams.Rotation); + } + + /// + /// Despawn an object that has been spawned + /// + /// Details of the object to despawn + protected void Despawn(ServerDespawnParams despawnParams) + { + var id = despawnParams.ObjectId; + if (!_spawnedObjects.ContainsKey(id)) + { + Debug.LogFormat("Object of id {0} has not been spawned, or has been despawned already", id); + return; + } + + var obj = _spawnedObjects[id]; + _spawnedObjects.Remove(id); + + var handler = WillDespawnObject; + if (handler != null) + { + var args = new ServerDespawnedArgs(id, obj); + handler(args); + } + + if(Instantiator == null) + Instantiator = new UnityGameObjectInstantiator(); + + Instantiator.Destroy(obj); + } + } +} diff --git a/Assets/ARDK/Networking/ARSim/Spawning/ServerAuthoritativeSpawnerBase.cs.meta b/Assets/ARDK/Networking/ARSim/Spawning/ServerAuthoritativeSpawnerBase.cs.meta new file mode 100644 index 0000000..1cd80cd --- /dev/null +++ b/Assets/ARDK/Networking/ARSim/Spawning/ServerAuthoritativeSpawnerBase.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a4fb93f4117f4184bd9e7763dee8d8e7 +timeCreated: 1597187814 \ No newline at end of file diff --git a/Assets/ARDK/Networking/ARSim/Spawning/ServerSpawningEventArgs.meta b/Assets/ARDK/Networking/ARSim/Spawning/ServerSpawningEventArgs.meta new file mode 100644 index 0000000..6f877a6 --- /dev/null +++ b/Assets/ARDK/Networking/ARSim/Spawning/ServerSpawningEventArgs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 30908a51f2c245c4aeb9f4c2c64753e7 +timeCreated: 1597186568 \ No newline at end of file diff --git a/Assets/ARDK/Networking/ARSim/Spawning/ServerSpawningEventArgs/ServerDespawnedArgs.cs b/Assets/ARDK/Networking/ARSim/Spawning/ServerSpawningEventArgs/ServerDespawnedArgs.cs new file mode 100644 index 0000000..6b4ba5c --- /dev/null +++ b/Assets/ARDK/Networking/ARSim/Spawning/ServerSpawningEventArgs/ServerDespawnedArgs.cs @@ -0,0 +1,22 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Utilities; + +using UnityEngine; + +namespace Niantic.ARDK.Networking.ARSim.Spawning.ServerSpawningEventArgs +{ + public struct ServerDespawnedArgs : + IArdkEventArgs + { + public ServerDespawnedArgs(string objectId, GameObject gameObject) : + this() + { + ObjectId = objectId; + GameObject = gameObject; + } + + public string ObjectId { get; private set; } + public GameObject GameObject { get; private set; } + } +} diff --git a/Assets/ARDK/Networking/ARSim/Spawning/ServerSpawningEventArgs/ServerDespawnedArgs.cs.meta b/Assets/ARDK/Networking/ARSim/Spawning/ServerSpawningEventArgs/ServerDespawnedArgs.cs.meta new file mode 100644 index 0000000..c8661cc --- /dev/null +++ b/Assets/ARDK/Networking/ARSim/Spawning/ServerSpawningEventArgs/ServerDespawnedArgs.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5407ac11f5b944ad9ecbdc7893f4cedd +timeCreated: 1597186736 \ No newline at end of file diff --git a/Assets/ARDK/Networking/ARSim/Spawning/ServerSpawningEventArgs/ServerSpawnedArgs.cs b/Assets/ARDK/Networking/ARSim/Spawning/ServerSpawningEventArgs/ServerSpawnedArgs.cs new file mode 100644 index 0000000..2700d69 --- /dev/null +++ b/Assets/ARDK/Networking/ARSim/Spawning/ServerSpawningEventArgs/ServerSpawnedArgs.cs @@ -0,0 +1,22 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Utilities; + +using UnityEngine; + +namespace Niantic.ARDK.Networking.ARSim.Spawning.ServerSpawningEventArgs +{ + public struct ServerSpawnedArgs : + IArdkEventArgs + { + public ServerSpawnedArgs(string objectId, GameObject gameObject): + this() + { + ObjectId = objectId; + GameObject = gameObject; + } + + public string ObjectId { get; private set; } + public GameObject GameObject { get; private set; } + } +} diff --git a/Assets/ARDK/Networking/ARSim/Spawning/ServerSpawningEventArgs/ServerSpawnedArgs.cs.meta b/Assets/ARDK/Networking/ARSim/Spawning/ServerSpawningEventArgs/ServerSpawnedArgs.cs.meta new file mode 100644 index 0000000..2badd23 --- /dev/null +++ b/Assets/ARDK/Networking/ARSim/Spawning/ServerSpawningEventArgs/ServerSpawnedArgs.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5ff2c0d1abb94e3d9663eec27960aa64 +timeCreated: 1597186579 \ No newline at end of file diff --git a/Assets/ARDK/Networking/Clock.meta b/Assets/ARDK/Networking/Clock.meta new file mode 100644 index 0000000..95c0e60 --- /dev/null +++ b/Assets/ARDK/Networking/Clock.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 519d664e6dc1043c480d13443e5fd2eb +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Networking/Clock/ICoordinatedClock.cs b/Assets/ARDK/Networking/Clock/ICoordinatedClock.cs new file mode 100644 index 0000000..b215de9 --- /dev/null +++ b/Assets/ARDK/Networking/Clock/ICoordinatedClock.cs @@ -0,0 +1,45 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace Niantic.ARDK.Networking.Clock +{ + /// + /// Reports the quality of the timestamp returned by the Coordinated Clock + /// + public enum CoordinatedClockTimestampQuality: + byte + { + /// There has not been an update from the server + Invalid = 0, + + /// The server has sent updates, but there is still variance in syncing + Syncing, + + /// The timestamp is now synchronized with the server + Stable + }; + + /// + /// A coordinated clock that synchronizes with a server sided clock so that all peers within + /// the same networking session the same timestamp. + /// + public interface ICoordinatedClock + { + /// + /// The current server synchronized time + /// + /// @note CurrentCorrectedTime itself has no guarantees of epoch or standard - it is a timestamp + /// in milliseconds. It is better used as a stopwatch or timer, rather than used to represent a + /// real world time (though this can be done by locally comparing it to another known clock). + /// + long CurrentCorrectedTime { get; } + + /// + /// The quality of the timestamp returned by this CoordinatedClock + /// + CoordinatedClockTimestampQuality SyncStatus { get; } + } +} diff --git a/Assets/ARDK/Networking/Clock/ICoordinatedClock.cs.meta b/Assets/ARDK/Networking/Clock/ICoordinatedClock.cs.meta new file mode 100644 index 0000000..a9b380e --- /dev/null +++ b/Assets/ARDK/Networking/Clock/ICoordinatedClock.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5d7915d357ca94ebda15b52f830fd6e7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Networking/Clock/LocalCoordinatedClock.cs b/Assets/ARDK/Networking/Clock/LocalCoordinatedClock.cs new file mode 100644 index 0000000..b4e7016 --- /dev/null +++ b/Assets/ARDK/Networking/Clock/LocalCoordinatedClock.cs @@ -0,0 +1,35 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace Niantic.ARDK.Networking.Clock +{ + /// + /// Local implementation of coordinated clock, does not require a network connection. + /// Just returns the system time. + /// + public sealed class LocalCoordinatedClock: + ICoordinatedClock + { + /// + public long CurrentCorrectedTime + { + get + { + return (DateTime.UtcNow - new DateTime(1970, 1, 1)).Ticks / 10000L; + } + } + + /// + public CoordinatedClockTimestampQuality SyncStatus + { + get + { + return CoordinatedClockTimestampQuality.Stable; + } + } + } +} diff --git a/Assets/ARDK/Networking/Clock/LocalCoordinatedClock.cs.meta b/Assets/ARDK/Networking/Clock/LocalCoordinatedClock.cs.meta new file mode 100644 index 0000000..bfa92ce --- /dev/null +++ b/Assets/ARDK/Networking/Clock/LocalCoordinatedClock.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 473494cf4a0c34daba1203fba9415985 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Networking/Clock/_NativeCoordinatedClock.cs b/Assets/ARDK/Networking/Clock/_NativeCoordinatedClock.cs new file mode 100644 index 0000000..f04ac1b --- /dev/null +++ b/Assets/ARDK/Networking/Clock/_NativeCoordinatedClock.cs @@ -0,0 +1,56 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Runtime.InteropServices; +using Niantic.ARDK.Internals; + +namespace Niantic.ARDK.Networking.Clock +{ + /// Wrapper around the native layer coordinated clock that gets updates from the multipeer + /// networking systems. + internal sealed class _NativeCoordinatedClock: + ICoordinatedClock + { + // Private handles and code to deal with native callbacks and initialization + private IntPtr _nativeHandle; + + internal _NativeCoordinatedClock(Guid stageIdentifier) + { + _nativeHandle = _NAR_CoordinatedClock_Init(stageIdentifier.ToByteArray()); + } + + ~_NativeCoordinatedClock() + { + if (_nativeHandle != IntPtr.Zero) + _NAR_CoordinatedClock_Release(_nativeHandle); + } + + public long CurrentCorrectedTime + { + get + { + return _NAR_CoordinatedClock_GetCurrentCorrectedTime(_nativeHandle); + } + } + + public CoordinatedClockTimestampQuality SyncStatus + { + get + { + return (CoordinatedClockTimestampQuality)_NAR_CoordinatedClock_GetSyncStatus(_nativeHandle); + } + } + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NAR_CoordinatedClock_Init(byte[] stageIdentifier); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern long _NAR_CoordinatedClock_GetCurrentCorrectedTime(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NAR_CoordinatedClock_Release(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern byte _NAR_CoordinatedClock_GetSyncStatus(IntPtr nativeHandle); + } +} diff --git a/Assets/ARDK/Networking/Clock/_NativeCoordinatedClock.cs.meta b/Assets/ARDK/Networking/Clock/_NativeCoordinatedClock.cs.meta new file mode 100644 index 0000000..7bfc34b --- /dev/null +++ b/Assets/ARDK/Networking/Clock/_NativeCoordinatedClock.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4badc20d9e4c541f0a5f0e0fd618a393 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Networking/DataInfo.cs b/Assets/ARDK/Networking/DataInfo.cs new file mode 100644 index 0000000..c633eb8 --- /dev/null +++ b/Assets/ARDK/Networking/DataInfo.cs @@ -0,0 +1,11 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.Networking +{ + public struct DataInfo + { + public uint tag; + public IPeer peer; + public TransportType transportType; + } +} \ No newline at end of file diff --git a/Assets/ARDK/Networking/DataInfo.cs.meta b/Assets/ARDK/Networking/DataInfo.cs.meta new file mode 100644 index 0000000..fe25207 --- /dev/null +++ b/Assets/ARDK/Networking/DataInfo.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 06c4d684de08478bb6760f5e0cc40fec +timeCreated: 1607554831 \ No newline at end of file diff --git a/Assets/ARDK/Networking/HLAPI.meta b/Assets/ARDK/Networking/HLAPI.meta new file mode 100644 index 0000000..5feb28d --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: a36aa34c93e894bac99d41977fa24b92 +folderAsset: yes +timeCreated: 1546555171 +licenseType: Pro +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Networking/HLAPI/Authority.meta b/Assets/ARDK/Networking/HLAPI/Authority.meta new file mode 100644 index 0000000..199173b --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Authority.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c1e67e1a3199493aa98b47c6f0914f80 +timeCreated: 1536519834 \ No newline at end of file diff --git a/Assets/ARDK/Networking/HLAPI/Authority/GreedyAuthorityReplicator.cs b/Assets/ARDK/Networking/HLAPI/Authority/GreedyAuthorityReplicator.cs new file mode 100644 index 0000000..191d3c6 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Authority/GreedyAuthorityReplicator.cs @@ -0,0 +1,149 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Linq; + +using Niantic.ARDK.Utilities.Extensions; +using Niantic.ARDK.Networking.HLAPI.Data; +using Niantic.ARDK.Utilities.Collections; +using Niantic.ARDK.Utilities.Logging; + +namespace Niantic.ARDK.Networking.HLAPI.Authority +{ + /// + /// That will greedily take roles. If it can be proven locally that the role is + /// able to be taken by the local peer, then the local peer will assume it can take the role, otherwise it will fail. + /// This can result in race conditions if two peers try to claim a role at the same time so it should only be used in + /// scenarios where authority can be statically determined (such as authority is always host). + /// + public sealed class GreedyAuthorityReplicator: + NetworkedDataHandlerBase, + IAuthorityReplicator + { + private Dictionary _peerToRoleLookup = new Dictionary(); + + private Dictionary> _roleToPeerLookup = + new Dictionary>(); + + private bool _isDirty; + + /// The identifier of this + /// The group to use + public GreedyAuthorityReplicator(string identifier, INetworkGroup group) + { + Identifier = identifier; + + if (group == null) + return; + + group.RegisterHandler(this); + } + + public Role LocalRole + { + get + { + var self = GetSelfOrNull(); + + return self == null ? Role.None : RoleOfPeer(Group.Session.Networking.Self); + } + } + + public IReadOnlyCollection PeersOfRole(Role role) + { + return _roleToPeerLookup.GetOrInsertNew(role).AsArdkReadOnly(); + } + + public Role RoleOfPeer(IPeer peer) + { + return _peerToRoleLookup.GetOrInsert(peer, Role.None); + } + + public void TryClaimRole(Role role, Action onPass, Action onFail) + { + var self = GetSelfOrNull(); + + if (self == null) + { + onFail(); + return; + } + + var allowMultiple = role != Role.Authority; + + var peersOfSameRole = PeersOfRole(role); + + if (peersOfSameRole.Count > 1 && !allowMultiple) + { + onFail(); + return; + } + + if (peersOfSameRole.Count == 1 && !allowMultiple && !peersOfSameRole.Contains(self)) + { + onFail(); + return; + } + + ChangeRoleOfPeer(self, role); + _isDirty = true; + + onPass(); + } + + private void ChangeRoleOfPeer(IPeer peer, Role newRole) + { + var prevRole = RoleOfPeer(peer); + _roleToPeerLookup.GetOrInsertNew(prevRole).Remove(peer); + _roleToPeerLookup.GetOrInsertNew(newRole).Add(peer); + _peerToRoleLookup[peer] = newRole; + + ARLog._DebugFormat + ( + "Authority Replicator on group {0} updating role of peer {1} from {2} to {3}", + false, + Group.NetworkId.RawId, + peer, + prevRole, + newRole + ); + } + + protected override object GetDataToSend + ( + ICollection targetPeers, + ReplicationMode replicationMode + ) + { + if (replicationMode.Transport != TransportType.ReliableOrdered) + return NothingToWrite; + + // Only send if there is a pending role transfer, or it is an initial com. + if (!_isDirty && !replicationMode.IsInitial) + return NothingToWrite; + + var targetPeersHash = new HashSet(targetPeers); + + // Only send if broadcasting or it's an initial com. + if (!targetPeersHash.SetEquals(Group.Session.Networking.OtherPeers) && !replicationMode.IsInitial) + return NothingToWrite; + + // Clear the dirty bit when sending as a broadcast. + if (targetPeersHash.SetEquals(Group.Session.Networking.OtherPeers)) + _isDirty = false; + + return LocalRole; + } + + protected override void HandleReceivedData + ( + object data, + IPeer sender, + ReplicationMode replicationMode + ) + { + ChangeRoleOfPeer(sender, (Role)data); + } + } +} diff --git a/Assets/ARDK/Networking/HLAPI/Authority/GreedyAuthorityReplicator.cs.meta b/Assets/ARDK/Networking/HLAPI/Authority/GreedyAuthorityReplicator.cs.meta new file mode 100644 index 0000000..7e4dfe0 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Authority/GreedyAuthorityReplicator.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: aba596f2adb040f3a09971356a92b14c +timeCreated: 1538085359 \ No newline at end of file diff --git a/Assets/ARDK/Networking/HLAPI/Authority/IAuthorityReplicator.cs b/Assets/ARDK/Networking/HLAPI/Authority/IAuthorityReplicator.cs new file mode 100644 index 0000000..21e5a49 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Authority/IAuthorityReplicator.cs @@ -0,0 +1,49 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Linq; + +using Niantic.ARDK.Utilities.Collections; + +namespace Niantic.ARDK.Networking.HLAPI.Authority +{ + /// + /// A replicator that will replicate authority info about a network entity. + /// + public interface IAuthorityReplicator: INetworkedDataHandler + { + /// + /// The local role of this network entity. + /// + Role LocalRole { get; } + + /// + /// Gets all peers that are of a given role. + /// This method should never return null, if needed an empty collection is returned. + /// + IReadOnlyCollection PeersOfRole(Role role); + + /// + /// Gets the role of a peer. + /// + Role RoleOfPeer(IPeer peer); + + /// + /// Trys to claim a role for the local peer. + /// + /// The role to claim. + /// Called if the role could be claimed. + /// Called if the role could not be claimed. + void TryClaimRole(Role role, Action onPass, Action onFail); + } + + + public static class AuthorityReplicatorExtension + { + public static IPeer PeerOfRole(this IAuthorityReplicator replicator, Role role) + { + return replicator.PeersOfRole(role).FirstOrDefault(); + } + } +} diff --git a/Assets/ARDK/Networking/HLAPI/Authority/IAuthorityReplicator.cs.meta b/Assets/ARDK/Networking/HLAPI/Authority/IAuthorityReplicator.cs.meta new file mode 100644 index 0000000..43d1d0d --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Authority/IAuthorityReplicator.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: b2a7243f6da349fb82f5764185d30f1a +timeCreated: 1579817485 \ No newline at end of file diff --git a/Assets/ARDK/Networking/HLAPI/Authority/Role.cs b/Assets/ARDK/Networking/HLAPI/Authority/Role.cs new file mode 100644 index 0000000..30df94c --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Authority/Role.cs @@ -0,0 +1,14 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +namespace Niantic.ARDK.Networking.HLAPI.Authority { + /// + /// The common roles that can be used for network authority. + /// + public enum Role { + None = 0, + Observer, + Authority = UInt16.MaxValue, + } +} \ No newline at end of file diff --git a/Assets/ARDK/Networking/HLAPI/Authority/Role.cs.meta b/Assets/ARDK/Networking/HLAPI/Authority/Role.cs.meta new file mode 100644 index 0000000..56f4856 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Authority/Role.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 7296ad15269f4b6fb37a9e3508135899 +timeCreated: 1536519853 \ No newline at end of file diff --git a/Assets/ARDK/Networking/HLAPI/Data.meta b/Assets/ARDK/Networking/HLAPI/Data.meta new file mode 100644 index 0000000..a7629e0 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Data.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c48ed99275364a08a230ad00f7e53a11 +timeCreated: 1536519067 \ No newline at end of file diff --git a/Assets/ARDK/Networking/HLAPI/Data/NetworkedDataDescriptor.cs b/Assets/ARDK/Networking/HLAPI/Data/NetworkedDataDescriptor.cs new file mode 100644 index 0000000..c404012 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Data/NetworkedDataDescriptor.cs @@ -0,0 +1,92 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Linq; + +using Niantic.ARDK.Networking.HLAPI.Authority; +using Niantic.ARDK.Utilities.Collections; + +namespace Niantic.ARDK.Networking.HLAPI.Data +{ + public struct NetworkedDataDescriptor + { + public Func> GetSenders { get; private set; } + public Func> GetReceivers { get; private set; } + public TransportType TransportType { get; private set; } + + public NetworkedDataDescriptor( + Func> getSenders, + Func> getReceivers, + TransportType transportType) + : this() + { + GetSenders = getSenders; + GetReceivers = getReceivers; + TransportType = transportType; + } + } + + public static class NetworkedDataDescriptorExtension + { + public static NetworkedDataDescriptor AuthorityToObserverDescriptor( + this IAuthorityReplicator auth, + TransportType transportType) + { + return new NetworkedDataDescriptor( + () => auth.PeersOfRole(Role.Authority), + () => auth.PeersOfRole(Role.Observer), + transportType); + } + + public static NetworkedDataDescriptor ObserversToAuthorityDescriptor( + this IAuthorityReplicator auth, + TransportType transportType) + { + return new NetworkedDataDescriptor( + () => auth.PeersOfRole(Role.Observer), + () => auth.PeersOfRole(Role.Authority), + transportType); + } + + // TODO: unit tests + public static NetworkedDataDescriptor AnyToAnyDescriptor( + this IAuthorityReplicator auth, + TransportType transportType) + { + return new NetworkedDataDescriptor( + () => GetAllPeersFromAuth(auth), + () => GetAllPeersFromAuth(auth), + transportType + ); + } + + public static NetworkedDataDescriptor AnyToAnyDescriptor( + this IMultipeerNetworking networking, + TransportType transportType) + { + return new NetworkedDataDescriptor( + () => GetAllPeersFromNetworking(networking), + () => GetAllPeersFromNetworking(networking), + transportType); + } + + private static IEnumerable GetAllPeersFromAuth(IAuthorityReplicator auth) + { + return auth.Group.Session.Networking == null ? + EmptyArray.Instance : + GetAllPeersFromNetworking(auth.Group.Session.Networking); + } + + private static IEnumerable GetAllPeersFromNetworking(IMultipeerNetworking networking) + { + if (!networking.IsConnected) + yield break; + + foreach (var peer in networking.OtherPeers) + yield return peer; + + yield return networking.Self; + } + } +} diff --git a/Assets/ARDK/Networking/HLAPI/Data/NetworkedDataDescriptor.cs.meta b/Assets/ARDK/Networking/HLAPI/Data/NetworkedDataDescriptor.cs.meta new file mode 100644 index 0000000..b188e60 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Data/NetworkedDataDescriptor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c3950c80787e4f5ca08225f3a767f9a2 +timeCreated: 1579821284 \ No newline at end of file diff --git a/Assets/ARDK/Networking/HLAPI/Data/PacketInfo.cs b/Assets/ARDK/Networking/HLAPI/Data/PacketInfo.cs new file mode 100644 index 0000000..1e2e0bd --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Data/PacketInfo.cs @@ -0,0 +1,19 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.Networking.HLAPI.Data +{ + public struct PacketInfo + { + public object Data { get; private set; } + public IPeer Sender { get; private set; } + public ReplicationMode ReplicationMode { get; private set; } + + public PacketInfo(object data, IPeer sender, ReplicationMode replicationMode): + this() + { + Data = data; + Sender = sender; + ReplicationMode = replicationMode; + } + } +} diff --git a/Assets/ARDK/Networking/HLAPI/Data/PacketInfo.cs.meta b/Assets/ARDK/Networking/HLAPI/Data/PacketInfo.cs.meta new file mode 100644 index 0000000..36073fc --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Data/PacketInfo.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3d7d2e265b494d3f93cb8994187446fc +timeCreated: 1579821663 \ No newline at end of file diff --git a/Assets/ARDK/Networking/HLAPI/Data/ReplicationMode.cs b/Assets/ARDK/Networking/HLAPI/Data/ReplicationMode.cs new file mode 100644 index 0000000..ca162d8 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Data/ReplicationMode.cs @@ -0,0 +1,18 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.Networking.HLAPI.Data { + /// + /// Information about how data is being replicated. + /// + public struct ReplicationMode { + /// + /// The transport being replicated over. + /// + public TransportType Transport { get; set; } + + /// + /// If this is the first time communicating with this particual set of peers. + /// + public bool IsInitial { get; set; } + } +} \ No newline at end of file diff --git a/Assets/ARDK/Networking/HLAPI/Data/ReplicationMode.cs.meta b/Assets/ARDK/Networking/HLAPI/Data/ReplicationMode.cs.meta new file mode 100644 index 0000000..9e109b5 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Data/ReplicationMode.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 121c264ff42649a3bc08241cf04ed514 +timeCreated: 1536960198 \ No newline at end of file diff --git a/Assets/ARDK/Networking/HLAPI/HlapiSession.cs b/Assets/ARDK/Networking/HLAPI/HlapiSession.cs new file mode 100644 index 0000000..766b304 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/HlapiSession.cs @@ -0,0 +1,563 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +using Niantic.ARDK.Utilities.Extensions; +using Niantic.ARDK.Networking.HLAPI.Data; +using Niantic.ARDK.Networking.HLAPI.Routing; +using Niantic.ARDK.Networking.MultipeerNetworkingEventArgs; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.BinarySerialization; +using Niantic.ARDK.Utilities.Collections; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; +using UnityEngine.SceneManagement; + +namespace Niantic.ARDK.Networking.HLAPI +{ + /// + /// A that will hook up with . + /// + public sealed class HlapiSession: + IHlapiSession + { + private readonly uint _messageTag; + + private readonly Dictionary _groupLookup = + new Dictionary(); + + private readonly Dictionary _unhandledPackets = + new Dictionary(); + + private readonly List> _broadcastGroups = new List>(); + private readonly HashSet> _sentGroups = new HashSet>(); + + private IMultipeerNetworking _networking; + + private readonly TransportType[] _transportTypeList = + { + TransportType.ReliableOrdered, + TransportType.ReliableUnordered, + TransportType.UnreliableOrdered, + TransportType.UnreliableUnordered + }; + + private readonly MemoryStream _cachedStream = new MemoryStream(1024); + + /// + public IMultipeerNetworking Networking + { + get + { + return _networking; + } + } + + /// + public void UnregisterGroup(INetworkGroup group) + { + ARLog._DebugFormat + ( + "Removing group {0} from HlapiSession with tag {1}", + false, + group.NetworkId.RawId, + _messageTag + ); + _groupLookup.Remove(group.NetworkId); + } + + /// + public INetworkGroup CreateAndRegisterGroup(NetworkId groupId) + { + if (_groupLookup.ContainsKey(groupId)) + throw new ArgumentException("Group id " + groupId + " already exists"); + + var unhandledPackets = _unhandledPackets.GetOrDefault(groupId); + + _groupLookup[groupId] = new NetworkGroup(groupId, this, unhandledPackets); + + ARLog._DebugFormat + ( + "Created and registered group {0} to HlapiSession with tag {1}", + false, + groupId.RawId, + _messageTag + ); + + if (unhandledPackets != null) + { + _unhandledPackets.Remove(groupId); + ARLog._DebugFormat("Removing cached packets for group: {0}", false, groupId.RawId); + } + + return _groupLookup[groupId]; + } + + /// + public void RegisterGroup(INetworkGroup group) + { + var groupId = group.NetworkId; + + if (_groupLookup.ContainsKey(groupId)) + throw new ArgumentException("Group id " + groupId + " already exists"); + + var handlerBase = group as NetworkedDataHandlerBase; + if (handlerBase == null) + throw new Exception("Implement your INetworkedDataHandler as a NetworkedDataHandlerBase"); + + var unhandledPackets = _unhandledPackets.GetOrDefault(groupId); + + group.ReceiveCachedDataFromSession(this, unhandledPackets); + + _groupLookup[groupId] = group; + + ARLog._DebugFormat + ( + "Registered group {0} to HlapiSession with tag {1}", + false, + groupId.RawId, + _messageTag + ); + + if (unhandledPackets != null) + { + _unhandledPackets.Remove(groupId); + ARLog._DebugFormat("Removing cached packets for group: {0}", false, groupId.RawId); + } + } + + /// + /// Create an unmanaged HlapiSession (must be manually ticked) that will + /// attach itself to the first IMultipeerNetworking that is created and send all data over + /// that network. If an IMultipeerNetworking has already been initialized, this will + /// automatically attach itself that that networking (will attach itself to the first + /// networking on MultipeerNetworking.Networkings if there are multiple already). + /// + /// Message tag that all messages pertaining to this manager + /// will use + public HlapiSession(uint messageTag) + { + _messageTag = messageTag; + + MultipeerNetworkingFactory.NetworkingInitialized += OnAnyMultipeerSessionDidInitialize; + ARLog._Debug + ( + "Created an HlapiSession using tag {0}, waiting for the first networking initialized" + ); + } + + /// + /// Create an unmanaged HlapiSession (must be manually ticked) that will + /// attach itself to the specified IMultipeerNetworking. This is useful if you want + /// to manage ticking (message batching + sending) behaviour, rather than rely on + /// the automatic per-frame sending behaviour + /// + /// Message tag that all messages pertaining to this manager + /// will use + /// The networking session this HLAPI session will use + public HlapiSession(uint messageTag, IMultipeerNetworking networking) + { + _messageTag = messageTag; + + ARLog._DebugFormat("Created an HlapiSession using tag {0}", false, _messageTag); + OnAnyMultipeerSessionDidInitialize(new AnyMultipeerNetworkingInitializedArgs(networking)); + } + + /// + /// Call this to query all attached groups (and their attached INetworkedDataHandlers) for any + /// data that they have accumulated and send that data. The specific data that will be written + /// and sent depends on the implementation of the handler (ie. a transform packer will only + /// check and send the transform at the time of this call, regardless of how many changes + /// there have been between calls to this method, while a message stream will send all queued + /// messages between the previous and current calls). + /// Data that is received will be processed when the message is received, and is independent of calling + /// this method + /// + public void SendQueuedData() + { + // Only tick if there is actually a network + if (_networking == null) + { + ARLog._WarnFormat + ( + "Ticking HlapiSession with tag {0}, but it is not connected to a networking", + true, + _messageTag + ); + return; + } + + // Query each group/handler with each transport type, since they may have varying protocols + foreach (var transportType in _transportTypeList) + { + foreach (var broadcastGroup in _broadcastGroups) + { + // Build a payload that pertains to this specific peer group/transport type + var stream = _cachedStream; + stream.Position = 0; + stream.SetLength(0); + + // Initial message flag for each new group + var isInitial = !_sentGroups.Contains(broadcastGroup); + stream.WriteByte(isInitial ? (byte)1 : (byte)0); + + var dataStartMarker = stream.Position; + + var replicationMode = new ReplicationMode(); + replicationMode.IsInitial = isInitial; + replicationMode.Transport = transportType; + + // Query groups and attempt to write data to the buffer + object data = GetDataToSend(broadcastGroup, replicationMode); + if (data != NetworkedDataHandlerBase.NothingToWrite) + using (var serializer = new BinarySerializer(stream)) + serializer.Serialize(data); + + // If any data has been written, send the data to the relevant peer(s) + long distance = stream.Position - dataStartMarker; + if (Math.Abs(distance) > 0) + { + var buffer = stream.ToArray(); + + IPeer[] targets; + if (broadcastGroup.Count == 1 && _networking.OtherPeers.Count > 1) + targets = new[] { broadcastGroup.First() }; + else + targets = _networking.OtherPeers.ToArray(); + + _networking.SendDataToPeers(_messageTag, buffer, targets, transportType); + } + } + } + + // Remember that every group has had an initial message sent + _sentGroups.UnionWith(_broadcastGroups); + } + + // Upon any changes to the peer list, regenerate the broadcast group list (each individual peer, + // as well as all peers in the session) + private void RefreshBroadcastGroups() + { + _broadcastGroups.Clear(); + + var remotePeers = _networking.OtherPeers; + + if (remotePeers == null) + return; + + foreach (var peer in remotePeers) + _broadcastGroups.Add(new HashSet(new[] {peer})); + + if (remotePeers.Count > 1) + _broadcastGroups.Add(new HashSet(remotePeers)); + } + + public void Dispose() + { + MultipeerNetworkingFactory.NetworkingInitialized -= OnAnyMultipeerSessionDidInitialize; + + if (_networking == null) + return; + + _networking.PeerDataReceived -= OnDidReceiveDataFromPeer; + _networking.PeerAdded -= OnDidAddPeer; + _networking.PeerRemoved -= OnDidRemovePeer; + _networking.Connected -= OnDidConnect; + } + + // This is only subscribed to if no IMultipeerNetworking is explicitly passed in during + // construction. + private void OnAnyMultipeerSessionDidInitialize(AnyMultipeerNetworkingInitializedArgs args) + { + if (_networking != null) + return; + + var networking = args.Networking; + _networking = networking; + + networking.PeerDataReceived += OnDidReceiveDataFromPeer; + + networking.PeerAdded += OnDidAddPeer; + networking.PeerRemoved += OnDidRemovePeer; + + networking.Connected += OnDidConnect; + } + + // Handle data that is received + private void OnDidReceiveDataFromPeer(PeerDataReceivedArgs args) + { + // If the data does not belong this manager, do nothing + if (args.Tag != _messageTag) + return; + + using (var stream = args.CreateDataReader()) + { + // Attempt to pass the received data to the corresponding group(s) + var isInitial = stream.ReadByte() == 1; + + var array = (_NetworkIdAndData[])GlobalSerializer.Deserialize(stream); + + var replicationMode = new ReplicationMode(); + replicationMode.Transport = args.TransportType; + replicationMode.IsInitial = isInitial; + + ARLog._DebugFormat + ( + "HlapiSession {0} got data containing {1} elements", + true, + _messageTag, + array.Length + ); + ReceiveData(array, args.Peer, replicationMode); + } + } + + private void OnDidAddPeer(PeerAddedArgs args) + { + RefreshBroadcastGroups(); + } + + private void OnDidRemovePeer(PeerRemovedArgs args) + { + RefreshBroadcastGroups(); + } + + private void OnDidConnect(ConnectedArgs args) + { + RefreshBroadcastGroups(); + } + + // TODO: Find a better place for this. + [Serializable] + internal struct _NetworkIdAndData + { + internal NetworkId _networkId; + internal object _data; + } + + /// + /// Called when the session should send data. + /// + /// The target peers to send to. + /// The mode to send. + private object GetDataToSend(HashSet target, ReplicationMode mode) + { + var list = new List<_NetworkIdAndData>(); + + // Query each attached group for data to be written + foreach (var networkGroupPair in _groupLookup) + { + var handler = (NetworkedDataHandlerBase)networkGroupPair.Value; + var data = handler.InternalGetDataToSend(target, mode); + + if (data != NetworkedDataHandlerBase.NothingToWrite) + { + ARLog._DebugFormat + ( + "HlapiSession {0} is queueing some data for group {1}", + true, + _messageTag, + networkGroupPair.Key + ); + list.Add + ( + new _NetworkIdAndData + { + _networkId = networkGroupPair.Key, _data = data + } + ); + } + } + + if (list.Count == 0) + return NetworkedDataHandlerBase.NothingToWrite; + + return list.ToArray(); + } + + /// + /// Called to receive data from a payload. + /// + /// The payload to receive. + /// The peer it is from. + /// The mode it was sent with. + private void ReceiveData(_NetworkIdAndData[] array, IPeer from, ReplicationMode mode) + { + foreach (var pair in array) + { + INetworkGroup group; + + // If there is a group that can handle this data (same NetworkId), give it to that group; + // else, cache reliable messages until the relevant group is opened. + bool found = _groupLookup.TryGetValue(pair._networkId, out group); + var handler = group as NetworkedDataHandlerBase; + if (found && handler != null) + { + ARLog._DebugFormat + ( + "HlapiSession {0} routing data to group {1}", + true, + _messageTag, + group.NetworkId.RawId + ); + handler.InternalReceiveData(pair._data, from, mode); + } + else + { + //If the transport type is not reliable, do not cache the data + bool mustSkip = + mode.Transport != TransportType.ReliableOrdered && + mode.Transport != TransportType.ReliableUnordered; + + if (mustSkip) + continue; + + var unknownGroup = + _unhandledPackets.GetOrInsert(pair._networkId, () => new UnhandledPacketCache()); + + ARLog._DebugFormat + ( + "HlapiSession {0} could not find group {1}, attempting to cache data", + true, + _messageTag, + pair._networkId.RawId + ); + unknownGroup.AttemptCachePayload(pair._data, from, mode); + } + } + } + } + + /// + /// Provides a HlapiSession that is tied to each _NativeMultipeerNetworking instance + /// that is created. These HlapiSessions can be accessed with the Guid of the networking instance, + /// and will be destroyed when the networking instance is destroyed. + /// + [DefaultExecutionOrder(Int32.MinValue)] + public static class HlapiSessionExtension + { + // Arbitrary, but constant, tag so that all peers are in agreement of the tag to use for + // the HlapiSession + private const uint HlapiSessionTag = 920348; + + private static readonly object _sessionCreationLock = new object(); + + private static readonly ConcurrentDictionary + _managedSessionLookup = new ConcurrentDictionary(); + + private static readonly _ReadOnlyDictionary _roManagedSessionLookup; + + private static readonly ConcurrentDictionary + _sceneSessionLookup = new ConcurrentDictionary(); + + static HlapiSessionExtension() + { + _roManagedSessionLookup = new _ReadOnlyDictionary(_managedSessionLookup); + } + + /// + /// The currently active HlapiSessions managed by this class + /// + public static IReadOnlyDictionary ManagedSessionLookup + { + get { return _roManagedSessionLookup; } + } + + public static HlapiSession GetOrCreateManagedSession(this Scene scene) + { + HlapiSession session; + if (_sceneSessionLookup.TryGetValue(scene, out session)) + return session; + + // Ideally we should use GetOrAdd from the ConcurrentDictionary. Unfortunately, GetOrAdd + // allows 2 values to be created in parallel and simply lets one of them "be garbage + // collected". The problem is that the HlapiSession actually registers itself in static + // events, so we should not allow 2 or more instances to be created in parallel. + lock (_sessionCreationLock) + { + // Check again inside the lock. If the value is still not there, then we can safely + // create and add it. + if (_sceneSessionLookup.TryGetValue(scene, out session)) + return session; + + var sceneHashCodeAsUint = (uint)scene.name.GetHashCode(); + ARLog._DebugFormat("Creating an HlapiSession with tag {0}", false, sceneHashCodeAsUint); + session = new HlapiSession(sceneHashCodeAsUint); + + if (!_sceneSessionLookup.TryAdd(scene, session)) + throw new InvalidOperationException("2 sessions were created for the same scene."); + } + + return session; + } + + /// + /// Gets or creates a HlapiSession that corresponds to a specific networking + /// instance. + /// + /// The networking instance to get a HlapiSession for + /// The HlapiSession that corresponds to the input network + public static HlapiSession GetOrCreateManagedSession(this IMultipeerNetworking networking) + { + HlapiSession session; + + var stageIdentifier = networking.StageIdentifier; + if (_managedSessionLookup.TryGetValue(stageIdentifier, out session)) + return session; + + // Similar to GetOrCreateManagedSession, we need to guarantee we never create 2 sessions + // in parallel. + lock(_sessionCreationLock) + { + // During the lock acquisition, a session might have been created. So check again. + if (_managedSessionLookup.TryGetValue(stageIdentifier, out session)) + return session; + + // Now we can safely create a new session. + + ARLog._DebugFormat + ( + "Creating an HlapiSession with tag {0}, attached to networking {1}", + false, + HlapiSessionTag, + stageIdentifier + ); + + session = new HlapiSession(HlapiSessionTag, networking); + if (!_managedSessionLookup.TryAdd(stageIdentifier, session)) + throw new InvalidOperationException("Duplicated StageIdentifier."); + + networking.Deinitialized += + (ignored) => _managedSessionLookup.TryRemove(stageIdentifier, out _); + } + + return session; + } + + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + private static void Startup() + { + _UpdateLoop.LateTick += Update; + SceneManager.sceneUnloaded += OnSceneUnloaded; + } + + private static void Update() + { + foreach (var session in _managedSessionLookup.Values) + session.SendQueuedData(); + + foreach (var session in _sceneSessionLookup.Values) + session.SendQueuedData(); + } + + private static void OnSceneUnloaded(Scene scene) + { + _sceneSessionLookup.TryRemove(scene, out _); + } + } +} diff --git a/Assets/ARDK/Networking/HLAPI/HlapiSession.cs.meta b/Assets/ARDK/Networking/HLAPI/HlapiSession.cs.meta new file mode 100644 index 0000000..24c3de2 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/HlapiSession.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 635eb2f630f3458fabd38befe2c00cd8 +timeCreated: 1538161419 \ No newline at end of file diff --git a/Assets/ARDK/Networking/HLAPI/IHlapiSession.cs b/Assets/ARDK/Networking/HLAPI/IHlapiSession.cs new file mode 100644 index 0000000..93d1738 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/IHlapiSession.cs @@ -0,0 +1,49 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.Networking.HLAPI.Routing; + +namespace Niantic.ARDK.Networking.HLAPI +{ + /// Responsible for replicating registered groups and their data across the network, by + /// addressing and routing messages so that a registered data handler will always receive + /// data from its corresponding data handler (on the other end of the networking + /// object). Implementations of this interface use an IMultipeerNetworking object to + /// send and receive messages + public interface IHlapiSession: + IDisposable + { + /// + /// Creates a new network group that is attached to this session. + /// + /// Unique identifier for this group, equivalent to a ulong + INetworkGroup CreateAndRegisterGroup(NetworkId groupId); + + /// + /// Register an existing group to this session. + /// + /// + void RegisterGroup(INetworkGroup group); + + /// + /// Close the specified group + /// + /// Group to remove from this session + void UnregisterGroup(INetworkGroup group); + + /// + /// The networking object that this session is attached to. May be null if the session is created + /// with no networking object. In that case, this will become the first initialized + /// IMultipeerNetworking object, and all data will be passed along that network. + /// + IMultipeerNetworking Networking { get; } + + /// + /// Query all network groups attached to this session to write any relevant data that their + /// data handlers have accumulated since the last call of this method to buffers, then send + /// the buffers to each relevant peer. + /// + void SendQueuedData(); + } +} \ No newline at end of file diff --git a/Assets/ARDK/Networking/HLAPI/IHlapiSession.cs.meta b/Assets/ARDK/Networking/HLAPI/IHlapiSession.cs.meta new file mode 100644 index 0000000..550a100 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/IHlapiSession.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 89bf1ab4d4df465d8499acc63e06c288 +timeCreated: 1537146651 \ No newline at end of file diff --git a/Assets/ARDK/Networking/HLAPI/INetworkGroup.cs b/Assets/ARDK/Networking/HLAPI/INetworkGroup.cs new file mode 100644 index 0000000..6292347 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/INetworkGroup.cs @@ -0,0 +1,53 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Networking.HLAPI.Routing; + +namespace Niantic.ARDK.Networking.HLAPI +{ + /// + /// A group of information to be replicated over the network. Can loosely be thought of as an + /// "object" - it handles a number of registered data handlers, which all have a lifetime + /// that is tied to this group. + /// + public interface INetworkGroup: + INetworkedDataHandler + { + /// + /// Register an INetworkedDataHandler to this group, which will handler sending/receiving data + /// as well as routing. + /// + /// + void RegisterHandler(INetworkedDataHandler handler); + + /// + /// Unregisters a handler from this group, such that it will no longer send/receive data. However, + /// the handler itself is not destroyed by this call. + /// + /// + void UnregisterHandler(INetworkedDataHandler handler); + + /// + /// Creates a new nested group that is attached to this group. + /// + /// Unique identifier for this group, equivalent to a ulong + INetworkGroup CreateNestedGroup(NetworkId groupId); + + /// + /// The IHlapiSession object that this group is attached to. + /// + IHlapiSession Session { get; } + + /// + /// The NetworkId representing this group + /// + NetworkId NetworkId { get; } + + /// + /// Initialize the Session and receive any cached data addressed to this NetworkGroup. This will + /// generally be called by the HlapiSession + /// + /// + /// + void ReceiveCachedDataFromSession(IHlapiSession session, UnhandledPacketCache cache); + } +} diff --git a/Assets/ARDK/Networking/HLAPI/INetworkGroup.cs.meta b/Assets/ARDK/Networking/HLAPI/INetworkGroup.cs.meta new file mode 100644 index 0000000..af85a2c --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/INetworkGroup.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c1e784b9bce64b209de78738352546d0 +timeCreated: 1536518864 \ No newline at end of file diff --git a/Assets/ARDK/Networking/HLAPI/INetworkedDataHandler.cs b/Assets/ARDK/Networking/HLAPI/INetworkedDataHandler.cs new file mode 100644 index 0000000..60c503c --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/INetworkedDataHandler.cs @@ -0,0 +1,30 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.Networking.HLAPI +{ + /// + /// Interface for a data handler that is attached to the HLAPI through an INetworkGroup. + /// @note Implement custom data handlers by extending `NetworkedDataHandlerBase` rather than this + /// class. The protected methods in that abstract class define the data handler's behaviour + /// with sending/receiving data. However, users should never call those methods, as it is the + /// role of the INetworkGroup to send/receive data. + /// + public interface INetworkedDataHandler + { + /// + /// Unique identifier for this data handler. Two handlers with the same Identifier cannot be + /// registered to the same INetworkGroup + /// + string Identifier { get; } + + /// + /// Group that this data handler is attached to. + /// + INetworkGroup Group { get; } + + /// + /// Unregister this handler from its current group. + /// + void Unregister(); + } +} diff --git a/Assets/ARDK/Networking/HLAPI/INetworkedDataHandler.cs.meta b/Assets/ARDK/Networking/HLAPI/INetworkedDataHandler.cs.meta new file mode 100644 index 0000000..46e0316 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/INetworkedDataHandler.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ea2cef29b6994bfe858918bfcdf2632f +timeCreated: 1579821265 \ No newline at end of file diff --git a/Assets/ARDK/Networking/HLAPI/NetworkGroup.cs b/Assets/ARDK/Networking/HLAPI/NetworkGroup.cs new file mode 100644 index 0000000..1cab0b1 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/NetworkGroup.cs @@ -0,0 +1,351 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; + +using Niantic.ARDK.Utilities.Extensions; +using Niantic.ARDK.Networking.HLAPI.Data; +using Niantic.ARDK.Networking.HLAPI.Routing; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Logging; + +namespace Niantic.ARDK.Networking.HLAPI +{ + /// + /// A network group that is attached to an IHlapiSession. Handles routing to data handlers that + /// are registered to this group. + /// + internal sealed class NetworkGroup: + NetworkedDataHandlerBase, + INetworkGroup + { + private readonly NetworkId _id; + private IHlapiSession _session; + private UnhandledPacketCache _cachedPacketInfo; + + private readonly Dictionary _handlerDict = + new Dictionary(); + + private readonly List _cachedNestedGroups = new List(); + + public NetworkGroup(NetworkId id) + { + _id = id; + Identifier = _id.ToString(); + } + + /// + /// Create a NetworkGroup that is attached to the IHlapiSession. Pass in any unhandled packets + /// so that they may be handled when Handlers are registered, or create a new one if there are + /// no unhandled packets (to cache packets addressed to unknown handlers). + /// + /// + /// + /// + public NetworkGroup(NetworkId id, IHlapiSession session, UnhandledPacketCache cache): + this(id) + { + _session = session; + _cachedPacketInfo = cache ?? new UnhandledPacketCache(); + } + + public NetworkId NetworkId + { + get + { + return _id; + } + } + + /// + public IHlapiSession Session + { + get + { + return _session; + } + } + + /// + public void RegisterHandler(INetworkedDataHandler handler) + { + var handlerBase = handler as NetworkedDataHandlerBase; + + if (handlerBase == null) + throw new Exception("Implement your INetworkedDataHandler as a NetworkedDataHandlerBase"); + + if (handlerBase.Identifier == null) + throw new Exception("Attempting to register a handler without an identifier"); + + if (_handlerDict.ContainsKey(handlerBase.Identifier)) + { + string message = "Already registered a handler with identifier: " + handlerBase.Identifier; + throw new Exception(message); + } + + // Tell the handler that this is now its group + handlerBase.RegisterToGroup(this); + + // Register this handler to this group + var identifier = handlerBase.Identifier; + _handlerDict[identifier] = handlerBase; + + ARLog._DebugFormat + ( + "Registered handler {0} to group {1}", + false, + handler.Identifier, + _id.RawId + ); + + // If there are cached packets belonging to the new handler, queue a callback to handle these + // packets next frame. This is necessary since handling the packets now may lead to data that + // will be processed before the handler's subscriptions are all set up. + if (_cachedPacketInfo.PacketLookup.ContainsKey(identifier)) + { + ARLog._DebugFormat + ( + "Group {0} found cached data for handler {1}, queueing a handle request", + false, + _id.RawId, + identifier + ); + _CallbackQueue.QueueCallback + ( + () => + { + if (!_cachedPacketInfo.PacketLookup.ContainsKey(identifier)) + { + ARLog._WarnFormat + ( + "Handling queued data failed for identifier {0}, no data found", + false, + identifier + ); + return; + } + + _cachedPacketInfo.HandleCached(identifier, handlerBase); + + _cachedPacketInfo.PacketLookup.Remove(identifier); + } + ); + } + } + + /// + public INetworkGroup CreateNestedGroup(NetworkId groupId) + { + if (_handlerDict.ContainsKey(groupId.ToString())) + { + string message = "Already registered a handler with identifier: " + groupId.ToString(); + throw new Exception(message); + } + + var newGroup = new NetworkGroup(groupId); + + if (_session == null) + _cachedNestedGroups.Add(newGroup); + else + newGroup.ReceiveCachedDataFromSession(_session, new UnhandledPacketCache()); + + RegisterHandler(newGroup); + ARLog._DebugFormat + ( + "Created a nested group with Id {0}, attached to group {1}", + false, + groupId.RawId, + _id.RawId + ); + return newGroup; + } + + /// + public void ReceiveCachedDataFromSession(IHlapiSession session, UnhandledPacketCache cache) + { + _session = session; + _cachedPacketInfo = cache ?? new UnhandledPacketCache(); + + if (_cachedNestedGroups.Count > 0) + foreach (var group in _cachedNestedGroups) + group.ReceiveCachedDataFromSession(_session, new UnhandledPacketCache()); + } + + [Serializable] + internal struct _NetworkGroupData + { + internal string _key; + internal object _data; + } + + /// + protected override void HandleReceivedData + ( + object allData, + IPeer sender, + ReplicationMode replicationMode + ) + { + var removingUnknowns = new HashSet(); + + foreach (var unknownHandler in _cachedPacketInfo.PacketLookup) + { + // Try to lookup cached unknown channels + var handler = _handlerDict.GetOrDefault(unknownHandler.Key); + + if (handler == null) + continue; + + // Have the channel handle its cached messages + _cachedPacketInfo.HandleCached(unknownHandler.Key, handler); + + removingUnknowns.Add(unknownHandler.Key); + } + + foreach (var removingUnknown in removingUnknowns) + _cachedPacketInfo.PacketLookup.Remove(removingUnknown); + + var array = (_NetworkGroupData[])allData; + foreach (var groupData in array) + { + NetworkedDataHandlerBase handler; + + //If the channel is known, receive data, otherwise, cache it + if (_handlerDict.TryGetValue(groupData._key, out handler)) + handler.InternalReceiveData(groupData._data, sender, replicationMode); + else + { + //If the transport type is not reliable, do not cache the data + bool shouldSkip = + replicationMode.Transport != TransportType.ReliableOrdered && + replicationMode.Transport != TransportType.ReliableUnordered; + + if (shouldSkip) + continue; + + var unknownPacketQueue = _cachedPacketInfo.PacketLookup.GetOrInsertNew(groupData._key); + unknownPacketQueue.Enqueue(new PacketInfo(groupData._data, sender, replicationMode)); + } + } + } + + /// + public override void Unregister() + { + // If this is not a nested group, close it from the session + if (Group == null) + { + _session.UnregisterGroup(this); + return; + } + + // Otherwise, close it from the owning group + base.Unregister(); + } + + /// + public void UnregisterHandler(INetworkedDataHandler handler) + { + if (!_handlerDict.ContainsKey(handler.Identifier)) + return; + + ARLog._DebugFormat + ( + "Unregistering handler {0} from group {1}", + false, + handler.Identifier, + _id.RawId + ); + _handlerDict[handler.Identifier].UnregisterFromGroup(); + _handlerDict.Remove(handler.Identifier); + } + + /// + protected override object GetDataToSend + ( + ICollection targetPeers, + ReplicationMode mode + ) + { + var list = new List<_NetworkGroupData>(); + + foreach (var handlerPair in _handlerDict) + { + var handlerResult = handlerPair.Value.InternalGetDataToSend(targetPeers, mode); + + if (handlerResult != NothingToWrite) + { + ARLog._DebugFormat + ( + "Enqueueing data from handler {0}", + true, + handlerPair.Key + ); + + list.Add + ( + new _NetworkGroupData + { + _key = handlerPair.Key, _data = handlerResult + } + ); + } + } + + if (list.Count == 0) + return NothingToWrite; + + return list.ToArray(); + } + } + + /// + /// Definition of a class that caches and handles packets belonging to unknown Groups/Handlers. + /// Follows the Group/Handler hierarchy (one UnhandledPacketCache per group, with a dictionary + /// of strings, which map to handlers' Identifiers). + /// + public sealed class UnhandledPacketCache + { + public readonly Dictionary> PacketLookup = + new Dictionary>(); + + /// + /// Attempt to cache a payload in this group. Shares a static data count with all other cached + /// packets sent through the HLAPI. + // TODO: Size limit for cached data + /// + /// Payload to cache + /// Peer that sent the data + /// Information about the transport type and whether it is an + /// initial message + public void AttemptCachePayload(object data, IPeer sender, ReplicationMode replicationMode) + { + var array = (NetworkGroup._NetworkGroupData[])data; + foreach (var groupData in array) + { + ARLog._DebugFormat("Caching data for identifier {0}", false, groupData._key); + var packet = PacketLookup.GetOrInsertNew(groupData._key); + packet.Enqueue(new PacketInfo(groupData._data, sender, replicationMode)); + } + } + + /// + /// Handle data that is cached with the handler's Identifier + /// + /// Identifier to look for in cached packets + /// Handler to handle cached data with + public void HandleCached(string identifier, NetworkedDataHandlerBase handler) + { + ARLog._DebugFormat + ( + "Handling cached data for identifier {0}, found {1} packets", + false, + identifier, + PacketLookup[identifier].Count + ); + + foreach (var packetInfo in PacketLookup[identifier]) + handler.InternalReceiveData(packetInfo.Data, packetInfo.Sender, packetInfo.ReplicationMode); + } + } +} diff --git a/Assets/ARDK/Networking/HLAPI/NetworkGroup.cs.meta b/Assets/ARDK/Networking/HLAPI/NetworkGroup.cs.meta new file mode 100644 index 0000000..fb045c5 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/NetworkGroup.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 27069c9f5454433b8221a3bb2df44b51 +timeCreated: 1582321222 \ No newline at end of file diff --git a/Assets/ARDK/Networking/HLAPI/NetworkedDataHandlerBase.cs b/Assets/ARDK/Networking/HLAPI/NetworkedDataHandlerBase.cs new file mode 100644 index 0000000..22dd90b --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/NetworkedDataHandlerBase.cs @@ -0,0 +1,126 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; + +using Niantic.ARDK.Networking.HLAPI.Data; + +namespace Niantic.ARDK.Networking.HLAPI +{ + /// + /// Abstract class to extend to implement custom data handlers for the HLAPI. The protected + /// methods will define the data handler's behaviour with sending/receiving data, but cannot + /// be accessed through the INetworkedDataHandler interface (users should never call these methods) + /// + public abstract class NetworkedDataHandlerBase: + INetworkedDataHandler + { + // Return this value during WriteToDataBuilder if this handler result should be ignored + // altogether. + public static readonly object NothingToWrite = new object(); + + /// + public string Identifier { get; internal set; } + + /// + public INetworkGroup Group { get; private set; } + + /// + /// Inform this handler that the group has registered this handler. A handler cannot be registered + /// to more than one group at a time. + /// + /// The group that has registered this handler + internal void RegisterToGroup(INetworkGroup group) + { + if (Group != null) + { + throw new Exception( + String.Format( + "This handler: {0} has already been registered to group: {1}", + Identifier, + Group.Identifier)); + } + + Group = group; + } + + internal void UnregisterFromGroup() + { + if (Group == null) + { + throw new Exception( + String.Format( + "Attempting to unregister handler: {0} that was never registered to a group", + Identifier)); + } + + Group = null; + } + + /// + /// Override this method to define how the custom data handler will write data (ie, transport type, + /// what data to send, when to send it, etc). + /// + protected abstract object GetDataToSend( + ICollection targetPeers, + ReplicationMode replicationMode); + + /// + /// Override this method to define how the custom data handler will receive data. It is guaranteed + /// that the received payload will follow the same format as the data written by this handler + /// (the data that is written in GetDataToSend) + /// + protected abstract void HandleReceivedData( + object data, + IPeer sender, + ReplicationMode replicationMode); + + /// + /// Only called by INetworkGroup, each time the group's manager calls SendQueuedData() + /// + internal object InternalGetDataToSend( + ICollection targetPeers, + ReplicationMode replicationMode) + { + return GetDataToSend(targetPeers, replicationMode); + } + + /// + /// Only called by INetworkGroup, each time the group's manager receives data addressed to this handler + /// + internal void InternalReceiveData( + object data, + IPeer sender, + ReplicationMode replicationMode) + { + HandleReceivedData(data, sender, replicationMode); + } + + /// + /// Returns the self peer if possible, otherwise returns null. For example, if the group's manager + /// has not yet been attached to an IMultipeerNetworking, there is no concept of Self, so + /// return null. + /// + /// + public IPeer GetSelfOrNull() + { + if (Group == null || Group.Session == null || Group.Session.Networking == null) + return null; + + return Group.Session.Networking.Self; + } + + /// + /// Remove this data handler from its current group. No more data will be sent/received by this + /// handler until it is registered to a new group + /// + public virtual void Unregister() + { + if (Group == null) + return; + + Group.UnregisterHandler(this); + Group = null; + } + } +} diff --git a/Assets/ARDK/Networking/HLAPI/NetworkedDataHandlerBase.cs.meta b/Assets/ARDK/Networking/HLAPI/NetworkedDataHandlerBase.cs.meta new file mode 100644 index 0000000..7b046d3 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/NetworkedDataHandlerBase.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9f233f2785d146a598d952f1eb275a9a +timeCreated: 1582068171 \ No newline at end of file diff --git a/Assets/ARDK/Networking/HLAPI/Object.meta b/Assets/ARDK/Networking/HLAPI/Object.meta new file mode 100644 index 0000000..377efe0 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Object.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 307c6d08d1e04f9cbcac50042c0eaab2 +timeCreated: 1536614288 \ No newline at end of file diff --git a/Assets/ARDK/Networking/HLAPI/Object/IMessageStreamReplicator.cs b/Assets/ARDK/Networking/HLAPI/Object/IMessageStreamReplicator.cs new file mode 100644 index 0000000..4f85af0 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Object/IMessageStreamReplicator.cs @@ -0,0 +1,30 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.Collections.Generic; +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.Networking.HLAPI.Object +{ + /// + /// Replicator interface for sending messages over the network. + /// + /// + public interface IMessageStreamReplicator: + INetworkedDataHandler + { + /// + /// Called when data is received from a peer (including from the local peer if they are in the set). + /// + event ArdkEventHandler> MessageReceived; + + /// + /// Sends a message to a set of peers. + /// + void SendMessage(TMessage message, IEnumerable targets); + + /// + /// Sends a message to a set of peers. + /// + void SendMessage(TMessage message, params IPeer[] targets); + } +} diff --git a/Assets/ARDK/Networking/HLAPI/Object/IMessageStreamReplicator.cs.meta b/Assets/ARDK/Networking/HLAPI/Object/IMessageStreamReplicator.cs.meta new file mode 100644 index 0000000..d825841 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Object/IMessageStreamReplicator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 803cdbbd79ef14b1c8bdc7fe01ca74f7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Networking/HLAPI/Object/INetworkedField.cs b/Assets/ARDK/Networking/HLAPI/Object/INetworkedField.cs new file mode 100644 index 0000000..27352e0 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Object/INetworkedField.cs @@ -0,0 +1,42 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.Networking.HLAPI.Object +{ + /// + /// A field that will be replicated over the network. + /// + /// + public interface INetworkedField: + INetworkedDataHandler + { + /// + /// The value of the field. + /// + Optional Value { get; set; } + + /// + /// Sets the value only if the local peer is the sender for this field. + /// + /// The new value for the field. + void SetIfSender(TValue newValue); + + /// + /// Fired on all peers when the value changes. + /// + event ArdkEventHandler> ValueChanged; + + /// + /// Fired on the sender when the value changes. + /// + event ArdkEventHandler> ValueChangedIfSender; + + /// + /// Fired on the receiver when the value changes. + /// + event ArdkEventHandler> ValueChangedIfReceiver; + } +} diff --git a/Assets/ARDK/Networking/HLAPI/Object/INetworkedField.cs.meta b/Assets/ARDK/Networking/HLAPI/Object/INetworkedField.cs.meta new file mode 100644 index 0000000..25a6297 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Object/INetworkedField.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 99606b0cd80147d688df5f386f3bc10a +timeCreated: 1538503879 \ No newline at end of file diff --git a/Assets/ARDK/Networking/HLAPI/Object/MessageReceivedEventArgs.cs b/Assets/ARDK/Networking/HLAPI/Object/MessageReceivedEventArgs.cs new file mode 100644 index 0000000..4d6a29b --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Object/MessageReceivedEventArgs.cs @@ -0,0 +1,19 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.Networking.HLAPI.Object +{ + public struct MessageReceivedEventArgs: + IArdkEventArgs + { + public readonly IPeer Sender; + public readonly TMessage Message; + + public MessageReceivedEventArgs(IPeer sender, TMessage message) + { + Sender = sender; + Message = message; + } + } +} diff --git a/Assets/ARDK/Networking/HLAPI/Object/MessageReceivedEventArgs.cs.meta b/Assets/ARDK/Networking/HLAPI/Object/MessageReceivedEventArgs.cs.meta new file mode 100644 index 0000000..fbea790 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Object/MessageReceivedEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ba77ad6f120e2437ea2b0910460ccb8f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Networking/HLAPI/Object/MessageStreamReplicator.cs b/Assets/ARDK/Networking/HLAPI/Object/MessageStreamReplicator.cs new file mode 100644 index 0000000..52c858e --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Object/MessageStreamReplicator.cs @@ -0,0 +1,171 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.Collections.Generic; +using System.Linq; + +using Niantic.ARDK.Utilities.Extensions; +using Niantic.ARDK.Networking.HLAPI.Data; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Logging; + +namespace Niantic.ARDK.Networking.HLAPI.Object +{ + /// + /// Concrete implementation of replicator for sending messages over the network. + /// + /// + public sealed class MessageStreamReplicator: + NetworkedDataHandlerBase, + IMessageStreamReplicator + { + // Number of frames peer messages can be queued without being a valid receiver. + // This gives a buffer for peers to correctly set up authority/networking agreements + // on joining + private const int FRAMES_TO_DROP_MESSAGES = 60; + private readonly NetworkedDataDescriptor _descriptor; + + private readonly Dictionary> _peerMessageQueues = + new Dictionary>(); + + private readonly Dictionary _peerMessageDropCounter = new Dictionary(); + + /// + public event ArdkEventHandler> MessageReceived; + + public MessageStreamReplicator + ( + string identifier, + NetworkedDataDescriptor descriptor, + INetworkGroup group + ) + { + Identifier = identifier; + _descriptor = descriptor; + + if (group == null) + return; + + group.RegisterHandler(this); + } + + protected override object GetDataToSend + ( + ICollection targetPeers, + ReplicationMode replicationMode + ) + { + if (replicationMode.Transport != TransportType.ReliableOrdered) + return NothingToWrite; + + var targetPeerList = targetPeers.ToList(); + if (targetPeerList.Count > 1) + return NothingToWrite; + + var peer = targetPeerList.First(); + + // If this peer is not a valid receiver, don't immediately drop the message + // Instead, count up to FRAMES_TO_DROP_MESSAGES before clearing the queued messages + if (!_descriptor.GetReceivers().Contains(peer)) + { + int frameCount; + // This will only succeed if we have tried to send a message to the peer, but it has not + // been sent or dropped yet. + var doesPeerHaveMessage = _peerMessageDropCounter.TryGetValue(peer, out frameCount); + + if (!doesPeerHaveMessage) + return NothingToWrite; + + if (frameCount == FRAMES_TO_DROP_MESSAGES) + { + var warningString = + "MessageStreamReplicator {0} on group {1} attempted to send a message " + + "to peer {2}, but that peer was never registered as a valid receiver." + + " Dropping message."; + ARLog._WarnFormat(warningString, false, Identifier, Group.NetworkId.RawId, peer); + _peerMessageDropCounter.Remove(peer); + _peerMessageQueues.Remove(peer); + } + else + _peerMessageDropCounter[peer] = frameCount + 1; + + return NothingToWrite; + } + + var messages = _peerMessageQueues.GetOrDefault(peer); + if (messages == null || messages.Count == 0) + return NothingToWrite; + + var messagesAsArray = messages.ToArray(); + messages.Clear(); + _peerMessageDropCounter.Remove(peer); + + var debugString = "MessageStreamReplicator {0} on group {1} sending message to peer {2}"; + ARLog._DebugFormat(debugString, false, Identifier, Group.NetworkId.RawId, peer); + return messagesAsArray; + } + + protected override void HandleReceivedData + ( + object data, + IPeer sender, + ReplicationMode replicationMode + ) + { + if (!_descriptor.GetSenders().Contains(sender)) + { + var warningString = + "MessageStreamReplicator {0} on group {1} got a message from an invalid sender {2}"; + + ARLog._WarnFormat(warningString, false, Identifier, Group.NetworkId.RawId, sender); + return; + } + + var handler = MessageReceived; + if (handler == null) + return; + + var debugString = "MessageStreamReplicator {0} on group {1} got message from peer {2}"; + ARLog._DebugFormat(debugString, false, Identifier, Group.NetworkId.RawId, sender); + + var array = (TMessage[])data; + foreach (var message in array) + { + var args = new MessageReceivedEventArgs(sender, message); + handler(args); + } + } + + /// + public void SendMessage(TMessage message, IEnumerable targets) + { + var self = GetSelfOrNull(); + + foreach (var peerInfo in targets) + { + if (peerInfo.Equals(self)) + { + var handler = MessageReceived; + if (handler != null) + { + var args = new MessageReceivedEventArgs(peerInfo, message); + handler(args); + } + } + else + { + var queue = _peerMessageQueues.GetOrInsertNew(peerInfo); + // Add a new entry for the peer, but don't overwrite a previously existing counter + // This ensures that we don't prolong the drop buffer by sending messages too often + _peerMessageDropCounter.GetOrInsertNew(peerInfo); + queue.Enqueue(message); + } + } + } + + /// + public void SendMessage(TMessage message, params IPeer[] targets) + { + SendMessage(message, new HashSet(targets)); + } + } +} diff --git a/Assets/ARDK/Networking/HLAPI/Object/MessageStreamReplicator.cs.meta b/Assets/ARDK/Networking/HLAPI/Object/MessageStreamReplicator.cs.meta new file mode 100644 index 0000000..b51618a --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Object/MessageStreamReplicator.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 792a056800954aa080b406e8a81f4bc0 +timeCreated: 1538500924 \ No newline at end of file diff --git a/Assets/ARDK/Networking/HLAPI/Object/NetworkedField.cs b/Assets/ARDK/Networking/HLAPI/Object/NetworkedField.cs new file mode 100644 index 0000000..13cef0a --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Object/NetworkedField.cs @@ -0,0 +1,232 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Linq; + +using Niantic.ARDK.Networking.HLAPI.Data; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.BinarySerialization; +using Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers; +using Niantic.ARDK.Utilities.Logging; + +namespace Niantic.ARDK.Networking.HLAPI.Object +{ + public sealed class NetworkedField: + NetworkedDataHandlerBase, + INetworkedField + { + private static readonly EqualityComparer> _equalityComparer = + EqualityComparer>.Default; + + private readonly NetworkedDataDescriptor _descriptor; + private readonly HashSet _cleanPeers = new HashSet(); + private Optional _value; + private bool _default; + + public NetworkedField + ( + string identifier, + NetworkedDataDescriptor descriptor, + INetworkGroup group, + Optional defaultValue = default(Optional) + ) + { + ARLog._DebugFormat + ( + "Creating a NetworkedField {0} on group {1}", + false, + identifier, + group == null ? "Null" : group.NetworkId.RawId.ToString() + ); + + Identifier = identifier; + _descriptor = descriptor; + + _default = true; + + if (defaultValue.HasValue) + { + ARLog._DebugFormat("Setting default value to {0}", false, defaultValue.Value); + _value = defaultValue; + } + + if (group != null) + group.RegisterHandler(this); + } + + /// + public Optional Value + { + get + { + return _value; + } + set + { + if (!IsSender(Group.Session.Networking.Self)) + throw new InvalidOperationException("Cannot set value if not sender."); + + if (_equalityComparer.Equals(_value, value)) + return; + + _value = value; + _default = false; + _cleanPeers.Clear(); + + var valueChanged = ValueChanged; + var valueChangedIfSender = ValueChangedIfSender; + if (valueChanged == null && valueChangedIfSender == null) + return; + + var args = + new NetworkedFieldValueChangedArgs(NetworkedFieldValueChangedMode.Sender, value); + + if (valueChanged != null) + valueChanged(args); + + if (valueChangedIfSender != null) + valueChangedIfSender(args); + } + } + + /// + public void SetIfSender(TValue newValue) + { + var self = GetSelfOrNull(); + if (IsSender(self)) + { + ARLog._DebugFormat + ( + "Setting NetworkedField {0} on group {1} to {2}", + false, + Identifier, + Group.NetworkId.RawId, + newValue + ); + Value = newValue; + } + } + + private bool IsSender(IPeer peer) + { + return _descriptor.GetSenders().Contains(peer); + } + + /// + public event ArdkEventHandler> ValueChanged; + + /// + public event ArdkEventHandler> ValueChangedIfSender; + + /// + public event ArdkEventHandler> ValueChangedIfReceiver; + + protected override object GetDataToSend + ( + ICollection targetPeers, + ReplicationMode replicationMode + ) + { + var self = GetSelfOrNull(); + + // Don't send if not the sender or if the value is still at its default. + if (!IsSender(self) || _default) + return NothingToWrite; + + var targetPeerList = targetPeers.ToList(); + + // Only send when sending to a specific peer. + if (targetPeerList.Count > 1) + return NothingToWrite; + + // Only send on the correct transport type. + if (replicationMode.Transport != _descriptor.TransportType) + return NothingToWrite; + + var needsCleanMarking = replicationMode.Transport != TransportType.UnreliableUnordered; + + var peer = targetPeerList.First(); + + // Only send if the peer is dirty. + if (needsCleanMarking && _cleanPeers.Contains(peer)) + return NothingToWrite; + + // only send if the peer is a receiver. + if (!_descriptor.GetReceivers().Contains(peer)) + return NothingToWrite; + + // This cleaning marker should come before the next 2 returns. + if (needsCleanMarking) + _cleanPeers.Add(peer); + + if (_value.HasValue) + { + ARLog._DebugFormat + ( + "Propagating NetworkedField {0} on group {1}'s value to peer {2}", + false, + Identifier, + Group.NetworkId.RawId, + peer + ); + return _value.Value; + } + + // Note that null gets serialized as null. NothingToWrite is not serialized. + return null; + } + + protected override void HandleReceivedData + ( + object data, + IPeer sender, + ReplicationMode replicationMode + ) + { + if (!IsSender(sender)) + { + ARLog._WarnFormat + ( + "Received field info from {0} who is not a sender for the field: {1}", + false, + sender, + Identifier + ); + + return; + } + + Optional value = default(Optional); + if (data != null) + value = (TValue)data; + + _value = value; + + ARLog._DebugFormat + ( + "NetworkedField {0} on group {1} received value {2} from peer {3}", + false, + Identifier, + Group.NetworkId.RawId, + value.Value, + sender + ); + + var valueChanged = ValueChanged; + var valueChangedIfReceiver = ValueChangedIfReceiver; + + if (valueChanged == null && valueChangedIfReceiver == null) + return; + + var args = + new NetworkedFieldValueChangedArgs(NetworkedFieldValueChangedMode.Receiver, value); + + if (valueChanged != null) + valueChanged(args); + + if (valueChangedIfReceiver != null) + valueChangedIfReceiver(args); + } + } +} diff --git a/Assets/ARDK/Networking/HLAPI/Object/NetworkedField.cs.meta b/Assets/ARDK/Networking/HLAPI/Object/NetworkedField.cs.meta new file mode 100644 index 0000000..78cccbe --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Object/NetworkedField.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 1c599c22210f403884e13bbeceff46bb +timeCreated: 1579902278 \ No newline at end of file diff --git a/Assets/ARDK/Networking/HLAPI/Object/NetworkedFieldValueChangedEventArgs.cs b/Assets/ARDK/Networking/HLAPI/Object/NetworkedFieldValueChangedEventArgs.cs new file mode 100644 index 0000000..cf48908 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Object/NetworkedFieldValueChangedEventArgs.cs @@ -0,0 +1,23 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.Networking.HLAPI.Object +{ + public struct NetworkedFieldValueChangedArgs: + IArdkEventArgs + { + public readonly NetworkedFieldValueChangedMode Mode; + public readonly Optional Value; + + public NetworkedFieldValueChangedArgs + ( + NetworkedFieldValueChangedMode mode, + Optional value + ) + { + Mode = mode; + Value = value; + } + } +} diff --git a/Assets/ARDK/Networking/HLAPI/Object/NetworkedFieldValueChangedEventArgs.cs.meta b/Assets/ARDK/Networking/HLAPI/Object/NetworkedFieldValueChangedEventArgs.cs.meta new file mode 100644 index 0000000..cfbaadf --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Object/NetworkedFieldValueChangedEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6212e78fdf6644518a24a54ce1c6c955 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Networking/HLAPI/Object/NetworkedFieldValueChangedMode.cs b/Assets/ARDK/Networking/HLAPI/Object/NetworkedFieldValueChangedMode.cs new file mode 100644 index 0000000..3a29f7e --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Object/NetworkedFieldValueChangedMode.cs @@ -0,0 +1,11 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.Networking.HLAPI.Object +{ + public enum NetworkedFieldValueChangedMode + { + Unknown, // This should never happen, but it is here so a "default" would be an invalid value. + Receiver, // We are on the receiving side of a value change. + Sender // We actually caused the value change and are sending the change to other peers. + } +} diff --git a/Assets/ARDK/Networking/HLAPI/Object/NetworkedFieldValueChangedMode.cs.meta b/Assets/ARDK/Networking/HLAPI/Object/NetworkedFieldValueChangedMode.cs.meta new file mode 100644 index 0000000..77b9923 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Object/NetworkedFieldValueChangedMode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b5591c145d3a64955a2e6a8e12581445 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Networking/HLAPI/Object/Unity.meta b/Assets/ARDK/Networking/HLAPI/Object/Unity.meta new file mode 100644 index 0000000..89790f8 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Object/Unity.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 54bc24de89ce48a3aa9249acb7cef360 +timeCreated: 1538510783 \ No newline at end of file diff --git a/Assets/ARDK/Networking/HLAPI/Object/Unity/AuthBehaviour.cs b/Assets/ARDK/Networking/HLAPI/Object/Unity/AuthBehaviour.cs new file mode 100644 index 0000000..f042d70 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Object/Unity/AuthBehaviour.cs @@ -0,0 +1,173 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; + +using Niantic.ARDK.Networking.HLAPI.Authority; +using Niantic.ARDK.Utilities.Collections; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; + +/// @namespace Niantic.ARDK.Networking.HLAPI.Object.Unity +/// @brief Unity specific objects that will be shared over a network +namespace Niantic.ARDK.Networking.HLAPI.Object.Unity +{ + /// + /// A NetworkedBehaviour that can be attached to a NetworkedUnityObject to automatically open + /// channels and handle Authority over the network. + /// + public sealed class AuthBehaviour: + NetworkedBehaviour, + IAuthorityReplicator + { + private const string AUTH_IDENTIFIER = "authBehaviour"; + private IAuthorityReplicator _authorityReplicatorImplementation; + private bool _alreadyUnregistered; + + /// + /// Whether or not the host of the session claims the role of Authority upon connection + /// + [SerializeField] + private bool _ownedByHost = true; + + /// + /// Whether or not all peers of the session claim the role of Observer upon connection. This is + /// superseded by _ownedByHost for the host of the session + /// + [SerializeField] + private bool _observeByDefault = true; + + private Role? _startupRole; + private Action _pass = () => {}; + private Action _fail = () => {}; + + protected override void SetupSession(out Action initializer, out int order) + { + initializer = () => + { + Owner.Networking.Connected += + (args) => + { + var gameObjectName = gameObject.name; + ARLog._DebugFormat + ( + "AuthBehaviour on {0} creating a replicator", + false, + gameObjectName + ); + _authorityReplicatorImplementation = + new GreedyAuthorityReplicator + ( + AUTH_IDENTIFIER, + _alreadyUnregistered ? null : Owner.Group + ); + + if (_ownedByHost && args.IsHost) + _startupRole = Role.Authority; + + if (_startupRole.HasValue) + { + ARLog._DebugFormat + ( + "AuthBehaviour on {0} claiming role {1}", + false, + gameObjectName, + _startupRole.Value + ); + _authorityReplicatorImplementation.TryClaimRole(_startupRole.Value, _pass, _fail); + } + else if (_observeByDefault) + { + ARLog._DebugFormat + ( + "AuthBehaviour on {0} claiming role {1}", + false, + gameObjectName, + Role.Observer + ); + _authorityReplicatorImplementation.TryClaimRole(Role.Observer, _pass, _fail); + } + }; + }; + + order = int.MinValue; + } + + /// + public Role LocalRole + { + get + { + if (_authorityReplicatorImplementation == null) + return Role.None; + + return _authorityReplicatorImplementation.LocalRole; + } + } + + private static readonly IReadOnlyCollection _emptyPeers = + new ARDKReadOnlyCollection(EmptyArray.Instance); + + /// + public IReadOnlyCollection PeersOfRole(Role role) + { + if (_authorityReplicatorImplementation == null) + return _emptyPeers; + + return _authorityReplicatorImplementation.PeersOfRole(role); + } + + /// + public Role RoleOfPeer(IPeer peer) + { + if (_authorityReplicatorImplementation == null) + return Role.None; + + return _authorityReplicatorImplementation.RoleOfPeer(peer); + } + + /// + public void TryClaimRole(Role role, Action onPass, Action onFail) + { + if (_authorityReplicatorImplementation != null) + _authorityReplicatorImplementation.TryClaimRole(role, onPass, onFail); + else + { + ARLog._DebugFormat + ( + "Tried to claim role {0}, but no replicator has been initialized, caching request", + false, + role + ); + _startupRole = role; + _pass = onPass; + _fail = onFail; + } + } + + public string Identifier + { + get + { + return AUTH_IDENTIFIER; + } + } + + public INetworkGroup Group + { + get + { + return Owner.Group; + } + } + + public void Unregister() + { + if (_authorityReplicatorImplementation == null) + _alreadyUnregistered = true; + else + _authorityReplicatorImplementation.Unregister(); + } + } +} diff --git a/Assets/ARDK/Networking/HLAPI/Object/Unity/AuthBehaviour.cs.meta b/Assets/ARDK/Networking/HLAPI/Object/Unity/AuthBehaviour.cs.meta new file mode 100644 index 0000000..4bf3b6a --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Object/Unity/AuthBehaviour.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 17d034239e1d4c618a9095b87e94d006 +timeCreated: 1538514173 \ No newline at end of file diff --git a/Assets/ARDK/Networking/HLAPI/Object/Unity/Helpers.meta b/Assets/ARDK/Networking/HLAPI/Object/Unity/Helpers.meta new file mode 100644 index 0000000..b6a9f7e --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Object/Unity/Helpers.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6842e7f69e01c43f08cd4dcc696102e9 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Networking/HLAPI/Object/Unity/Helpers/NetworkedUnityObjectEditor.cs b/Assets/ARDK/Networking/HLAPI/Object/Unity/Helpers/NetworkedUnityObjectEditor.cs new file mode 100644 index 0000000..44a7380 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Object/Unity/Helpers/NetworkedUnityObjectEditor.cs @@ -0,0 +1,130 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +#if UNITY_EDITOR + +using System.Linq; +using UnityEditor; + +using UnityEngine; + +namespace Niantic.ARDK.Networking.HLAPI.Object.Unity.Helpers { + /// + /// Custom editor for the NetworkedUnityObject class. + /// Handles automated value setting for prefab and instance IDs. + /// + [CustomEditor(typeof(NetworkedUnityObject))] + internal sealed class NetworkedUnityObjectEditor : Editor { + + public override void OnInspectorGUI() { + if (!Application.isPlaying) { + var netUniObj = (NetworkedUnityObject) target; + + // Make sure the prefab ID on this object is set properly. + UpdateInstanceId(netUniObj); + UpdateNetworkedBehavioursList(netUniObj); + } + + // Still use the normal property field to show the UI + base.OnInspectorGUI(); + } + + /// + /// Populate the list of NetworkedBehaviours attached to this NetworkedUnityObject so that + /// they can all be started up at creation. + /// + private void UpdateNetworkedBehavioursList(NetworkedUnityObject obj) { + // If we're in the prefab stage, we can handle things knowing that we're modifying the prefab + // directly. + if (UnityEditor.SceneManagement.PrefabStageUtility.GetCurrentPrefabStage() != null) { + // Regenerate the behaviour list in place + obj._behaviours = obj.GetComponents(); + } else if (PrefabUtility.IsPartOfPrefabInstance(obj) && + !PrefabUtility.IsPrefabAssetMissing(obj)) { + // If we're editting a prefab instance, the property must be editted through the + // SerializedProperty flow, which is a bit janky but ensures that the property gets marked + // as a prefab override. If the user wants to apply these changes to the prefab, it will + // then be clear what has and hasn't been overridden. + var behaviours = obj.GetComponents(); + var behavioursProperty = serializedObject.FindProperty("_behaviours"); + + // If these are the same size, we can assume that no component has been added or removed, + // and thus we can save the time from destroying and rebuilding, which gets expensive in + // an OnGUI context. + if (behaviours.Length != behavioursProperty.arraySize) { + behavioursProperty.ClearArray(); + + for (var i = 0; i < behaviours.Length; i++) { + behavioursProperty.InsertArrayElementAtIndex(i); + var element = behavioursProperty.GetArrayElementAtIndex(i); + element.objectReferenceValue = behaviours[i]; + } + serializedObject.ApplyModifiedProperties(); + } + } + } + + /// + /// Determines if this object is an instance, and then sets its IDs accordingly. + /// + /// + private void UpdateInstanceId(NetworkedUnityObject netUniObj) + { + // We want to first ensure we are selecting an instance, not a prefab. + if + ( + UnityEditor.SceneManagement.PrefabStageUtility.GetCurrentPrefabStage() == null && + PrefabUtility.IsPartOfPrefabInstance(netUniObj) && + !PrefabUtility.IsPrefabAssetMissing(netUniObj) + ) + { + if ((ulong)netUniObj.PrefabId == 0) + { + // We need to sync this instance to its prefab + var prefabPath = + PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(netUniObj); + var prefab = PrefabUtility.LoadPrefabContents(prefabPath); + var prefabNetUniObj = prefab.GetComponent(); + SetPrefabId(serializedObject, (ulong)prefabNetUniObj.PrefabId); + } + else + { + // Check the property modifications to see if the user has messed with the prefab id. + // We don't want this to be altered on prefab instances, so revert if they have. + var propertyModifications = PrefabUtility.GetPropertyModifications(netUniObj); + var prefabIdModification = + propertyModifications.FirstOrDefault(mod => mod.propertyPath == "_prefabId"); + if (prefabIdModification != null) { + PrefabUtility.RevertPropertyOverride( + serializedObject.FindProperty("_prefabId"), + InteractionMode.AutomatedAction + ); + } + } + + // If this instance still has a 0 raw Id, regenerate it. + if ((ulong)netUniObj.Id == 0) { + GenerateRawId(serializedObject); + } + } + } + + /// + /// Sets an object's prefab Id to the specified ulong and saves it. + /// + private static void SetPrefabId(SerializedObject serializedObject, ulong id) { + var prefabIdField = serializedObject.FindProperty("_prefabId"); + prefabIdField.longValue = (long)id; + serializedObject.ApplyModifiedProperties(); + } + + /// + /// Generates a new raw Id for an object and saves it. + /// + private static void GenerateRawId(SerializedObject serializedObject) { + var rawIdField = serializedObject.FindProperty("_rawId"); + rawIdField.longValue = NetworkedUnityObject.GenerateId(); + serializedObject.ApplyModifiedProperties(); + } + } +} +#endif \ No newline at end of file diff --git a/Assets/ARDK/Networking/HLAPI/Object/Unity/Helpers/NetworkedUnityObjectEditor.cs.meta b/Assets/ARDK/Networking/HLAPI/Object/Unity/Helpers/NetworkedUnityObjectEditor.cs.meta new file mode 100644 index 0000000..4066786 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Object/Unity/Helpers/NetworkedUnityObjectEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 00e37b6c45d2b4f879dba1afcd936506 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Networking/HLAPI/Object/Unity/NetTransform.cs b/Assets/ARDK/Networking/HLAPI/Object/Unity/NetTransform.cs new file mode 100644 index 0000000..b701c76 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Object/Unity/NetTransform.cs @@ -0,0 +1,45 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.Networking.HLAPI.Data; + +using UnityEngine; + +// TODO: comment + +namespace Niantic.ARDK.Networking.HLAPI.Object.Unity +{ + [RequireComponent(typeof(AuthBehaviour))] + public sealed class NetTransform : + NetworkedBehaviour + { + [SerializeField] + private TransformPiece _replicatedPieces = TransformPiece.All; + + private UnreliableBroadcastTransformPacker _transformPacker; + + protected override void SetupSession(out Action initializer, out int order) + { + initializer = () => + { + var descriptor = Owner.Auth.AuthorityToObserverDescriptor(TransportType.UnreliableUnordered); + _transformPacker = new UnreliableBroadcastTransformPacker + ( + "NetTransform", + gameObject.transform, + descriptor, + _replicatedPieces, + Owner.Group + ); + }; + + order = 0; + } + + private void OnDestroy() + { + _transformPacker?.Unregister(); + } + } +} diff --git a/Assets/ARDK/Networking/HLAPI/Object/Unity/NetTransform.cs.meta b/Assets/ARDK/Networking/HLAPI/Object/Unity/NetTransform.cs.meta new file mode 100644 index 0000000..ddf3f7d --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Object/Unity/NetTransform.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ed3d79a91d614637b36cb1ab7eb7a887 +timeCreated: 1538514262 \ No newline at end of file diff --git a/Assets/ARDK/Networking/HLAPI/Object/Unity/NetworkSceneSpawnManifest.cs b/Assets/ARDK/Networking/HLAPI/Object/Unity/NetworkSceneSpawnManifest.cs new file mode 100644 index 0000000..19f232e --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Object/Unity/NetworkSceneSpawnManifest.cs @@ -0,0 +1,19 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using UnityEngine; + +// TODO: comment + +namespace Niantic.ARDK.Networking.HLAPI.Object.Unity { + public class NetworkSceneSpawnManifest : MonoBehaviour { + [SerializeField] private PrefabManifest _manifest = null; + + private void Awake() { + NetworkSpawner.LoadManifest(_manifest); + } + + private void OnDestroy() { + NetworkSpawner.UnloadManifest(_manifest); + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/Networking/HLAPI/Object/Unity/NetworkSceneSpawnManifest.cs.meta b/Assets/ARDK/Networking/HLAPI/Object/Unity/NetworkSceneSpawnManifest.cs.meta new file mode 100644 index 0000000..ccdbbca --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Object/Unity/NetworkSceneSpawnManifest.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 61225b9e18604b82b4ba8d216a58e42e +timeCreated: 1538586335 \ No newline at end of file diff --git a/Assets/ARDK/Networking/HLAPI/Object/Unity/NetworkSpawner.cs b/Assets/ARDK/Networking/HLAPI/Object/Unity/NetworkSpawner.cs new file mode 100644 index 0000000..c516e43 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Object/Unity/NetworkSpawner.cs @@ -0,0 +1,653 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; + +using Niantic.ARDK.Networking.HLAPI.Authority; +using Niantic.ARDK.Networking.HLAPI.Data; +using Niantic.ARDK.Networking.HLAPI.Routing; +using Niantic.ARDK.Networking.MultipeerNetworkingEventArgs; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; + +using Random = System.Random; + +namespace Niantic.ARDK.Networking.HLAPI.Object.Unity +{ + public struct NetworkObjectLifecycleArgs: + IArdkEventArgs + { + public NetworkObjectLifecycleArgs + ( + NetworkedUnityObject networkedUnityObject, + IMultipeerNetworking networking, + IPeer peer + ): + this() + { + Object = networkedUnityObject; + Networking = networking; + Peer = peer; + } + + public NetworkedUnityObject Object { get; private set; } + public IMultipeerNetworking Networking { get; private set; } + public IPeer Peer { get; private set; } + } + + /// + /// A static class that handles the replication and network spawning of NetworkedUnityObjects for + /// all peers across the network. Also handles the network destruction of spawned objects. + /// + public static class NetworkSpawner + { + private static readonly ConcurrentDictionary _loadedPrefabs = + new ConcurrentDictionary(); + + private static readonly ConcurrentDictionary _spawnedObjects = + new ConcurrentDictionary(); + + private static readonly Random _random = new Random(); + private static readonly byte[] _idGenBuffer = new byte[8]; + private static readonly int _debugPeerIdLength = 6; + + private static + ConcurrentDictionary> _spawnMessageStreams = + new ConcurrentDictionary>(); + + private static + ConcurrentDictionary> _destructorMessageStreams = + new ConcurrentDictionary>(); + + // Some hard coded random values so that all peers are in agreement of network spawning + // groups/channels. + private const ulong SpawnGroupId = 94842342L; + private const ulong SpawnChannelId = 38901231L; + private const ulong DestructorChannelId = 38209183L; + + public static event ArdkEventHandler NetworkObjectSpawned; + public static event ArdkEventHandler NetworkObjectDestroyed; + + private static bool _initialized; + private static void _InitializeIfNeeded() + { + if (_initialized) + return; + + ARLog._Debug("Initializing NetworkSpawner"); + MultipeerNetworkingFactory.NetworkingInitialized += _MultipeerNetworkingInitialized; + _initialized = true; + } + + internal static void _Deinitialize() + { + ARLog._Debug("Deinitializing NetworkSpawner, existing sessions will still be useable"); + MultipeerNetworkingFactory.NetworkingInitialized -= _MultipeerNetworkingInitialized; + _initialized = false; + } + + private static void _MultipeerNetworkingInitialized + ( + AnyMultipeerNetworkingInitializedArgs networkingArgs + ) + { + var multipeerNetworking = networkingArgs.Networking; + + var netSpawnerGroup = + multipeerNetworking + .GetOrCreateManagedSession() + .CreateAndRegisterGroup(new NetworkId(SpawnGroupId)); + + var streamReplicator = + new MessageStreamReplicator + ( + "_NSSpawn", + multipeerNetworking.AnyToAnyDescriptor(TransportType.ReliableOrdered), + netSpawnerGroup + ); + + _spawnMessageStreams[multipeerNetworking.StageIdentifier] = streamReplicator; + + streamReplicator.MessageReceived += + (args) => SpawnMessageStreamOnMessageReceive(args.Message, args.Sender, streamReplicator); + + var destructorMessageStream = + new MessageStreamReplicator + ( + "_NSDestroy", + multipeerNetworking.AnyToAnyDescriptor(TransportType.ReliableOrdered), + netSpawnerGroup + ); + + _destructorMessageStreams[multipeerNetworking.StageIdentifier] = destructorMessageStream; + + destructorMessageStream.MessageReceived += DestroyMessageStreamOnMessageReceived; + + multipeerNetworking.PeerAdded += + (peerAddedArgs) => + { + foreach (var repUnityObject in _spawnedObjects.Values) + { + bool isMine = + repUnityObject.WasSpawnedByMe && + repUnityObject.Networking.StageIdentifier.Equals + (multipeerNetworking.StageIdentifier); + + if (isMine) + { + var targets = new HashSet(new[] {peerAddedArgs.Peer }); + + var message = + new SpawnMessage() + { + Location = repUnityObject.transform.position, + Rotation = repUnityObject.transform.rotation, + NewId = repUnityObject.Id, + PrefabId = repUnityObject.PrefabId, + }; + + ARLog._DebugFormat + ( + "New peer {0} added, informing them of NetworkedUnityObject {1}", + false, + peerAddedArgs.Peer.ToString(_debugPeerIdLength), + repUnityObject.Id.RawId + ); + streamReplicator.SendMessage(message, targets); + } + } + }; + + multipeerNetworking.Deinitialized += + (ignoredArgs) => + { + _spawnMessageStreams.TryRemove(multipeerNetworking.StageIdentifier, out _); + _destructorMessageStreams.TryRemove(multipeerNetworking.StageIdentifier, out _); + }; + + //If a peer leaves, locally destroy all objects belonging to that peer if they can be destroyed + multipeerNetworking.PeerRemoved += + (removedArgs) => + { + var peer = removedArgs.Peer; + + foreach (var pair in _spawnedObjects) + { + var key = pair.Key; + var spawnedObject = pair.Value; + if (!spawnedObject.CanDestroyIfDestructorLeaves(peer)) + continue; + + ARLog._DebugFormat + ( + "Peer {0} left, destroying their spawned object {1}", + false, + peer.ToString(_debugPeerIdLength), + spawnedObject.Id.RawId + ); + var handler = NetworkObjectDestroyed; + if (handler != null) + { + var args = + new NetworkObjectLifecycleArgs(spawnedObject, multipeerNetworking, peer); + + handler(args); + } + + // It is safe to remove an item from a ConcurrentDictionary during a foreach + _spawnedObjects.TryRemove(key, out _); + + spawnedObject._isDestroyed = true; + UnityEngine.Object.Destroy(spawnedObject.gameObject); + } + }; + } + + // This method is invoked by tests using reflection. + private static void DestroyMessageStreamOnMessageReceive + ( + NetworkId networkId, IPeer sender + ) + { + var args = new MessageReceivedEventArgs(sender, networkId); + DestroyMessageStreamOnMessageReceived(args); + } + + private static void DestroyMessageStreamOnMessageReceived + ( + MessageReceivedEventArgs messageReceivedArgs + ) + { + var objectID = messageReceivedArgs.Message; + NetworkedUnityObject networkedObject; + _spawnedObjects.TryGetValue(objectID, out networkedObject); + + var peer = messageReceivedArgs.Sender; + // This may occur when two valid peers destroy the same object simultaneously, or if a message + // gets duplicated. (Or if some peer is cheating). In those cases, do nothing + if (networkedObject == null || !networkedObject.IsDestructionAuthorizedPeer(peer)) + { + ARLog._WarnFormat + ("Received an invalid NetworkDestroy call from peer {0}, for object {1}", + false, + peer.ToString(_debugPeerIdLength), + objectID + ); + return; + } + + _spawnedObjects.TryRemove(objectID, out _); + networkedObject._isDestroyed = true; + + ARLog._DebugFormat + ( + "Network destroying spawned object {0}, destroyed by peer {1}", + false, + objectID.RawId, + peer.ToString(_debugPeerIdLength) + ); + + var handler = NetworkObjectDestroyed; + if (handler != null) + { + var networking = networkedObject.Networking; + var args = new NetworkObjectLifecycleArgs(networkedObject, networking, peer); + handler(args); + } + +#if UNITY_EDITOR // Added specifically so this can be run in Unity unit tests + UnityEngine.Object.DestroyImmediate(networkedObject.gameObject); +#else + UnityEngine.Object.Destroy(networkedObject.gameObject); +#endif + } + + private static void SpawnMessageStreamOnMessageReceive + ( + SpawnMessage message, + IPeer peer, + IMessageStreamReplicator stream + ) + { + // If the object already exists (duplicated message), do nothing + if (_spawnedObjects.ContainsKey(message.NewId)) + { + ARLog._DebugFormat("Object with id {0} already exists.",false, message.NewId); + return; + } + + NetworkedUnityObject prefab; + + if (!_loadedPrefabs.TryGetValue(message.PrefabId, out prefab)) + { + ARLog._WarnFormat("No prefab with id: {0}.", false, message.PrefabId); + return; + } + + var newInstance = UnityEngine.Object.Instantiate(prefab, message.Location, message.Rotation); + newInstance.Id = message.NewId; + newInstance.Networking = stream.Group.Session.Networking; + newInstance.SpawningPeer = peer; + _spawnedObjects[message.NewId] = newInstance; + ARLog._DebugFormat + ( + "NetworkSpawned object with PrefabId {0}, RawId {1}, by peer {2}", + false, + message.PrefabId, + message.NewId.RawId, + peer.ToString(_debugPeerIdLength) + ); + + newInstance.Initialize(); + + var handler = NetworkObjectSpawned; + if (handler != null) + { + var args = new NetworkObjectLifecycleArgs(newInstance, newInstance.Networking, peer); + handler(args); + } + } + + /// + /// Loads all prefabs in the PrefabManifest to prepare for network spawning. This is + /// automatically called by the NetworkSceneSpawnManifest MonoBehaviour. + /// + /// Manifest containing prefabs to load into memory + public static void LoadManifest(PrefabManifest manifest) + { + _InitializeIfNeeded(); + + ARLog._Debug("NetworkSpawner loading prefab manifest"); + foreach (var prefab in manifest.Prefabs) + _loadedPrefabs.TryAdd(prefab.PrefabId, prefab); + } + + /// + /// Unloads prefabs loaded from the PrefabManifest from memory. This is called by the + /// NetworkSceneSpawnManifest MonoBehaviour + /// + /// Manifest containing prefabs to unload from memory + public static void UnloadManifest(PrefabManifest manifest) + { + ARLog._Debug("NetworkSpawner unloading prefab manifest"); + foreach (var prefab in manifest.Prefabs) + _loadedPrefabs.TryRemove(prefab.PrefabId, out _); + } + + /// + /// Locally instantiates a prefab with given starting parameters, then sends a message across + /// the network for all listening peers to also instantiate the same prefab. + /// + /// The prefab to spawn + /// The networking stack on which to spawn the object + /// The initial position of the object + /// The initial rotation of the object + /// The starting role of the local peer + /// The network ID of the new object, will be automatically assigned if empty + /// The peers for which to spawn the object + /// The spawned NetworkedUnityObject + public static NetworkedUnityObject NetworkSpawn + ( + this NetworkedUnityObject spawnObject, + IMultipeerNetworking networking, + Vector3? position = null, + Quaternion? rotation = null, + Role? startingLocalRole = null, + NetworkId? newNetId = null, + List targetPeers = null + ) + { + _InitializeIfNeeded(); + + var newInstance = + NetworkSpawnHelper + ( + spawnObject, + networking, + position, + rotation, + startingLocalRole, + newNetId, + targetPeers + ); + + return newInstance; + } + + /// + /// Locally instantiates a prefab with given starting parameters, then sends a message across the + /// network for all listening peers to also instantiate the same prefab. + /// + /// The prefab to spawn + /// The initial position of the object + /// The initial rotation of the object + /// The starting role of the local peer + /// The network ID of the new object, will be automatically assigned if empty + /// The peers for which to spawn the object + /// The spawned NetworkedUnityObject + public static NetworkedUnityObject NetworkSpawn + ( + this NetworkedUnityObject spawnObject, + Vector3? position = null, + Quaternion? rotation = null, + Role? startingLocalRole = null, + NetworkId? newNetId = null, + List targetPeers = null + ) + { + _InitializeIfNeeded(); + + var newInstance = + NetworkSpawnHelper + ( + spawnObject, + MultipeerNetworkingFactory.Networkings.First(), + position, + rotation, + startingLocalRole, + newNetId, + targetPeers + ); + + return newInstance; + } + + // Helper function for both versions of NetworkSpawn() + private static NetworkedUnityObject NetworkSpawnHelper + ( + this NetworkedUnityObject spawnObject, + IMultipeerNetworking networking, + Vector3? position = null, + Quaternion? rotation = null, + Role? startingLocalRole = null, + NetworkId? newNetId = null, + List targetPeers = null + ) + { + _InitializeIfNeeded(); + + if (networking == null || !networking.IsConnected) + { + ARLog._Error("Trying to network spawn before the networking is connected"); + return null; + } + + if (newNetId.HasValue && _spawnedObjects.ContainsKey(newNetId.Value)) + { + ARLog._WarnFormat + ( + "Object with id {0} already exists. Cannot spawn another one.", + false, + newNetId.Value + ); + + return null; + } + + var networkedUnityObject = UnityEngine.Object.Instantiate(spawnObject); + networkedUnityObject.Networking = networking; + networkedUnityObject.SpawningPeer = networking.Self; + + if (position.HasValue) + networkedUnityObject.transform.position = position.Value; + + if (rotation.HasValue) + networkedUnityObject.transform.rotation = rotation.Value; + + if (newNetId.HasValue) + networkedUnityObject.Id = newNetId.Value; + else + { + _random.NextBytes(_idGenBuffer); + var nextId = BitConverter.ToUInt64(_idGenBuffer, 0); + networkedUnityObject.Id = (NetworkId)nextId; + } + + ARLog._DebugFormat + ( + "Local peer NetworkSpawned object with PrefabId {0}, RawId {1}", + false, + networkedUnityObject, + networkedUnityObject.Id.RawId + ); + + if (startingLocalRole.HasValue) + networkedUnityObject.Auth.TryClaimRole(startingLocalRole.Value, () => {}, () => {}); + + if (targetPeers == null) + targetPeers = networking.OtherPeers.ToList(); + + var message = + new SpawnMessage() + { + PrefabId = networkedUnityObject.PrefabId, + NewId = networkedUnityObject.Id, + Location = networkedUnityObject.transform.position, + Rotation = networkedUnityObject.transform.rotation, + }; + + IMessageStreamReplicator streamReplicator; + if (_spawnMessageStreams.TryGetValue(networking.StageIdentifier, out streamReplicator)) + streamReplicator.SendMessage(message, targetPeers); + + _spawnedObjects[networkedUnityObject.Id] = networkedUnityObject; + + networkedUnityObject.Initialize(); + + var handler = NetworkObjectSpawned; + if (handler != null) + { + var args = + new NetworkObjectLifecycleArgs + ( + networkedUnityObject, + networkedUnityObject.Networking, + networkedUnityObject.Networking.Self + ); + + handler(args); + } + + return networkedUnityObject; + } + + /// + /// Check if we are allowed to propagate the destruction message, then send it if allowed. + /// If no one had previously destroyed the object, destroy it after sending the message. Only + /// objects that were network spawned can be network destroyed + /// + /// The object to be destroyed + public static void NetworkDestroy(this NetworkedUnityObject networkedObject) + { + ARLog._DebugFormat + ( + "Attempting to NetworkDestroy object {0}", + false, + networkedObject.Id.RawId + ); + + _InitializeIfNeeded(); + + if (!networkedObject.IsDestructionAuthorizedPeer(networkedObject.Networking.Self)) + { + if (networkedObject.SpawningPeer != null) + { + ARLog._WarnFormat + ( + "Local peer is not a valid destructor for object: {0}", + false, + networkedObject.Id + ); + } + + return; + } + + _spawnedObjects.TryRemove(networkedObject.Id, out _); + + var networking = networkedObject.Networking; + if (networking != null) + { + if (_destructorMessageStreams.TryGetValue(networking.StageIdentifier, out var stream)) + stream.SendMessage(networkedObject.Id, networking.OtherPeers); + } + + // This is for the case that a valid peer destroys an object with the Object.Destroy method, and + // will attempt to send a message to network destroy the object. + // Todo (awang): make SendMessageImmediate that actually somewhat works on scene close + if (networkedObject._isDestroyed) + return; + + networkedObject._isDestroyed = true; + + var handler = NetworkObjectDestroyed; + if (handler != null) + { + IPeer self = null; + if (networking != null) + self = networking.Self; + + var args = new NetworkObjectLifecycleArgs(networkedObject, networking, self); + handler(args); + } + +#if UNITY_EDITOR // Added specifically so NetworkDestroy() can be run in Unity unit tests + UnityEngine.Object.DestroyImmediate(networkedObject.gameObject); +#else + UnityEngine.Object.Destroy(networkedObject.gameObject); +#endif + } + + [Serializable] + internal struct SpawnMessage + { + public NetworkId PrefabId { get; set; } + public NetworkId NewId { get; set; } + public Vector3 Location { get; set; } + public Quaternion Rotation { get; set; } + } + + // TODO: Create an ItemSerializer for SpawnMessage for performance. It is [Serializable] already + /* + private class SpawnMessageSerializationProvider: ISerializationProvider + { + public static readonly ISerializationProvider Shared = + new SpawnMessageSerializationProvider + ( + NetworkId.SerializationProvider.Shared, + NetVector3.SerializationProvider.DefaultShared, + NetQuaternion.SerializationProvider.DefaultShared + ); + + private readonly Serializer _serializer; + private readonly Deserializer _deserializer; + + public SpawnMessageSerializationProvider + ( + ISerializationProvider networkIdSerializationProvider, + ISerializationProvider vectorSerializationProvider, + ISerializationProvider quaternionSerializationProvider + ) + { + _serializer = + (data, writer) => + { + networkIdSerializationProvider.Serializer(data.PrefabId, writer); + networkIdSerializationProvider.Serializer(data.NewId, writer); + vectorSerializationProvider.Serializer(data.Location, writer); + quaternionSerializationProvider.Serializer(data.Rotation, writer); + }; + + _deserializer = + reader => new SpawnMessage() + { + PrefabId = networkIdSerializationProvider.Deserializer(reader), + NewId = networkIdSerializationProvider.Deserializer(reader), + Location = vectorSerializationProvider.Deserializer(reader), + Rotation = quaternionSerializationProvider.Deserializer(reader), + }; + } + + public Serializer Serializer + { + get + { + return _serializer; + } + } + + public Deserializer Deserializer + { + get + { + return _deserializer; + } + } + }*/ + } +} diff --git a/Assets/ARDK/Networking/HLAPI/Object/Unity/NetworkSpawner.cs.meta b/Assets/ARDK/Networking/HLAPI/Object/Unity/NetworkSpawner.cs.meta new file mode 100644 index 0000000..b896760 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Object/Unity/NetworkSpawner.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 10a39698759a488f8ebd544c5a0ed852 +timeCreated: 1538512607 \ No newline at end of file diff --git a/Assets/ARDK/Networking/HLAPI/Object/Unity/NetworkedBehaviour.cs b/Assets/ARDK/Networking/HLAPI/Object/Unity/NetworkedBehaviour.cs new file mode 100644 index 0000000..0d7c8e6 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Object/Unity/NetworkedBehaviour.cs @@ -0,0 +1,52 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; + +using Niantic.ARDK.Utilities.Logging; +using Niantic.ARDK.Internals.EditorUtilities; + +using UnityEngine; + +namespace Niantic.ARDK.Networking.HLAPI.Object.Unity +{ + /// Defines the behaviour of a NetworkedUnityObject. + /// Since NetworkedUnityObjects have their own setup/destroy flows, do NOT + /// override Awake. + [RequireComponent(typeof(NetworkedUnityObject))] + public abstract class NetworkedBehaviour: MonoBehaviour + { + /// The NetworkedUnityObject attached to the same GameObject as this component. + [_Autofill] + [SerializeField] + private NetworkedUnityObject _owner = null; + + /// The NetworkedUnityObject attached to the same GameObject as this script + public NetworkedUnityObject Owner + { + get { return _owner == null ? GetComponent() : _owner; } + } + + public int Initialize(out Action initializer) + { + ARLog._DebugFormat + ( + "Calling SetupSession for NetworkedBehaviour attached to group {0}", + false, + Owner.Id + ); + + SetupSession(out initializer, out int order); + return order; + } + + /// Implement this method to define the behaviour of the NetworkedUnityObject upon network + /// initialization or startup + /// @param onNetworkingDidInitialize + /// Action invoked when this GameObject is network spawned. + /// @param order + /// Order that the onNetworkingDidInitialize Action is invoked, relative to that of other + /// NetworkedBehaviors on this GameObject. + protected abstract void SetupSession(out Action onNetworkingDidInitialize, out int order); + } +} diff --git a/Assets/ARDK/Networking/HLAPI/Object/Unity/NetworkedBehaviour.cs.meta b/Assets/ARDK/Networking/HLAPI/Object/Unity/NetworkedBehaviour.cs.meta new file mode 100644 index 0000000..18720c1 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Object/Unity/NetworkedBehaviour.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ab2afe525182477fbec6a96393523fbe +timeCreated: 1538512652 \ No newline at end of file diff --git a/Assets/ARDK/Networking/HLAPI/Object/Unity/NetworkedUnityObject.cs b/Assets/ARDK/Networking/HLAPI/Object/Unity/NetworkedUnityObject.cs new file mode 100644 index 0000000..799ae09 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Object/Unity/NetworkedUnityObject.cs @@ -0,0 +1,379 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Linq; + +using Niantic.ARDK.External; +using Niantic.ARDK.Internals.EditorUtilities; +using Niantic.ARDK.Networking.HLAPI.Authority; +using Niantic.ARDK.Networking.HLAPI.Routing; +using Niantic.ARDK.Networking.MultipeerNetworkingEventArgs; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; +#if UNITY_EDITOR +using UnityEditor; +#endif + +namespace Niantic.ARDK.Networking.HLAPI.Object.Unity +{ + /// + /// A MonoBehaviour that provides replication details for a prefab/scene object. Handles details + /// such as valid destructors, authority, and network groups for each networked object. + /// + /// An object with this component needs to stay alive for at least one frame after Awake, + /// or else CallbackQueue will have a null reference to the object. + /// + [DefaultExecutionOrder(Int32.MinValue)] + [RequireComponent(typeof(AuthBehaviour))] + public sealed class NetworkedUnityObject: + MonoBehaviour, + ISerializationCallbackReceiver + { + /// + /// An Id that represents the instance of the object, shared between all peers in the session + /// + [SerializeField] + private long _rawId; + + /// + /// An Id that represents the prefab, shared between all builds of the scene + /// + [SerializeField] + private long _prefabId; + + /// + /// The peers that have the right to network destroy the object + /// + [EnumFlag] + [SerializeField] + private DestructionAuthorizedPeerOptions _destructionAuthorizedPeers = DestructionAuthorizedPeerOptions.Anyone; + + /// + /// If the only peer with destructor rights leaves the session without destroying the object, + /// clean it up locally + /// + [SerializeField] + private bool _destroyIfDestroyerLeaves; + + /// + /// The AuthBehaviour that handles authority for each instance of this object + /// + [_Autofill] + [SerializeField] + private AuthBehaviour _auth; + + /// + /// The default NetworkedBehaviour for this object + /// + [SerializeField] + private NetworkedBehaviour _defaultBehaviour = null; + + /// + /// All NetworkedBehaviours attached to this object, will be populated automatically + /// + [SerializeField] + internal NetworkedBehaviour[] _behaviours; + + /// + /// Possible peer(s) that can be given the right to network destroy the object + /// + [Flags] + private enum DestructionAuthorizedPeerOptions + { + /// This object should not be network destroyed + None = 0, + + /// Peers other than the spawner/authority can network destroy this object + UnrelatedPeers = 1, + + /// The spawner of this object can network destroy it + Spawner = 2, + + /// The authority of this object can network destroy it + Authority = 4, + + /// All peers can network destroy this object + Anyone = ~None, + } + + private INetworkGroup _group; + + private static System.Random _random = new System.Random(); + + + private IHlapiSession Session + { + get + { + if (Networking != null) + { + return Networking.GetOrCreateManagedSession(); + } + + return gameObject.scene.GetOrCreateManagedSession(); + } + } + + /// + /// Whether or not the object has already been destroyed + /// + internal bool _isDestroyed; + + /// + /// Whether or not the object was spawned by the local peer + /// + public bool WasSpawnedByMe + { + get => SpawningPeer != null && SpawningPeer.Equals(Networking.Self); + } + + /// + /// The peer that network spawned this object, will be null if not network spawned + /// + public IPeer SpawningPeer { get; internal set; } + + /// + /// The networking instance that this object is tied to + /// + public IMultipeerNetworking Networking { get; internal set; } + + /// + /// An Id that represents the instance of the object, shared between all peers in the session + /// + public NetworkId Id + { + get => (NetworkId)(ulong)_rawId; + internal set => _rawId = (long)(ulong)value; + } + + /// + /// An Id that represents the prefab, shared between all builds of the scene + /// + public NetworkId PrefabId + { + get => (NetworkId)(ulong)_prefabId; + } + + /// + /// The AuthBehaviour that handles this object + /// + public AuthBehaviour Auth + { + get => _auth; + } + + /// + /// The NetworkedBehaviour that determines the behaviour of the NetworkedUnityObject + /// + public NetworkedBehaviour DefaultBehaviour + { + get => _defaultBehaviour; + } + + /// + /// The networking group that corresponds to this object, handled by the UnitySceneNetworkMaster + /// + public INetworkGroup Group + { + get => _group ?? (_group = Session.CreateAndRegisterGroup(Id)); + } + + /// + /// Initializes the NetworkedUnityObject and all NetworkedBehaviours on the object + /// + public void Initialize() + { + ARLog._DebugFormat + ( + "Initializing NetworkedUnityObject {0}", + false, + Id.RawId + ); + + _group ??= Session.CreateAndRegisterGroup(Id); + + var initializerList = new List>(); + + if (_behaviours.Length == 0) + { + var warningFormat = + "The NetworkedUnityObject on {0} was initialized with no behaviours, maybe those need " + + "to be set up?"; + + ARLog._WarnFormat(warningFormat, false, gameObject.name); + } + + foreach (var behaviour in _behaviours) + { + var order = behaviour.Initialize(out Action initializer); + initializerList.Add(new KeyValuePair(order, initializer)); + } + + initializerList.Sort((kvp1, kvp2) => kvp1.Key.CompareTo(kvp2.Key)); + + foreach (var initKvp in initializerList) + initKvp.Value.Invoke(); + } + + /// + /// Determines if a peer has the right to destroy an object + /// + /// The peer that would like to destroy the object + /// Whether or not the peer can destroy this object + public bool IsDestructionAuthorizedPeer(IPeer peer) + { + // If SpawningPeer is not set, this object was not network spawned, so don't try to network + // destroy it + if (SpawningPeer == null) + return false; + + if (_destructionAuthorizedPeers == DestructionAuthorizedPeerOptions.None) + return false; + + if (_destructionAuthorizedPeers == DestructionAuthorizedPeerOptions.Anyone) + return true; + + var selectedUnrelatedPeers = + _destructionAuthorizedPeers & DestructionAuthorizedPeerOptions.UnrelatedPeers; + + if (selectedUnrelatedPeers == DestructionAuthorizedPeerOptions.UnrelatedPeers) + if (!SpawningPeer.Equals(peer) && _auth.RoleOfPeer(peer) != Role.Authority) + return true; + + if ((_destructionAuthorizedPeers & DestructionAuthorizedPeerOptions.Spawner) != 0) + if (SpawningPeer.Equals(peer)) + return true; + + if ((_destructionAuthorizedPeers & DestructionAuthorizedPeerOptions.Authority) != 0) + if (_auth.RoleOfPeer(peer) == Role.Authority) + return true; + + return false; + } + + /// + /// Checks if local destruction of this object is allowed if the sole destructor of the object + /// leaves the session without destroying the object, as well as if the peer in question is + /// in fact the sole destructor of the object + /// + /// The peer that left the session + internal bool CanDestroyIfDestructorLeaves(IPeer peer) + { + if (!_destroyIfDestroyerLeaves) + return false; + + bool shouldReturnFalse = + (_destructionAuthorizedPeers & DestructionAuthorizedPeerOptions.Spawner) == 0 && + (_destructionAuthorizedPeers & DestructionAuthorizedPeerOptions.Authority) == 0; + + if (shouldReturnFalse) + return false; + + return IsDestructionAuthorizedPeer(peer); + } + + private void Start() + { + // If SpawningPeer is set, this object was NetworkSpawned and init already occurred + if (SpawningPeer != null) + return; + + if (Networking == null) + Networking = MultipeerNetworkingFactory.Networkings.FirstOrDefault(); + + if (Networking != null) + { + ARLog._DebugFormat + ( + "NetworkedUnityObject {0} is attached to {1}, initializing", + false, + _rawId, + Networking.StageIdentifier + ); + Initialize(); + } + else + MultipeerNetworkingFactory.NetworkingInitialized += _NetworkingInitialized; + } + + private void _NetworkingInitialized(AnyMultipeerNetworkingInitializedArgs args) + { + MultipeerNetworkingFactory.NetworkingInitialized -= _NetworkingInitialized; + Networking = args.Networking; + ARLog._DebugFormat + ( + "NetworkedUnityObject {0} is attached to {1}, initializing", + false, + _rawId, + Networking.StageIdentifier + ); + Initialize(); + } + + private void OnDestroy() + { + ARLog._DebugFormat + ( + "NetworkedUnityObject {0} is destroyed, unregistering", + false, + _rawId + ); + Group.Unregister(); + + /// If this object was already destroyed, don't try to destroy it again. + if (_isDestroyed) + return; + + if (Networking == null) + { + // As the networking was never set, it means we need to unregister from the static event. + MultipeerNetworkingFactory.NetworkingInitialized -= _NetworkingInitialized; + _isDestroyed = true; + return; + } + + _isDestroyed = true; + this.NetworkDestroy(); + } + + public void OnBeforeSerialize() + { +#if UNITY_EDITOR + // Check if we're serializing a regular prefab + var prefabAssetType = PrefabUtility.GetPrefabAssetType(this); + if + ( + prefabAssetType == PrefabAssetType.Regular && + !PrefabUtility.IsPartOfPrefabInstance(this) + ) + { + // Prefab rawID should always be 0. Important to ensure in case user hits "Apply All" + // rawID is a trait of prefab instances anyway + _rawId = 0; + + // If we haven't generated a prefabID, do so + if (_prefabId == 0) + _prefabId = GenerateId(); + } +#endif + } + + public void OnAfterDeserialize() + { + // Explicitly left empty + } + + /// + /// Generates a randomized Long to be used for an Id. + /// + internal static long GenerateId() + { + var longBytes = new byte[8]; + _random.NextBytes(longBytes); + + return BitConverter.ToInt64(longBytes, 0); + } + } +} diff --git a/Assets/ARDK/Networking/HLAPI/Object/Unity/NetworkedUnityObject.cs.meta b/Assets/ARDK/Networking/HLAPI/Object/Unity/NetworkedUnityObject.cs.meta new file mode 100644 index 0000000..d07d1fd --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Object/Unity/NetworkedUnityObject.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9fd171c6c1184ff491f420f69849ba07 +timeCreated: 1538510970 \ No newline at end of file diff --git a/Assets/ARDK/Networking/HLAPI/Object/Unity/PrefabManifest.cs b/Assets/ARDK/Networking/HLAPI/Object/Unity/PrefabManifest.cs new file mode 100644 index 0000000..f7c5636 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Object/Unity/PrefabManifest.cs @@ -0,0 +1,15 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using UnityEngine; + +// TODO: comment + +namespace Niantic.ARDK.Networking.HLAPI.Object.Unity { + [Serializable] + [CreateAssetMenu(menuName ="Networking/Spawning/PrefabManifest")] + public class PrefabManifest : ScriptableObject { + public List Prefabs = new List(); + } +} \ No newline at end of file diff --git a/Assets/ARDK/Networking/HLAPI/Object/Unity/PrefabManifest.cs.meta b/Assets/ARDK/Networking/HLAPI/Object/Unity/PrefabManifest.cs.meta new file mode 100644 index 0000000..f1a6b5d --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Object/Unity/PrefabManifest.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3cabe4f37b454aa1aa61155165bcf4af +timeCreated: 1538684842 \ No newline at end of file diff --git a/Assets/ARDK/Networking/HLAPI/Object/UnreliableBroadcastTransformPacker.cs b/Assets/ARDK/Networking/HLAPI/Object/UnreliableBroadcastTransformPacker.cs new file mode 100644 index 0000000..31e65ac --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Object/UnreliableBroadcastTransformPacker.cs @@ -0,0 +1,191 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Linq; + +using Niantic.ARDK.Utilities.Extensions; +using Niantic.ARDK.Networking.HLAPI.Data; +using Niantic.ARDK.Utilities.BinarySerialization; +using Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers; + +using UnityEngine; + +namespace Niantic.ARDK.Networking.HLAPI.Object.Unity +{ + [Flags] + public enum TransformPiece + { + Position = 0x1, + Rotation = 0x2, + Scale = 0x4, + PositionAndRotation = Position | Rotation, + All = Position | Rotation | Scale, + } + + /// + /// Replicator that will replicate transform un-reliably over the network. + /// + public sealed class UnreliableBroadcastTransformPacker: + NetworkedDataHandlerBase + { + private readonly Transform _transform; + private readonly TransformPiece _pieces; + private readonly NetworkedDataDescriptor _descriptor; + private Vector3? _prevPosition; + private Quaternion? _prevRotation; + private Vector3? _prevScale; + private readonly List _peersSentThisFrame = new List(); + private readonly List _dirtyPeers = new List(); + + /// + /// The transform to be replicated. + /// + /// The pieces of the transform to replicate. + /// + public UnreliableBroadcastTransformPacker( + string identifier, + Transform transform, + NetworkedDataDescriptor descriptor, + TransformPiece pieces, + INetworkGroup group) + { + Identifier = identifier; + _transform = transform; + _pieces = pieces; + _descriptor = descriptor; + + if (group == null) + return; + + group.RegisterHandler(this); + } + + // TODO: Find where to put this. + [Serializable] + internal struct PackedTransform + { + internal TransformPiece _dirtyPieces; + internal Vector3 _position; + internal Quaternion _rotation; + internal Vector3 _localScale; + } + + protected override object GetDataToSend + ( + ICollection targetPeers, + ReplicationMode replicationMode + ) + { + if (replicationMode.Transport != _descriptor.TransportType) + return NothingToWrite; + + if (!_descriptor.GetSenders().Contains(Group.Session.Networking.Self)) + return NothingToWrite; + + // Only send to target groups with one peer, so just grab the first peer + var firstPeerInTarget = targetPeers.First(); + if (targetPeers.Count != 1 || !_descriptor.GetReceivers().Contains(firstPeerInTarget)) + return NothingToWrite; + + // If we've never sent to this peer before, override the IsInitial flag. This happens + // when we are sending to a peer that just became an observer (but has already joined + // the session). + if (!_dirtyPeers.Contains(firstPeerInTarget)) + { + _dirtyPeers.Add(firstPeerInTarget); + replicationMode.IsInitial = true; + } + + var dirtyPieces = (TransformPiece)0; + + var shouldSendPosition = + HasFlag(_pieces, TransformPiece.Position) && + (_transform.position != _prevPosition || replicationMode.IsInitial); + + if (shouldSendPosition) + dirtyPieces |= TransformPiece.Position; + + var shouldSendRotation = + HasFlag(_pieces, TransformPiece.Rotation) && + (_transform.rotation != _prevRotation || replicationMode.IsInitial); + + if (shouldSendRotation) + dirtyPieces |= TransformPiece.Rotation; + + var shouldSendScale = + HasFlag(_pieces, TransformPiece.Scale) && + (_transform.localScale != _prevScale || replicationMode.IsInitial); + + if (shouldSendScale) + dirtyPieces |= TransformPiece.Scale; + + if (dirtyPieces == 0) + return NothingToWrite; + + _peersSentThisFrame.Add(targetPeers.First()); + + var result = new PackedTransform(); + result._dirtyPieces = dirtyPieces; + + if (HasFlag(dirtyPieces, TransformPiece.Position)) + { + if (_peersSentThisFrame.Count == _descriptor.GetReceivers().Count()) + _prevPosition = _transform.position; + + result._position = _transform.position; + } + + if (HasFlag(dirtyPieces, TransformPiece.Rotation)) + { + if (_peersSentThisFrame.Count == _descriptor.GetReceivers().Count()) + _prevRotation = _transform.rotation; + + result._rotation = _transform.rotation; + } + + if (HasFlag(dirtyPieces, TransformPiece.Scale)) + { + if (_peersSentThisFrame.Count == _descriptor.GetReceivers().Count()) + _prevScale = _transform.localScale; + + result._localScale = _transform.localScale; + } + + if (_peersSentThisFrame.Count == _descriptor.GetReceivers().Count()) + _peersSentThisFrame.Clear(); + + return result; + } + + protected override void HandleReceivedData + ( + object data, + IPeer sender, + ReplicationMode replicationMode + ) + { + if (!_descriptor.GetSenders().Contains(sender)) + return; + + var packedTransform = (PackedTransform)data; + var receivedPieces = packedTransform._dirtyPieces; + var relevantPieces = receivedPieces & _pieces; + + if (HasFlag(relevantPieces, TransformPiece.Position)) + _transform.position = packedTransform._position; + + if (HasFlag(relevantPieces, TransformPiece.Rotation)) + _transform.rotation = packedTransform._rotation; + + if (HasFlag(relevantPieces, TransformPiece.Scale)) + _transform.localScale = packedTransform._localScale; + } + + /// + private bool HasFlag(TransformPiece pieces, TransformPiece flag) + { + return (pieces & flag) != 0; + } + } +} diff --git a/Assets/ARDK/Networking/HLAPI/Object/UnreliableBroadcastTransformPacker.cs.meta b/Assets/ARDK/Networking/HLAPI/Object/UnreliableBroadcastTransformPacker.cs.meta new file mode 100644 index 0000000..41a1352 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Object/UnreliableBroadcastTransformPacker.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 13eea5721f5174231a5d726baeaa2bc3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Networking/HLAPI/Routing.meta b/Assets/ARDK/Networking/HLAPI/Routing.meta new file mode 100644 index 0000000..3cd06d1 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Routing.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: cd1b097853d44697b7aa6755ce1db4ed +timeCreated: 1537146746 \ No newline at end of file diff --git a/Assets/ARDK/Networking/HLAPI/Routing/NetworkId.cs b/Assets/ARDK/Networking/HLAPI/Routing/NetworkId.cs new file mode 100644 index 0000000..d099cb8 --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Routing/NetworkId.cs @@ -0,0 +1,70 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +/// @namespace Niantic.ARDK.Networking.HLAPI.Routing +/// @brief Routing over a network +namespace Niantic.ARDK.Networking.HLAPI.Routing +{ + /// + /// An id for representing something over the network. + /// + public struct NetworkId: + IEquatable + { + private readonly ulong _id; + + public NetworkId(ulong id) + { + _id = id; + } + + public ulong RawId + { + get + { + return _id; + } + } + + public bool Equals(NetworkId other) + { + return _id.Equals(other._id); + } + + public override bool Equals(object obj) + { + return obj is NetworkId && Equals((NetworkId)obj); + } + + public override int GetHashCode() + { + return _id.GetHashCode(); + } + + public override string ToString() + { + return _id.ToString(); + } + + public static explicit operator ulong(NetworkId id) + { + return id._id; + } + + public static explicit operator NetworkId(ulong id) + { + return new NetworkId(id); + } + + public static bool operator == (NetworkId id1, NetworkId id2) + { + return id1._id == id2._id; + } + + public static bool operator != (NetworkId id1, NetworkId id2) + { + return id1._id != id2._id; + } + } +} diff --git a/Assets/ARDK/Networking/HLAPI/Routing/NetworkId.cs.meta b/Assets/ARDK/Networking/HLAPI/Routing/NetworkId.cs.meta new file mode 100644 index 0000000..641a69b --- /dev/null +++ b/Assets/ARDK/Networking/HLAPI/Routing/NetworkId.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: adb49195f1374fabbe87cb67e6b3d3c4 +timeCreated: 1537148406 \ No newline at end of file diff --git a/Assets/ARDK/Networking/IMultipeerNetworking.cs b/Assets/ARDK/Networking/IMultipeerNetworking.cs new file mode 100644 index 0000000..00537a1 --- /dev/null +++ b/Assets/ARDK/Networking/IMultipeerNetworking.cs @@ -0,0 +1,172 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.IO; + +using Niantic.ARDK.AR; +using Niantic.ARDK.Networking.Clock; +using Niantic.ARDK.Networking.MultipeerNetworkingEventArgs; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Collections; + +namespace Niantic.ARDK.Networking +{ + public interface IMultipeerNetworking: + IDisposable + { + /// The runtime environment this MultipeerNetworking is compatible with. + RuntimeEnvironment RuntimeEnvironment { get; } + + /// A unique identifier for this MultipeerNetworking instance + Guid StageIdentifier { get; } + + /// A boolean indicating whether or not the instance has connected to a game or session via the + /// `Join` method. + bool IsConnected { get; } + + /// The local peer. + IPeer Self { get; } + + /// The host peer. + IPeer Host { get; } + + /// The set of all peers other than self for a particular connection. + IReadOnlyCollection OtherPeers { get; } + + /// This networking session's internal coordinated clock + ICoordinatedClock CoordinatedClock { get; } + + /// Sends `tag` and `data` to another peer using a specific transport type. + /// @param tag A unsigned integer that can be used to know how to resolve the format of the + /// bytes in `data` on the receiving side. + /// @param data An array of bytes to be sent to the receiving peer. + /// @param peer The peer to which to send the `tag` and `data`. + /// @param transportType Options that control the way the `tag` and `data` are sent to the peer. + /// @param sendToSelf Whether or not the local peer sending this data should also receive the + /// data locally in the `DidReceiveDataFromPeer` callback. + /// @note Please be aware of that the size of `data` may have adverse affects on overall + /// performance. + void SendDataToPeer( + uint tag, + byte[] data, + IPeer peer, + TransportType transportType, + bool sendToSelf = false); + + /// Sends `tag` and `data` to a number of peers using a specific transport type. + /// @param tag A unsigned integer the can be used to know how to resolve the format of the + /// bytes in `data` on the receiving side. + /// @param data An array of bytes to be sent to the receiving peers. + /// @param peers An array of peers to which to send the `tag` and `data`. If empty, will send to + /// all connected peers. + /// @param transportType Options that control the way the `tag` and `data` are sent to the + /// peers. + /// @param sendToSelf Whether or not the local peer sending this data should also receive the + /// data locally in the `DidReceiveDataFromPeer` callback. + /// @note Please be aware of that the size of `data` may have adverse affects on overall + /// performance. + /// @note Sending an empty list in the peers field will send data to all peers + void SendDataToPeers( + uint tag, + byte[] data, + IEnumerable peers, + TransportType transportType, + bool sendToSelf = false); + + /// Sends `tag` and `data` to all connected peers using a specific transport type. + /// @param tag A unsigned integer the can be used to know how to resolve the format of the + /// bytes in `data` on the receiving side. + /// @param data An array of bytes to be sent to all peers. + /// @param transportType Options that control the way the `tag` and `data` are sent to the + /// peers. + /// @param sendToSelf Whether or not the local peer sending this data should also receive the + /// data locally in the `DidReceiveDataFromPeer` callback. + /// @note Please be aware of that the size of `data` may have adverse affects on overall + /// performance. + void BroadcastData(uint tag, byte[] data, TransportType transportType, bool sendToSelf = false); + + /// Sends the `key` and `value` pair to a KeyValue store on the server. The KeyValue store + /// is persistent through the entire session. The server ensures that every client sees the + /// latest available value for every key. So this API can be used as a persistent and sync'd key + /// value store across all clients. Although every client will eventually see the latest value + /// for every key, clients may miss intermediate values. If multiple clients are writing to the + /// same key, the last update to make it over the internet to the server wins. + /// @param key The key for the value being stored + /// @param value The value to store + void StorePersistentKeyValue(string key, byte[] value); + + /// + /// Sends the specified data to the ARM server (if connected to an ARM session) with the tag + /// @note This is currently undergoing internal development and testing, and will not do anything. + /// + /// Tag that will be sent to the ARM server + /// Data that will be sent to the ARM server + void SendDataToArm(uint tag, byte[] data); + + /// Joins a specific game or session. Games or sessions are linked by `metadata`. Meaning that + /// in order for two peers to join the same game or session, they must use the same `metadata` + /// value. + void Join(byte[] metadata, byte[] token = null, Int64 timestamp = 0); + + /// Leaves a specific game or session. + /// @note After leaving a session, the IMultipeerNetworking object cannot be reused to join a + /// new session (or rejoin the old one). Dispose the existing object and create a new + /// IMultipeerNetworking object to join a new session. + void Leave(); + + /// + /// Returns a string representation of the MultipeerNetworking. + /// + /// A string representation of the MultipeerNetworking + string ToString(); + + /// + /// Returns a truncated string representation of the MultipeerNetworking, for easy printing. + /// + /// The character limit of the returned string + /// A truncated string representation of the MultipeerNetworking + string ToString(int count); + + /// Event fired upon connection success. + event ArdkEventHandler Connected; + + /// Event fired when a join command failed. + event ArdkEventHandler ConnectionFailed; + + /// Event fired when this class is about to disconnect. + event ArdkEventHandler Disconnected; + + /// Event fired whenever a message is received from another peer. + event ArdkEventHandler PeerDataReceived; + + /// Event fired when a peer is added. + event ArdkEventHandler PeerAdded; + + /// Event fired when a peer is removed, either from intentional action, timeout, or error. + event ArdkEventHandler PeerRemoved; + + /// Event fired when someone has added a new key-value pair to the server KeyValue store, + /// or updated an existing one. + event ArdkEventHandler PersistentKeyValueUpdated; + + /// Event fired when this object is about to deinitialize. + event ArdkEventHandler Deinitialized; + + /// + /// Event fired when receiving data from an ARM server + /// @note This is currently undergoing internal development and testing, and will not be fired. + /// + event ArdkEventHandler DataReceivedFromArm; + + /// + /// @note This is currently undergoing internal development and testing, and will not be fired. + /// + event ArdkEventHandler SessionStatusReceivedFromArm; + + /// + /// @note This is currently undergoing internal development and testing, and will not be fired. + /// + event ArdkEventHandler SessionResultReceivedFromArm; + } +} diff --git a/Assets/ARDK/Networking/IMultipeerNetworking.cs.meta b/Assets/ARDK/Networking/IMultipeerNetworking.cs.meta new file mode 100644 index 0000000..f3d8c9d --- /dev/null +++ b/Assets/ARDK/Networking/IMultipeerNetworking.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3b982de5d435442efbc7638dd95e39e0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Networking/IPeer.cs b/Assets/ARDK/Networking/IPeer.cs new file mode 100644 index 0000000..d6c4069 --- /dev/null +++ b/Assets/ARDK/Networking/IPeer.cs @@ -0,0 +1,19 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +namespace Niantic.ARDK.Networking +{ + public interface IPeer: + IEquatable + { + /// + /// A unique identifier for the peer + /// + Guid Identifier { get; } + + string ToString(); + + string ToString(int count); + } +} diff --git a/Assets/ARDK/Networking/IPeer.cs.meta b/Assets/ARDK/Networking/IPeer.cs.meta new file mode 100644 index 0000000..e5e58d1 --- /dev/null +++ b/Assets/ARDK/Networking/IPeer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f5ce896b64364617b52d341da1726a1e +timeCreated: 1540479305/ \ No newline at end of file diff --git a/Assets/ARDK/Networking/MultipeerNetworkingEventArgs.meta b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs.meta new file mode 100644 index 0000000..8a94c62 --- /dev/null +++ b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ce5970da8c3d34941a266a3844d35855 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/AnyMultipeerNetworkingInitializedArgs.cs b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/AnyMultipeerNetworkingInitializedArgs.cs new file mode 100644 index 0000000..96d0fee --- /dev/null +++ b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/AnyMultipeerNetworkingInitializedArgs.cs @@ -0,0 +1,17 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.Networking.MultipeerNetworkingEventArgs +{ + public struct AnyMultipeerNetworkingInitializedArgs: + IArdkEventArgs + { + public readonly IMultipeerNetworking Networking; + + public AnyMultipeerNetworkingInitializedArgs(IMultipeerNetworking networking) + { + Networking = networking; + } + } +} diff --git a/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/AnyMultipeerNetworkingInitializedArgs.cs.meta b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/AnyMultipeerNetworkingInitializedArgs.cs.meta new file mode 100644 index 0000000..19caf0b --- /dev/null +++ b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/AnyMultipeerNetworkingInitializedArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 584625f79f66040468273b7f313c3fa8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/ConnectedArgs.cs b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/ConnectedArgs.cs new file mode 100644 index 0000000..f50c889 --- /dev/null +++ b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/ConnectedArgs.cs @@ -0,0 +1,27 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.Networking.MultipeerNetworkingEventArgs +{ + public struct ConnectedArgs: + IArdkEventArgs + { + public ConnectedArgs(IPeer self, IPeer host): + this() + { + Self = self; + Host = host; + } + public IPeer Self { get; private set; } + public IPeer Host { get; private set; } + + public bool IsHost + { + get + { + return Self.Equals(Host); + } + } + } +} diff --git a/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/ConnectedArgs.cs.meta b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/ConnectedArgs.cs.meta new file mode 100644 index 0000000..7604bb7 --- /dev/null +++ b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/ConnectedArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b3669e5fb47af4e32b66fb640a4a697b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/ConnectionFailedArgs.cs b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/ConnectionFailedArgs.cs new file mode 100644 index 0000000..680d1b2 --- /dev/null +++ b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/ConnectionFailedArgs.cs @@ -0,0 +1,17 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.Networking.MultipeerNetworkingEventArgs +{ + public struct ConnectionFailedArgs: + IArdkEventArgs + { + public ConnectionFailedArgs(uint errorCode): + this() + { + ErrorCode = errorCode; + } + public uint ErrorCode { get; private set; } + } +} diff --git a/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/ConnectionFailedArgs.cs.meta b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/ConnectionFailedArgs.cs.meta new file mode 100644 index 0000000..cc554ce --- /dev/null +++ b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/ConnectionFailedArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1448f9971c9d34b299519f717fb6a0ac +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/DataReceivedFromArmArgs.cs b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/DataReceivedFromArmArgs.cs new file mode 100644 index 0000000..16ee629 --- /dev/null +++ b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/DataReceivedFromArmArgs.cs @@ -0,0 +1,27 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.IO; + +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.Networking.MultipeerNetworkingEventArgs +{ + public struct DataReceivedFromArmArgs: + IArdkEventArgs + { + public DataReceivedFromArmArgs(uint tag, byte[] data): + this() + { + Tag = tag; + _data = data; + } + + public uint Tag { get; private set; } + + private readonly byte[] _data; + public MemoryStream CreateDataReader() + { + return new MemoryStream(_data, false); + } + } +} diff --git a/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/DataReceivedFromArmArgs.cs.meta b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/DataReceivedFromArmArgs.cs.meta new file mode 100644 index 0000000..79067f8 --- /dev/null +++ b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/DataReceivedFromArmArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 22e09ba4bda344cfb91113131b440dca +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/DeinitializedArgs.cs b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/DeinitializedArgs.cs new file mode 100644 index 0000000..5bca152 --- /dev/null +++ b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/DeinitializedArgs.cs @@ -0,0 +1,11 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.Networking.MultipeerNetworkingEventArgs +{ + public struct DeinitializedArgs: + IArdkEventArgs + { + } +} diff --git a/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/DeinitializedArgs.cs.meta b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/DeinitializedArgs.cs.meta new file mode 100644 index 0000000..4e75556 --- /dev/null +++ b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/DeinitializedArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4fa563c59e78a49af86c3476cc14d389 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/DisconnectedArgs.cs b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/DisconnectedArgs.cs new file mode 100644 index 0000000..7887753 --- /dev/null +++ b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/DisconnectedArgs.cs @@ -0,0 +1,11 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.Networking.MultipeerNetworkingEventArgs +{ + public struct DisconnectedArgs: + IArdkEventArgs + { + } +} diff --git a/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/DisconnectedArgs.cs.meta b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/DisconnectedArgs.cs.meta new file mode 100644 index 0000000..b00e578 --- /dev/null +++ b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/DisconnectedArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4ad75bf9794a7490eb64ef8290137088 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/PeerAddedArgs.cs b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/PeerAddedArgs.cs new file mode 100644 index 0000000..616dcc7 --- /dev/null +++ b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/PeerAddedArgs.cs @@ -0,0 +1,18 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.Networking.MultipeerNetworkingEventArgs +{ + public struct PeerAddedArgs: + IArdkEventArgs + { + public PeerAddedArgs(IPeer peer): + this() + { + Peer = peer; + } + + public IPeer Peer { get; private set; } + } +} diff --git a/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/PeerAddedArgs.cs.meta b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/PeerAddedArgs.cs.meta new file mode 100644 index 0000000..30fb6e9 --- /dev/null +++ b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/PeerAddedArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b0d57187224b54623a2d536f6f2a8991 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/PeerDataReceivedArgs.cs b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/PeerDataReceivedArgs.cs new file mode 100644 index 0000000..795849e --- /dev/null +++ b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/PeerDataReceivedArgs.cs @@ -0,0 +1,44 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.IO; + +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.Networking.MultipeerNetworkingEventArgs +{ + public struct PeerDataReceivedArgs: + IArdkEventArgs + { + public PeerDataReceivedArgs(IPeer peer, uint tag, TransportType transportType, byte[] data): + this() + { + Peer = peer; + Tag = tag; + TransportType = transportType; + _data = data; + } + + public IPeer Peer { get; private set; } + public uint Tag { get; private set; } + public TransportType TransportType { get; private set; } + + private readonly byte[] _data; + public int DataLength + { + get { return _data.Length; } + } + + public MemoryStream CreateDataReader() + { + return new MemoryStream(_data, false); + } + + public byte[] CopyData() + { + var result = new byte[_data.Length]; + Buffer.BlockCopy(_data, 0, result, 0, _data.Length); + return result; + } + } +} diff --git a/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/PeerDataReceivedArgs.cs.meta b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/PeerDataReceivedArgs.cs.meta new file mode 100644 index 0000000..32daa4b --- /dev/null +++ b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/PeerDataReceivedArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 53c1e9f9c251a46698400f7cd5a2c793 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/PeerRemovedArgs.cs b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/PeerRemovedArgs.cs new file mode 100644 index 0000000..1edfb70 --- /dev/null +++ b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/PeerRemovedArgs.cs @@ -0,0 +1,18 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.Networking.MultipeerNetworkingEventArgs +{ + public struct PeerRemovedArgs: + IArdkEventArgs + { + public PeerRemovedArgs(IPeer peer): + this() + { + Peer = peer; + } + + public IPeer Peer { get; private set; } + } +} diff --git a/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/PeerRemovedArgs.cs.meta b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/PeerRemovedArgs.cs.meta new file mode 100644 index 0000000..c2a9c06 --- /dev/null +++ b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/PeerRemovedArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c0306a887869d46a78ec13a8a3772d5f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/PersistentKeyValueUpdatedArgs.cs b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/PersistentKeyValueUpdatedArgs.cs new file mode 100644 index 0000000..56408c8 --- /dev/null +++ b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/PersistentKeyValueUpdatedArgs.cs @@ -0,0 +1,32 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.IO; + +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.Networking.MultipeerNetworkingEventArgs +{ + public struct PersistentKeyValueUpdatedArgs: + IArdkEventArgs + { + public PersistentKeyValueUpdatedArgs(string key, byte[] value): + this() + { + Key = key; + _value = value; + } + + public string Key { get; private set; } + + private readonly byte[] _value; + public MemoryStream CreateValueReader() + { + return new MemoryStream(_value, false); + } + + public byte[] CopyValue() + { + return (byte[])_value.Clone(); + } + } +} diff --git a/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/PersistentKeyValueUpdatedArgs.cs.meta b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/PersistentKeyValueUpdatedArgs.cs.meta new file mode 100644 index 0000000..eb7e002 --- /dev/null +++ b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/PersistentKeyValueUpdatedArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0748a6556daec4ed8b39c8a690d56094 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/SessionResultReceivedFromArmArgs.cs b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/SessionResultReceivedFromArmArgs.cs new file mode 100644 index 0000000..6b7b286 --- /dev/null +++ b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/SessionResultReceivedFromArmArgs.cs @@ -0,0 +1,27 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.IO; + +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.Networking.MultipeerNetworkingEventArgs +{ + public struct SessionResultReceivedFromArmArgs: + IArdkEventArgs + { + public SessionResultReceivedFromArmArgs(uint outcome, byte[] details): + this() + { + Outcome = outcome; + _details = details; + } + + public uint Outcome { get; private set; } + + private readonly byte[] _details; + public MemoryStream CreateDetailsReader() + { + return new MemoryStream(_details, false); + } + } +} diff --git a/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/SessionResultReceivedFromArmArgs.cs.meta b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/SessionResultReceivedFromArmArgs.cs.meta new file mode 100644 index 0000000..d79ae3e --- /dev/null +++ b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/SessionResultReceivedFromArmArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9f4176057383a4ca4a5cb5c8ef036a23 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/SessionStatusReceivedFromArmArgs.cs b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/SessionStatusReceivedFromArmArgs.cs new file mode 100644 index 0000000..8a5cdd4 --- /dev/null +++ b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/SessionStatusReceivedFromArmArgs.cs @@ -0,0 +1,18 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.Networking.MultipeerNetworkingEventArgs +{ + public struct SessionStatusReceivedFromArmArgs: + IArdkEventArgs + { + public SessionStatusReceivedFromArmArgs(uint status): + this() + { + Status = status; + } + + public uint Status { get; private set; } + } +} diff --git a/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/SessionStatusReceivedFromArmArgs.cs.meta b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/SessionStatusReceivedFromArmArgs.cs.meta new file mode 100644 index 0000000..6ccfe74 --- /dev/null +++ b/Assets/ARDK/Networking/MultipeerNetworkingEventArgs/SessionStatusReceivedFromArmArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bc086a91d0bba4ec7a45b4d25a3fc691 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Networking/MultipeerNetworkingFactory.cs b/Assets/ARDK/Networking/MultipeerNetworkingFactory.cs new file mode 100644 index 0000000..afab1e0 --- /dev/null +++ b/Assets/ARDK/Networking/MultipeerNetworkingFactory.cs @@ -0,0 +1,337 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.ComponentModel; + +using Niantic.ARDK.AR; +using Niantic.ARDK.VirtualStudio; +using Niantic.ARDK.VirtualStudio.Networking; +using Niantic.ARDK.VirtualStudio.Networking.Mock; +using Niantic.ARDK.Networking.MultipeerNetworkingEventArgs; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Collections; +using Niantic.ARDK.Utilities.Logging; +using Niantic.ARDK.VirtualStudio.Remote; + +namespace Niantic.ARDK.Networking +{ + /// A class to create new MultipeerNetworking instances as well as to be notified of their + /// creation. + public static class MultipeerNetworkingFactory + { + /// Initializes the static members of this class that depend on previously initialized members. + static MultipeerNetworkingFactory() + { + _readOnlyNetworkings = _networkings.AsArdkReadOnly(); + } + + /// Create a MultipeerNetworking appropriate for the current device. + /// + /// On a mobile device, the attempted order will be LiveDevice, Remote, and finally Mock. + /// In the Unity Editor, the attempted order will be Remote, then Mock. + /// + /// @param stageIdentifier + /// The identifier used by the C++ library to connect all related components. + /// + /// @returns The created MultipeerNetworking, or throws if it was not possible to create a session. + public static IMultipeerNetworking Create(Guid stageIdentifier = default(Guid)) + { + return _Create(ServerConfiguration.ARBE, null, stageIdentifier); + } + + public static IMultipeerNetworking Create + ( + ServerConfiguration serverConfiguration, + Guid stageIdentifier = default + ) + { + return _Create(serverConfiguration, null, stageIdentifier); + } + + /// Create a MultipeerNetworking with the specified RuntimeEnvironment. + /// + /// @param env + /// The env used to create the MultipeerNetworking. + /// @param stageIdentifier + /// The identifier used by the C++ library to connect all related components. + /// + /// @returns The created MultipeerNetworking, or throws if it was not possible to create a session. + public static IMultipeerNetworking Create(RuntimeEnvironment env, Guid stageIdentifier = default(Guid)) + { + var networking = _Create(env, stageIdentifier, ServerConfiguration.ARBE); + if (networking == null) + { + throw new NotSupportedException + ("The provided env is not supported by this build."); + } + + return networking; + } + + /// Create a MultipeerNetworking with the specified RuntimeEnvironment. + /// + /// @param env + /// The env used to create the MultipeerNetworking. + /// @param serverConfiguration + /// The ServerConfiguration that this MultipeerNetworking will use to communicate with ARBEs + /// @param stageIdentifier + /// The identifier used by the C++ library to connect all related components. + /// + /// @returns The created MultipeerNetworking, or throws if it was not possible to create a session. + public static IMultipeerNetworking Create + ( + RuntimeEnvironment env, + ServerConfiguration serverConfiguration, + Guid stageIdentifier = default(Guid) + ) + { + var networking = _Create(env, stageIdentifier, serverConfiguration); + if (networking == null) + { + throw new NotSupportedException + ("The the provided env is not supported by this build."); + } + + return networking; + } + + /// A collection of all current networking stacks + public static IReadOnlyCollection Networkings + { + get + { + return _readOnlyNetworkings; + } + } + + private static ArdkEventHandler _networkingInitialized; + + /// Event called when a new MultipeerNetworking instance is initialized. + public static event ArdkEventHandler NetworkingInitialized + { + add + { + _StaticMemberValidator._FieldIsNullWhenScopeEnds(() => _networkingInitialized); + + _networkingInitialized += value; + + // If there already exists some networkings, call the event so you don't miss anything + foreach (var networking in _networkings) + { + var args = new AnyMultipeerNetworkingInitializedArgs(networking); + value(args); + } + } + remove + { + _networkingInitialized -= value; + } + } + + /// Tries to create a MultipeerNetworking of any of the given envs. + /// + /// @param configuration + /// Configuration object telling how to connect to the server. + /// @param envs + /// A collection of envs used to create the networking for. As not all platforms support + /// all envs, the code will try to create the networking for the first env, then for the + /// second and so on. If envs is null or empty, then the order used is LiveDevice, + /// Remote and finally Mock. + /// @param stageIdentifier + /// The identifier used by the C++ library to connect all related components. + /// + /// @returns The created networking, or null if it was not possible to create the object. + internal static IMultipeerNetworking _Create + ( + ServerConfiguration configuration, + IEnumerable envs = null, + Guid stageIdentifier = default(Guid) + ) + { + bool triedAtLeast1 = false; + + if (envs != null) + { + foreach (var env in envs) + { + var possibleResult = _Create(env, stageIdentifier, configuration); + if (possibleResult != null) + return possibleResult; + + triedAtLeast1 = true; + } + } + + if (!triedAtLeast1) + return _Create(configuration, ARSessionFactory._defaultBestMatches, stageIdentifier); + + throw new NotSupportedException("None of the provided envs are supported by this build."); + } + + internal static IMultipeerNetworking _CreateVirtualStudioManagedNetworking + ( + RuntimeEnvironment env, + ServerConfiguration configuration, + Guid stageIdentifier, + _IVirtualStudioManager virtualStudioMaster, + bool isLocal + ) + { + IMultipeerNetworking implementation; + switch (env) + { + case RuntimeEnvironment.Mock: + implementation = new _MockMultipeerNetworking(stageIdentifier, virtualStudioMaster); + break; + + case RuntimeEnvironment.Remote: + implementation = new _RemoteEditorMultipeerNetworking(configuration, stageIdentifier); + break; + + default: + // Both LiveDevice and Default are invalid cases for this method + throw new ArgumentOutOfRangeException(nameof(env), env, null); + } + + _InvokeNetworkingInitialized(implementation, isLocal); + return implementation; + } + + private static IMultipeerNetworking _Create + ( + RuntimeEnvironment env, + Guid stageIdentifier, + ServerConfiguration configuration + ) + { + if (stageIdentifier == default(Guid)) + stageIdentifier = Guid.NewGuid(); + + IMultipeerNetworking result; + switch (env) + { + case RuntimeEnvironment.Default: + return Create(configuration, stageIdentifier); + + case RuntimeEnvironment.LiveDevice: + result = new _NativeMultipeerNetworking(configuration, stageIdentifier); + break; + + case RuntimeEnvironment.Remote: + if (!_RemoteConnection.IsEnabled) + return null; + + result = new _RemoteEditorMultipeerNetworking(configuration, stageIdentifier); + break; + + case RuntimeEnvironment.Mock: + result = new _MockMultipeerNetworking(stageIdentifier, _VirtualStudioManager.Instance); + break; + + default: + throw new InvalidEnumArgumentException(nameof(env), (int)env, env.GetType()); + } + + _InvokeNetworkingInitialized(result, isLocal: true); + return result; + } + + internal static _NativeMultipeerNetworking _CreateLiveDeviceNetworking + ( + ServerConfiguration serverConfiguration, + Guid stageIdentifier, + bool isLocal + ) + { + var result = new _NativeMultipeerNetworking(serverConfiguration, stageIdentifier); + _InvokeNetworkingInitialized(result, isLocal); + return result; + } + + private static + ArdkEventHandler _nonLocalNetworkingInitialized; + + internal static event + ArdkEventHandler _NonLocalNetworkingInitialized + { + add + { + _StaticMemberValidator._FieldIsNullWhenScopeEnds(() => _nonLocalNetworkingInitialized); + + _nonLocalNetworkingInitialized += value; + + // If there already exists some networkings, call the event so you don't miss anything + foreach (var networking in _nonLocalNetworkings) + { + var args = new AnyMultipeerNetworkingInitializedArgs(networking); + value(args); + } + } + remove + { + _nonLocalNetworkingInitialized -= value; + } + } + + #region Implementation + private static readonly ARDKReadOnlyCollection _readOnlyNetworkings; + + private static readonly HashSet _networkings = + new HashSet(_ReferenceComparer.Instance); + + private static readonly HashSet _nonLocalNetworkings = + new HashSet(_ReferenceComparer.Instance); + + private static void _InvokeNetworkingInitialized(IMultipeerNetworking networking, bool isLocal) + { + if (SessionExists(networking, isLocal)) + { + ARLog._WarnFormat + ( + "An IMultipeerNetworking instance with the StageIdentifier {0} was already initialized.", + false, + networking.StageIdentifier + ); + + return; + } + + ArdkEventHandler handler; + + if (isLocal) + { + ARLog._Debug("Initializing a local session"); + _StaticMemberValidator._CollectionIsEmptyWhenScopeEnds(() => _networkings); + + _networkings.Add(networking); + networking.Deinitialized += (_) => _networkings.Remove(networking); + handler = _networkingInitialized; + } + else + { + ARLog._Debug("Initializing a non-local session"); + _StaticMemberValidator._CollectionIsEmptyWhenScopeEnds(() => _nonLocalNetworkings); + + _nonLocalNetworkings.Add(networking); + networking.Deinitialized += (_) => _nonLocalNetworkings.Remove(networking); + handler = _nonLocalNetworkingInitialized; + } + + if (handler != null) + { + var args = new AnyMultipeerNetworkingInitializedArgs(networking); + handler(args); + } + } + + private static bool SessionExists(IMultipeerNetworking networking, bool isLocal) + { + if (isLocal) + return _networkings.Contains(networking); + + return _nonLocalNetworkings.Contains(networking); + } + #endregion + } +} diff --git a/Assets/ARDK/Networking/MultipeerNetworkingFactory.cs.meta b/Assets/ARDK/Networking/MultipeerNetworkingFactory.cs.meta new file mode 100644 index 0000000..9330b25 --- /dev/null +++ b/Assets/ARDK/Networking/MultipeerNetworkingFactory.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 790a1899c3c11454a97dc95c14e5fc08 +timeCreated: 1536268533 +licenseType: Pro +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Networking/NetworkMessageSizeLimits.cs b/Assets/ARDK/Networking/NetworkMessageSizeLimits.cs new file mode 100644 index 0000000..f8f56db --- /dev/null +++ b/Assets/ARDK/Networking/NetworkMessageSizeLimits.cs @@ -0,0 +1,30 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.Networking +{ + /// + /// Information about the maximum size of various network message components. + /// + public static class NetworkMessageSizeLimits + { + /// + /// 8000 bytes + /// + public static readonly int MaxUnreliableMessageSize = 8000; + + /// + /// 10 MB + /// + public static readonly int MaxReliableMessageSize = 10 * 1024 * 1024; + + /// + /// 4 KB + /// + public static readonly int MaxPersistentKeyValueKeySize = 4 * 1024; + + /// + /// 100 MB + /// + public static readonly int MaxPersistentKeyValueValueSize = 100 * 1024 * 1024; + } +} diff --git a/Assets/ARDK/Networking/NetworkMessageSizeLimits.cs.meta b/Assets/ARDK/Networking/NetworkMessageSizeLimits.cs.meta new file mode 100644 index 0000000..6329d82 --- /dev/null +++ b/Assets/ARDK/Networking/NetworkMessageSizeLimits.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: fb929e891bba4d148c2440fb93ba0ece +timeCreated: 1610499536 \ No newline at end of file diff --git a/Assets/ARDK/Networking/NetworkingErrorCode.cs b/Assets/ARDK/Networking/NetworkingErrorCode.cs new file mode 100644 index 0000000..45684c2 --- /dev/null +++ b/Assets/ARDK/Networking/NetworkingErrorCode.cs @@ -0,0 +1,39 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; + +namespace Niantic.ARDK.Networking +{ + // Possible networking error codes when authenticating or connecting to ARBEs + public enum NetworkingErrorCode : Int32 + { + Unknown = 0, + // 1-100 - Handshake errors + + // OK + Ok = 200, + + // ARBE-specific + ARBENotSet = 500, + ARBEConnection, + ARBEHttp, + ARBEResponse, + ARBEVersion, + + // Auth server + AuthNotSet = 600, + AuthConnection, + AuthHttp, + AuthResponse, + + // Api key + ApiKeyInvalid = 700, + ApiKeyNotSet, + + // UDP errors + UdpInvalid = 800, + + // Unexpected + Unexpected = 911, + + } +} diff --git a/Assets/ARDK/Networking/NetworkingErrorCode.cs.meta b/Assets/ARDK/Networking/NetworkingErrorCode.cs.meta new file mode 100644 index 0000000..6c64234 --- /dev/null +++ b/Assets/ARDK/Networking/NetworkingErrorCode.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 03f938ed87764c3fb47c18721a95814c +timeCreated: 1630368933 \ No newline at end of file diff --git a/Assets/ARDK/Networking/ServerConfiguration.cs b/Assets/ARDK/Networking/ServerConfiguration.cs new file mode 100644 index 0000000..da6ef14 --- /dev/null +++ b/Assets/ARDK/Networking/ServerConfiguration.cs @@ -0,0 +1,95 @@ +#define AUTH_REQUIRED +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; + +namespace Niantic.ARDK.Networking +{ + [Serializable] + public struct ServerConfiguration + { + public static readonly int DefaultHeartbeatFrequency = 1000; + +#if AUTH_REQUIRED + public static readonly bool AuthRequired = true; +#else + public static readonly bool AuthRequired = false; +#endif + + /// + /// Endpoint that serves an ARBE address + public key, and is used to connect in native. + /// + public static readonly string ARBEEndpoint = "https://ardk.eng.nianticlabs.com:8084/publickey"; + + /// + /// API key to use for authenticating the application. Create a Resources/ARDK directory and + /// add an ArdkAuthConfig scriptable object with your API key to ensure that authentication + /// automatically happens when your application is loaded. + /// + public static string ApiKey { get; set; } + + /// + /// URL at which the API key will be authenticated. + /// @note This can only be set for internal testing. Other attempts to set it will no-op. + /// + public static string AuthenticationUrl { get; set; } + + /// + /// Generates a ServerConfiguration pointed at ARBEs, with no defined ClientMetadata. If the + /// ClientMetadata is not defined when this ServerConfiguration is used to generate an + /// IMultipeerNetworking, a random Guid will be generated + /// + public static ServerConfiguration ARBE + { + get + { + return + new ServerConfiguration + ( + DefaultHeartbeatFrequency, + ARBEEndpoint + ); + } + } + + public int HeartbeatFrequency; + public string Endpoint; + public byte[] ClientMetadata; + + public ServerConfiguration(string endpoint) + : this + ( + DefaultHeartbeatFrequency, + endpoint + ) + { + } + public ServerConfiguration + ( + int heartbeatFrequency, + string endpoint + ) + : this() + { + HeartbeatFrequency = heartbeatFrequency; + Endpoint = endpoint; + } + public ServerConfiguration + ( + int heartbeatFrequency, + string endpoint, + byte[] clientMetadata + ) + : this() + { + HeartbeatFrequency = heartbeatFrequency; + ClientMetadata = clientMetadata; + Endpoint = endpoint; + } + + // Populate the ClientId with a random Guid + internal void GenerateRandomClientId() + { + ClientMetadata = Guid.NewGuid().ToByteArray(); + } + } +} diff --git a/Assets/ARDK/Networking/ServerConfiguration.cs.meta b/Assets/ARDK/Networking/ServerConfiguration.cs.meta new file mode 100644 index 0000000..e34f624 --- /dev/null +++ b/Assets/ARDK/Networking/ServerConfiguration.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e5fdddd4230d4c44bf55876a638e4c51 +timeCreated: 1545410807 \ No newline at end of file diff --git a/Assets/ARDK/Networking/TransportType.cs b/Assets/ARDK/Networking/TransportType.cs new file mode 100644 index 0000000..d3793e6 --- /dev/null +++ b/Assets/ARDK/Networking/TransportType.cs @@ -0,0 +1,34 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.Networking +{ + /// + /// The method of getting data to other clients + /// + public enum TransportType: + byte + { + /// + /// Messages may drop, and won't be re-sent. + /// They may arrive out of order, or not at all + /// + UnreliableUnordered = 1, + + /// + /// Messages may be dropped, but they will be delivered in order. + /// + UnreliableOrdered = 2, + + /// + /// Messages will eventually arrive at each destination they're sent to. + /// However, they may arrive out of order in doing so. + /// + ReliableUnordered = 3, + + /// + /// Messages sent with this transport type will be received by each other peer + /// in the order they were sent. Won't be dropped or arrive out of order + /// + ReliableOrdered = 4, + }; +} \ No newline at end of file diff --git a/Assets/ARDK/Networking/TransportType.cs.meta b/Assets/ARDK/Networking/TransportType.cs.meta new file mode 100644 index 0000000..155f459 --- /dev/null +++ b/Assets/ARDK/Networking/TransportType.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 47a5b41ab82e4363a6ac32881f483502 +timeCreated: 1607554831 \ No newline at end of file diff --git a/Assets/ARDK/Networking/_NativeMultipeerNetworking.cs b/Assets/ARDK/Networking/_NativeMultipeerNetworking.cs new file mode 100644 index 0000000..06189a0 --- /dev/null +++ b/Assets/ARDK/Networking/_NativeMultipeerNetworking.cs @@ -0,0 +1,1563 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; + +using AOT; + +using Niantic.ARDK.AR; +using Niantic.ARDK.Internals; +using Niantic.ARDK.Networking.Clock; +using Niantic.ARDK.Networking.MultipeerNetworkingEventArgs; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Collections; +using Niantic.ARDK.Utilities.Logging; + +namespace Niantic.ARDK.Networking +{ + //! Handles multipeer networking sessions + /// + /// Provides events for peers joining/leaving the session, receiving data from peers, setup status\n + /// Provides fields for querying a list of peers, the host of the session, local player\n + /// Provides methods for joining/leaving a session, sending data to one or more peers + /// + internal sealed class _NativeMultipeerNetworking: + _ThreadCheckedObject, + IMultipeerNetworking + { + /// + public Guid StageIdentifier { get; private set; } + + /// + public bool IsConnected { get; private set; } + + private byte[] _joinedSessionMetadata; + + // Privately handled lookup of peers. Peers are registered on DidAddPeer and removed on + // DidRemovePeer + private readonly Dictionary _peers = new Dictionary(); + private readonly ARDKReadOnlyCollection _readOnlyPeers; + + // Keys used in the persistent key-value store prefixed by ! are reserved for the server + private static readonly char KeyValueKeyReservedPrefix = '!'; + + /// + public IReadOnlyCollection OtherPeers + { + get + { + // Ideally all the inner methods should also be thread checked... but this basic check + // should avoid really bad cases from happening. + _CheckThread(); + + return _readOnlyPeers; + } + } + + /// + public IPeer Self { get; private set; } + + /// + public IPeer Host { get; private set; } + + /// + /// Get a copy of the session metadata that this _NativeMultipeerNetworking is currently + /// connected to. + /// @note The output of this property should not be changed, but is returned as an array + /// for performance. + /// @note Will return null if the session is not connected. + /// + public byte[] GetJoinedSessionMetadata() + { + _CheckThread(); + + if (_joinedSessionMetadata == null) + return null; + + var metadataCopy = new byte[_joinedSessionMetadata.Length]; + _joinedSessionMetadata.CopyTo(metadataCopy, 0); + + return metadataCopy; + } + + private ICoordinatedClock _clock; + + public ICoordinatedClock CoordinatedClock + { + get + { + _CheckThread(); + + if (_clock == null) + { + ARLog._Debug("Creating a new _NativeCoordinatedClock"); + _clock = new _NativeCoordinatedClock(StageIdentifier); + } + + return _clock; + } + } + + /// + /// Set to true if the _NativeMultipeerNetworking is destroyed, or if the underlying native code + /// is explicitly destroyed with Destroy. Prevents any currently queued callbacks from + /// processing + /// + internal bool IsDestroyed { get; private set; } + + /// + public void Join(byte[] metadata, byte[] token = null, Int64 timestamp = 0) + { + if (metadata == null || metadata.Length == 0) + throw new ArgumentException("Cannot be null or empty.", nameof(metadata)); + + _CheckThread(); + + if (_nativeHandle == IntPtr.Zero) + throw new ObjectDisposedException("Multipeer networking was destroyed!", (Exception)null); + + if (IsConnected) + { + ARLog._Warn + ( + metadata.SequenceEqual(_joinedSessionMetadata) + ? "ARDK: Already joined this session." + : "ARDK: Already connected to a different session." + ); + + return; + } + + ARLog._DebugFormat("Attempting to join session: {0}", false, Encoding.UTF8.GetString(metadata)); + + if (ServerConfiguration.AuthRequired) + { + if (string.IsNullOrEmpty(ServerConfiguration.ApiKey)) + { + ARLog._Error("Cannot join session without ServerConfiguration.ApiKey set"); + } + var apiKeyAsBytes = Encoding.UTF8.GetBytes(ServerConfiguration.ApiKey); + + var lengthOfMetadata = Math.Max(metadata.Length, apiKeyAsBytes.Length); + var sessionMetadataWithAuth = new byte[lengthOfMetadata]; + + Array.Copy(metadata, sessionMetadataWithAuth, metadata.Length); + + for (var i = 0; i < Math.Min(apiKeyAsBytes.Length, sessionMetadataWithAuth.Length); i++) + { + sessionMetadataWithAuth[i] ^= apiKeyAsBytes[i]; + } + + _joinedSessionMetadata = sessionMetadataWithAuth; + + _NARMultipeerNetworking_Join + ( + _nativeHandle, + sessionMetadataWithAuth, + (ulong)sessionMetadataWithAuth.Length + ); + } + else + { + _joinedSessionMetadata = metadata; + + _NARMultipeerNetworking_Join + ( + _nativeHandle, + metadata, + (ulong)metadata.Length + ); + } + } + + /// + public void Leave() + { + _CheckThread(); + + if (_nativeHandle == IntPtr.Zero) + throw new ObjectDisposedException("Multipeer networking was destroyed!", (Exception)null); + + if (!IsConnected) + { + ARLog._Warn("ARDK: Cannot leave a multipeer networking session that is not connected."); + + return; + } + + var metadata = _joinedSessionMetadata; + + ARLog._DebugFormat("Leaving session: {0}", false, Encoding.UTF8.GetString(metadata)); + + _NARMultipeerNetworking_Leave(_nativeHandle, metadata, (ulong)metadata.Length); + _peers.Clear(); + IsConnected = false; + _joinedSessionMetadata = null; + + var handler = Disconnected; + if (handler != null) + { + var args = new DisconnectedArgs(); + handler(args); + } + } + + /// + public void SendDataToPeer + ( + uint tag, + byte[] data, + IPeer peer, + TransportType transportType, + bool sendToSelf = false + ) + { + if (peer == null) + throw new ArgumentNullException(nameof(peer)); + + // TODO: stackalloc when unsafe? + SendDataToPeers + ( + tag, + data, + new[] { peer }, + transportType, + sendToSelf + ); + } + + /// + public void SendDataToPeers + ( + uint tag, + byte[] data, + IEnumerable peers, + TransportType transportType, + bool sendToSelf = false + ) + { + if (data == null) + throw new ArgumentNullException(nameof(data)); + + _CheckThread(); + + if (_nativeHandle == IntPtr.Zero) + throw new ObjectDisposedException("Multipeer networking was destroyed!", (Exception)null); + + if (!IsConnected) + { + ARLog._Warn + ( + "ARDK: Cannot send data through a multipeer networking session " + + "that is not connected." + ); + + return; + } + + if (data.Length == 0) + { + ARLog._Warn("ARDK: Cannot send empty data array."); + return; + } + + var isUnreliableMessage = + transportType == TransportType.UnreliableOrdered || + transportType == TransportType.UnreliableUnordered; + + if (isUnreliableMessage) + { + if (data.Length > NetworkMessageSizeLimits.MaxUnreliableMessageSize) + { + ARLog._ErrorFormat + ( + "Attempting to send an unreliable message of {0} bytes, over the limit of {1} bytes", + data.Length, + NetworkMessageSizeLimits.MaxUnreliableMessageSize + ); + + return; + } + } + else + { + if (data.Length > NetworkMessageSizeLimits.MaxReliableMessageSize) + { + ARLog._ErrorFormat + ( + "Attempting to send a reliable message of {0} bytes, over the limit of {1} bytes", + data.Length, + NetworkMessageSizeLimits.MaxReliableMessageSize + ); + + return; + } + } + + if (peers == null) + throw new ArgumentNullException(nameof(peers)); + + var peerList = peers.ToList(); + + ARLog._DebugFormat + ( + "Sending {0} bytes with tag {1} to {2} peers", + true, + data.Length, + tag, + peerList.Count + ); + + var peerIdentifiers = new byte[peerList.Count * 16]; + for (var i = 0; i < peerList.Count; i++) + { + var peerGUID = peerList[i].Identifier.ToByteArray(); + + for (var j = 0; j < 16; j++) + peerIdentifiers[j + i * 16] = peerGUID[j]; + } + + _NARMultipeerNetworking_SendDataToPeers + ( + _nativeHandle, + tag, + data, + (ulong)data.Length, + peerIdentifiers, + (ulong)peerList.Count, + (byte)transportType + ); + + if (sendToSelf) + { + ARLog._DebugFormat + ( + "Sending {0} bytes with tag {1} to self", + true, + data.Length, + tag + ); + var handler = PeerDataReceived; + if (handler != null) + { + var args = new PeerDataReceivedArgs(Self, tag, transportType, data); + handler(args); + } + } + } + + /// + public void BroadcastData + ( + uint tag, + byte[] data, + TransportType transportType, + bool sendToSelf = false + ) + { + SendDataToPeers(tag, data, new List(), transportType, sendToSelf); + } + + public void StorePersistentKeyValue(string key, byte[] value) + { + if (string.IsNullOrEmpty(key)) + throw new ArgumentException("Cannot store a key-value with a null or empty key"); + + if (value == null) + throw new ArgumentNullException(nameof(value)); + + _CheckThread(); + + if (_nativeHandle == IntPtr.Zero) + throw new ObjectDisposedException("Multipeer networking was destroyed!", (Exception)null); + + if (key[0] == KeyValueKeyReservedPrefix) + { + ARLog._ErrorFormat + ( + "The prefix `!` for keys is reserved for the server, not storing for key: {0}", + key + ); + return; + } + + var sizeOfKey = Encoding.UTF8.GetByteCount(key); + if (sizeOfKey > NetworkMessageSizeLimits.MaxPersistentKeyValueKeySize) + { + ARLog._ErrorFormat + ( + "Attempting to set a persistent key value with key size {0}, over the limit of {1}", + sizeOfKey, + NetworkMessageSizeLimits.MaxPersistentKeyValueKeySize + ); + + return; + } + + if (value.Length > NetworkMessageSizeLimits.MaxPersistentKeyValueValueSize) + { + ARLog._ErrorFormat + ( + "Attempting to set a persistent key value with value size {0}, over the limit of {1}", + value.Length, + NetworkMessageSizeLimits.MaxPersistentKeyValueValueSize + ); + + return; + } + + ARLog._DebugFormat + ( + "Storing key: {0} with value of length: {1}", + false, + key, + value.Length + ); + + _NARMultipeerNetworking_StorePersistentKeyValue + ( + _nativeHandle, + key, + value, + (UInt64)value.Length + ); + } + + public void SendDataToArm(uint tag, byte[] data) + { + if (data == null) + throw new ArgumentNullException(nameof(data)); + + _CheckThread(); + + if (_nativeHandle == IntPtr.Zero) + throw new ArgumentException("Multipeer networking was destroyed!"); + + if (!IsConnected) + { + ARLog._Warn + ( + "ARDK: Cannot send data through a multipeer networking session " + + "that is not connected." + ); + + return; + } + + ARLog._DebugFormat + ( + "Sending message to Arm with tag: {0} and data of length: {1}", + true, + tag, + data.Length + ); + + _NARMultipeerNetworking_SendDataToARM + ( + _nativeHandle, + tag, + data, + (ulong)data.Length + ); + } + + /// + public override string ToString() + { + return string.Format("StageID: {0}", StageIdentifier); + } + + /// + public string ToString(int count) + { + return string.Format("StageID: {0}", StageIdentifier.ToString().Substring(0, count)); + } + + static _NativeMultipeerNetworking() + { + Platform.Init(); + } + + /// + /// Creates a multipeer networking client with a custom server configuration and a custom + /// StageIdentifier. + /// + internal _NativeMultipeerNetworking + ( + ServerConfiguration configuration, + Guid stageIdentifier + ) + { + ARLog._DebugFormat("Creating _NativeMultipeerNetworking with stageIdentifier: {0}", false, stageIdentifier); + _FriendTypeAsserter.AssertCallerIs(typeof(MultipeerNetworkingFactory)); + + _readOnlyPeers = _peers.Values.AsArdkReadOnly(); + + var arbeEndpoint = configuration.Endpoint; + + StageIdentifier = stageIdentifier; + +#pragma warning disable 0162 + // This is required to differentiate between unit testing (does not require the native platform) + // and Native in Editor + if (NativeAccess.Mode == NativeAccess.ModeType.Testing) + return; +#pragma warning restore 0162 + + // Only fill out the ClientMetadata if auth is not required. Otherwise, the server will handle it + if (!ServerConfiguration.AuthRequired && configuration.ClientMetadata == null) + configuration.GenerateRandomClientId(); + + if (!ServerConfiguration.AuthRequired) + { + ARLog._Debug("Attempting to create _NativeMultipeerNetworking without auth"); + + _nativeHandle = _NARMultipeerNetworking_Init + ( + stageIdentifier.ToByteArray(), + configuration.HeartbeatFrequency, + arbeEndpoint, + configuration.ClientMetadata, + (ulong)configuration.ClientMetadata.LongLength, + _applicationHandle, + _ConnectionDidFailWithErrorNative + ); + + ARLog._DebugFormat("Created _NativeMultipeerNetworking with handle: {0}", false, _nativeHandle); + } + else + { + var apiKeyCopy = ServerConfiguration.ApiKey; + var authUrlCopy = ServerConfiguration.AuthenticationUrl; + + var isMissingAuthComponents = + string.IsNullOrEmpty(apiKeyCopy) || string.IsNullOrEmpty(authUrlCopy); + + if (isMissingAuthComponents) + { + var authErrorMessage = + "Attempting to use networking without setting up your API key or Authentication URL. " + + "Set those up through the ARDKAuthRegistrar, or at runtime on ServerConfiguration " + + "before using networking!"; + + throw new Exception(authErrorMessage); + } + + ARLog._Debug("Attempting to create _NativeMultipeerNetworking with auth"); + _nativeHandle = _NARMultipeerNetworking_InitEx + ( + stageIdentifier.ToByteArray(), + configuration.HeartbeatFrequency, + arbeEndpoint, + configuration.ClientMetadata, + 0, + apiKeyCopy, + authUrlCopy, + _applicationHandle, + _ConnectionDidFailWithErrorNative + ); + ARLog._DebugFormat("Created _NativeMultipeerNetworking with handle: {0}", false, _nativeHandle); + } + + // We now subscribe to this callback in the _Init call above + _connectionDidFailWithErrorInitialized = true; + + // Inform the GC that this class is holding a large native object, so it gets cleaned up fast + // TODO(awang): Make an IReleasable interface that handles this for all native-related classes + GC.AddMemoryPressure(GCPressure); + + _nativeARMSenderHandle = _NARMultipeerNetworking_GetARMMessageSender(_nativeHandle); + + SubscribeToInternalCallbacks(); + } + + /// Constructor used by the _NativeARNetworking class since the networking is constructed in native + internal _NativeMultipeerNetworking(IntPtr nativeMultipeerNetworking) + { + _nativeHandle = nativeMultipeerNetworking; + _nativeARMSenderHandle = _NARMultipeerNetworking_GetARMMessageSender(_nativeHandle); + + Guid stageIdentifier; + _NARMultipeerNetworking_GetStageIdentifier(_nativeHandle, out stageIdentifier); + ARLog._Debug("Constructed a _NativeMultipeerNetworking belonging to a _NativeARNetworking"); + + // Inform the GC that this class is holding a large native object, so it gets cleaned up fast + // TODO(awang): Make an IReleasable interface that handles this for all native-related classes + GC.AddMemoryPressure(GCPressure); + + StageIdentifier = stageIdentifier; + + // We always subscribe to this callback in the _Init call in the other constructor. + // So this native object should also have the callback already set. + _connectionDidFailWithErrorInitialized = true; + SubscribeToInternalCallbacks(); + } + + ~_NativeMultipeerNetworking() + { + Dispose(false); + } + + /// + public void Dispose() + { + _CheckThread(); + + ARLog._Debug("Disposing _NativeMultipeerNetworking"); + GC.SuppressFinalize(this); + Dispose(true); + } + + private void Dispose(bool disposing) + { + if (disposing) + { + var handler = Deinitialized; + if (handler != null) + { + var args = new DeinitializedArgs(); + handler(args); + } + + _connectionFailed.Dispose(); + _clock = null; + } + + if (_nativeHandle != IntPtr.Zero) + { + _NARMultipeerNetworking_ReleaseARMMessageSender(_nativeARMSenderHandle); + _nativeARMSenderHandle = IntPtr.Zero; + _NARMultipeerNetworking_Release(_nativeHandle); + _nativeHandle = IntPtr.Zero; + + ARLog._Debug("Successfully released native multipeer object"); + } + + _cachedHandle.Free(); + + IsConnected = false; + IsDestroyed = true; + } + + private ArdkEventHandler _connected; + + /// + public event ArdkEventHandler Connected + { + add + { + _CheckThread(); + + _connected += value; + + if (IsConnected) + { + var args = new ConnectedArgs(Self, Host); + value(args); + } + } + remove { _connected -= value; } + } + + private ArdkEventHandler _persistentKeyValueUpdated; + + /// + public event ArdkEventHandler PersistentKeyValueUpdated + { + add + { + _CheckThread(); + + SubscribeToDidUpdatePersistentKeyValue(); + _persistentKeyValueUpdated += value; + } + remove { _persistentKeyValueUpdated -= value; } + } + + private readonly _CatchUpEvent _connectionFailed = + new _CatchUpEvent(); + + /// + public event ArdkEventHandler ConnectionFailed + { + add { _connectionFailed.Register(value); } + remove { _connectionFailed.Unregister(value); } + } + + /// + public event ArdkEventHandler Disconnected; + + /// + public event ArdkEventHandler PeerDataReceived; + + /// + public event ArdkEventHandler PeerAdded; + + /// + public event ArdkEventHandler PeerRemoved; + + /// + public event ArdkEventHandler Deinitialized; + + /// + public event ArdkEventHandler DataReceivedFromArm = (args) => {}; + + /// + public event ArdkEventHandler SessionStatusReceivedFromArm + { + add { _sessionStatusReceivedFromArm += value; } + remove { _sessionStatusReceivedFromArm -= value; } + } + + /// + public event ArdkEventHandler SessionResultReceivedFromArm + { + add { _sessionResultReceivedFromArm += value; } + remove { _sessionResultReceivedFromArm -= value; } + } + + // Below here are private fields and methods to handle native code and callbacks + + // The pointer to the C++ object handling functionality at the native level + private IntPtr _nativeHandle; + + // The pointer to the C++ object for sending ARM messages. + private IntPtr _nativeARMSenderHandle; + + internal IntPtr GetNativeHandle() + { + return _nativeHandle; + } + + private IntPtr _cachedHandleIntPtr = IntPtr.Zero; + private SafeGCHandle<_NativeMultipeerNetworking> _cachedHandle; + + // Approx memory size of native object + // Magic number for 10MB, from profiling an iPhone 8 + private const long GCPressure = 10L * 1024L * 1024L; + + // Used to round-trip a pointer through c++, + // so that we can keep our this pointer even in c# functions + // marshaled and called by native code + private IntPtr _applicationHandle + { + get + { + if (_cachedHandleIntPtr != IntPtr.Zero) + return _cachedHandleIntPtr; + + lock (this) + { + if (_cachedHandleIntPtr != IntPtr.Zero) + return _cachedHandleIntPtr; + + // https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.gchandle.tointptr.aspx + _cachedHandle = SafeGCHandle.Alloc(this); + _cachedHandleIntPtr = _cachedHandle.ToIntPtr(); + } + + return _cachedHandleIntPtr; + } + } + + RuntimeEnvironment IMultipeerNetworking.RuntimeEnvironment + { + get { return RuntimeEnvironment.LiveDevice; } + } + +#region CallbackImplementation + private bool _didConnectInitialized; + private bool _connectionDidFailWithErrorInitialized; + private bool _didReceiveDataFromPeerInitialized; + private bool _didAddPeerInitialized; + private bool _didRemovePeerInitialized; + private bool _didUpdatePersistentKeyValueInitialized; + private bool _armCallbacksInitialized; + +#region InternalSubscriptions + /// + /// These callbacks are subscribed to at initialization as they set the data that will be provided + /// by accessors (Self, Host, Peers, etc) + /// + private void SubscribeToInternalCallbacks() + { + SubscribeToDidConnect(); + SubscribeToDidAddPeer(); + SubscribeToDidRemovePeer(); + SubscribeToConnectionDidFailWithError(); + SubscribeToDidReceiveDataFromPeer(); + SubscribeToArmCallbacks(); + } + + internal void SubscribeToDidConnect() + { + if (_didConnectInitialized) + return; + + lock (this) + { + if (_didConnectInitialized) + return; + + _NARMultipeerNetworking_Set_didConnectCallback + ( + _applicationHandle, + _nativeHandle, + _didConnectNative + ); + + _didConnectInitialized = true; + } + } + + internal void SubscribeToConnectionDidFailWithError() + { + if (_connectionDidFailWithErrorInitialized) + return; + + lock (this) + { + if (_connectionDidFailWithErrorInitialized) + return; + + _NARMultipeerNetworking_Set_connectionDidFailWithErrorCallback + ( + _applicationHandle, + _nativeHandle, + _ConnectionDidFailWithErrorNative + ); + + _connectionDidFailWithErrorInitialized = true; + } + } + + internal void SubscribeToDidReceiveDataFromPeer() + { + if (_didReceiveDataFromPeerInitialized) + return; + + lock (this) + { + if (_didReceiveDataFromPeerInitialized) + return; + + _NARMultipeerNetworking_Set_didReceiveDataFromPeerCallback + ( + _applicationHandle, + _nativeHandle, + _didReceiveDataFromPeerNative + ); + + _didReceiveDataFromPeerInitialized = true; + } + } + + internal void SubscribeToDidAddPeer() + { + if (_didAddPeerInitialized) + return; + + lock (this) + { + if (_didAddPeerInitialized) + return; + + _NARMultipeerNetworking_Set_didAddPeerCallback + ( + _applicationHandle, + _nativeHandle, + _didAddPeerNative + ); + + _didAddPeerInitialized = true; + } + } + + internal void SubscribeToDidRemovePeer() + { + if (_didRemovePeerInitialized) + return; + + lock (this) + { + if (_didRemovePeerInitialized) + return; + + _NARMultipeerNetworking_Set_didRemovePeerCallback + ( + _applicationHandle, + _nativeHandle, + _didRemovePeerNative + ); + + _didRemovePeerInitialized = true; + } + } + + internal void SubscribeToDidUpdatePersistentKeyValue() + { + if (_didUpdatePersistentKeyValueInitialized) + return; + + lock (this) + { + if (_didUpdatePersistentKeyValueInitialized) + return; + + _NARMultipeerNetworking_Set_didUpdatePersistentKeyValueCallback + ( + _applicationHandle, + _nativeHandle, + _didUpdatePersistentKeyValueNative + ); + + _didUpdatePersistentKeyValueInitialized = true; + } + } + + internal void SubscribeToArmCallbacks() + { + if (_armCallbacksInitialized) + return; + + lock (this) + { + if (_armCallbacksInitialized) + return; + + _NARMultipeerNetworking_Set_didReceiveDataFromARMCallback + ( + _applicationHandle, + _nativeHandle, + _didReceiveDataFromArmNative + ); + + _NARMultipeerNetworking_Set_didReceiveARMSessionStatusCallback + ( + _applicationHandle, + _nativeHandle, + _didReceiveSessionStatusFromArmNative + ); + + _NARMultipeerNetworking_Set_didReceiveARMSessionResultCallback + ( + _applicationHandle, + _nativeHandle, + _didReceiveSessionResultFromArmNative + ); + + _armCallbacksInitialized = true; + } + } +#endregion +#endregion + +#region InternalCallbacks + private event ArdkEventHandler _sessionStatusReceivedFromArm = + (args) => {}; + + private event ArdkEventHandler _sessionResultReceivedFromArm = + (args) => {}; + + [MonoPInvokeCallback(typeof(_NARMultipeerNetworking_Did_Connect_Callback))] + private static void _didConnectNative + ( + IntPtr context, + IntPtr rawSelf, + IntPtr rawHost, + UInt32 isHost + ) + { + ARLog._Debug("Invoked _didConnectNative"); + var session = SafeGCHandle.TryGetInstance<_NativeMultipeerNetworking>(context); + + if (session == null || session.IsDestroyed) + { + ARLog._Warn("_didConnectNative called after C# object was already destroyed."); + + _Peer._ReleasePeer(rawSelf); + _Peer._ReleasePeer(rawHost); + + return; + } + + _CallbackQueue.QueueCallback + ( + () => + { + if (session.IsDestroyed) + { + ARLog._Warn("Queued _didConnectNative called after C# object was already destroyed."); + + _Peer._ReleasePeer(rawSelf); + _Peer._ReleasePeer(rawHost); + + return; + } + + var self = _Peer.FromNativeHandle(rawSelf); + var host = _Peer.FromNativeHandle(rawHost); + + session.IsConnected = true; + session.Self = self; + session.Host = host; + + var handler = session._connected; + if (handler != null) + { + ARLog._Debug("Surfacing Connected event"); + var args = new ConnectedArgs(self, host); + handler(args); + } + } + ); + } + + [MonoPInvokeCallback(typeof(_NARMultipeerNetworking_Connection_Did_Fail_With_Error_Callback))] + private static void _ConnectionDidFailWithErrorNative(IntPtr context, UInt32 errorCode) + { + ARLog._Debug("Invoked _ConnectionDidFailWithErrorNative"); + var instance = SafeGCHandle.TryGetInstance<_NativeMultipeerNetworking>(context); + if (instance == null || instance.IsDestroyed) + return; + + ARLog._WarnFormat("Failed with err code {0}",false, errorCode); + + var args = new ConnectionFailedArgs(errorCode); + instance._connectionFailed.InvokeUsingCallbackQueue(args); + } + + [MonoPInvokeCallback(typeof(_NARMultipeerNetworking_Did_Receive_Data_From_Peer_Callback))] + private static void _didReceiveDataFromPeerNative + ( + IntPtr context, + UInt32 tag, + IntPtr rawData, + UInt64 rawDataSize, + IntPtr rawPeer, + byte transportType + ) + { + ARLog._Debug("Invoked _didReceiveDataFromPeerNative", true); + var instance = SafeGCHandle.TryGetInstance<_NativeMultipeerNetworking>(context); + + if (instance == null || instance.IsDestroyed) + { + ARLog._Warn("Queued _didReceiveDataFromPeerNative called after C# instance was destroyed."); + _Peer._ReleasePeer(rawPeer); + return; + } + + var data = new byte[rawDataSize]; + Marshal.Copy(rawData, data, 0, (int)rawDataSize); + + _CallbackQueue.QueueCallback + ( + () => + { + if (instance.IsDestroyed) + { + var msg = "Queued _didReceiveDataFromPeerNative called after C# instance was destroyed."; + ARLog._Warn(msg); + + _Peer._ReleasePeer(rawPeer); + return; + } + + var peer = _Peer.FromNativeHandle(rawPeer); + + var dataInfo = + new DataInfo + { + tag = tag, peer = peer, transportType = (TransportType)transportType + }; + + var handler = instance.PeerDataReceived; + if (handler != null) + { + ARLog._Debug("Surfacing PeerDataReceived event"); + var args = new PeerDataReceivedArgs(peer, tag, dataInfo.transportType, data); + handler(args); + } + } + ); + } + + [MonoPInvokeCallback(typeof(_NARMultipeerNetworking_Did_Add_Or_Remove_Peer_Callback))] + private static void _didAddPeerNative(IntPtr context, IntPtr rawPeer) + { + ARLog._Debug("Invoked _didAddPeerNative"); + + var instance = SafeGCHandle.TryGetInstance<_NativeMultipeerNetworking>(context); + if (instance == null || instance.IsDestroyed) + { + ARLog._Warn("_didAddPeerNative invoked after C# instance was destroyed."); + _Peer._ReleasePeer(rawPeer); + return; + } + + _CallbackQueue.QueueCallback + ( + () => + { + if (instance.IsDestroyed) + { + ARLog._Warn("Queued _didAddPeerNative invoked after C# instance was destroyed."); + _Peer._ReleasePeer(rawPeer); + return; + } + + var peer = _Peer.FromNativeHandle(rawPeer); + instance._peers[peer.Identifier] = peer; + + var handler = instance.PeerAdded; + if (handler != null) + { + ARLog._Debug("Surfacing PeerAdded event"); + var args = new PeerAddedArgs(peer); + handler(args); + } + } + ); + } + + [MonoPInvokeCallback(typeof(_NARMultipeerNetworking_Did_Add_Or_Remove_Peer_Callback))] + private static void _didRemovePeerNative(IntPtr context, IntPtr peerIDPtr) + { + ARLog._Debug("Invoked _didRemovePeerNative"); + + var instance = SafeGCHandle.TryGetInstance<_NativeMultipeerNetworking>(context); + if (instance == null || instance.IsDestroyed) + { + ARLog._Warn("_didRemovePeerNative invoked after C# instance was destroyed."); + _Peer._ReleasePeer(peerIDPtr); + return; + } + + _CallbackQueue.QueueCallback + ( + () => + { + if (instance.IsDestroyed) + { + ARLog._Warn("Queued _didRemovePeerNative invoked after C# instance was destroyed."); + _Peer._ReleasePeer(peerIDPtr); + return; + } + + var peer = _Peer.FromNativeHandle(peerIDPtr); + + // If a peer-left message containing Self.Identifier has been received, you have been dropped + // from the session. In that case, clear the peers list. + if (peer.Identifier == instance.Self.Identifier) + instance._peers.Clear(); + else + { + // It is not guaranteed that the peerIDPtr surfaced is equivalent to the cached value for + // that peer, iterate through all of the cached peers and remove the peer by identifier + var query = instance._peers.Where(kvp => kvp.Value.Identifier == peer.Identifier); + + foreach (var cachedPeer in query.ToList()) + instance._peers.Remove(cachedPeer.Key); + } + + var handler = instance.PeerRemoved; + if (handler != null) + { + ARLog._Debug("Surfacing PeerRemoved event"); + var args = new PeerRemovedArgs(peer); + handler(args); + } + } + ); + } + + [MonoPInvokeCallback(typeof(_NARMultipeerNetworking_Did_Update_Persistent_KeyValue_Callback))] + private static void _didUpdatePersistentKeyValueNative + ( + IntPtr context, + string key, + IntPtr value, + UInt64 valueSize + ) + { + ARLog._Debug("Invoked _didUpdatePersistentKeyValueNative"); + var session = SafeGCHandle.TryGetInstance<_NativeMultipeerNetworking>(context); + + if (session == null || session.IsDestroyed) + { + ARLog._Warn("_didUpdatePersistentKeyValueNative invoked after C# object was destroyed."); + return; + } + + var data = new byte[valueSize]; + Marshal.Copy(value, data, 0, (int)valueSize); + + _CallbackQueue.QueueCallback + ( + () => + { + if (session.IsDestroyed) + { + ARLog._Warn("_didUpdatePersistentKeyValueNative invoked after C# object was destroyed."); + } + + var handler = session._persistentKeyValueUpdated; + if (handler != null) + { + ARLog._Debug("Surfacing PersistentKeyValueUpdated event"); + var args = new PersistentKeyValueUpdatedArgs(key, data); + handler(args); + } + } + ); + } + + [MonoPInvokeCallback(typeof(_NARMultipeerNetworking_Did_Receive_Data_From_ARM_Callback))] + private static void _didReceiveDataFromArmNative + ( + IntPtr context, + UInt32 tag, + IntPtr rawData, + UInt64 rawDataSize + ) + { + ARLog._Debug("Invoked _didReceiveDataFromArmNative"); + var session = SafeGCHandle.TryGetInstance<_NativeMultipeerNetworking>(context); + + if (session == null || session.IsDestroyed) + { + ARLog._Warn("_didReceiveDataFromArmNative invoked after C# object was destroyed."); + return; + } + + var data = new byte[rawDataSize]; + Marshal.Copy(rawData, data, 0, (int)rawDataSize); + + _CallbackQueue.QueueCallback + ( + () => + { + if (session.IsDestroyed) + { + ARLog._Warn("_didReceiveDataFromArmNative invoked after C# object was destroyed."); + } + + ARLog._Debug("Surfacing DataReceivedFromArm event"); + var args = new DataReceivedFromArmArgs(tag, data); + session.DataReceivedFromArm(args); + } + ); + } + + [MonoPInvokeCallback + (typeof(_NARMultipeerNetworking_Did_Receive_Session_Status_From_ARM_Callback))] + private static void _didReceiveSessionStatusFromArmNative + ( + IntPtr context, + UInt32 status + ) + { + ARLog._Debug("Invoked _didReceiveSessionStatusFromArmNative"); + var session = SafeGCHandle.TryGetInstance<_NativeMultipeerNetworking>(context); + + if (session == null || session.IsDestroyed) + { + ARLog._Warn("_didReceiveSessionStatusFromArmNative invoked after C# object was destroyed."); + return; + } + + _CallbackQueue.QueueCallback + ( + () => + { + if (session.IsDestroyed) + { + ARLog._Warn("_didReceiveSessionStatusFromArmNative invoked after C# object was destroyed."); + } + + ARLog._Debug("Surfacing SessionStatusReceivedFromArmArgs event"); + var args = new SessionStatusReceivedFromArmArgs(status); + session._sessionStatusReceivedFromArm(args); + } + ); + } + + [MonoPInvokeCallback + (typeof(_NARMultipeerNetworking_Did_Receive_Session_Result_From_ARM_Callback))] + private static void _didReceiveSessionResultFromArmNative + ( + IntPtr context, + UInt32 outcome, + IntPtr rawDetails, + UInt64 rawDetailsSize + ) + { + ARLog._Debug("Invoked _didReceiveSessionResultFromArmNative"); + var session = SafeGCHandle.TryGetInstance<_NativeMultipeerNetworking>(context); + + if (session == null || session.IsDestroyed) + { + ARLog._Warn("_didReceiveSessionStatusFromArmNative invoked after C# object was destroyed."); + return; + } + + byte[] data; + + if (rawDetailsSize == 0 || rawDetails == IntPtr.Zero) + { + data = EmptyArray.Instance; + } + else + { + data = new byte[rawDetailsSize]; + Marshal.Copy(rawDetails, data, 0, (int)rawDetailsSize); + } + + + _CallbackQueue.QueueCallback + ( + () => + { + if (session.IsDestroyed) + { + ARLog._Warn("_didReceiveSessionStatusFromArmNative invoked after C# object was destroyed."); + } + + ARLog._Debug("Surfacing SessionResultReceivedFromArmArgs event"); + var args = new SessionResultReceivedFromArmArgs(outcome, data); + session._sessionResultReceivedFromArm(args); + } + ); + } +#endregion + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NARMultipeerNetworking_Init + ( + byte[] stageIdentifier, + int heartbeatFrequencyMillis, + string tcpServerAddress, + byte[] clientMetadata, + UInt64 clientMetadataSize, + IntPtr context, + _NARMultipeerNetworking_Connection_Did_Fail_With_Error_Callback cb + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NARMultipeerNetworking_InitEx + ( + byte[] stageIdentifier, + int heartbeatFrequencyMillis, + string tcpServerAddress, + byte[] clientMetadata, + UInt64 clientMetadataSize, + string apiKey, + string authenticationUrl, + IntPtr context, + _NARMultipeerNetworking_Connection_Did_Fail_With_Error_Callback cb + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARMultipeerNetworking_Release(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARMultipeerNetworking_GetStageIdentifier + ( + IntPtr nativeHandle, + out Guid outIdentifier + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARMultipeerNetworking_Join + ( + IntPtr nativeHandle, + byte[] sessionMetadata, + UInt64 sessionMetadataSize + ); + + // TODO: Why does leave take the metadata again? + // Can we join multiple sessions? Why can't it just leave the one it's in? + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARMultipeerNetworking_Leave + ( + IntPtr nativeHandle, + byte[] sessionMetadata, + UInt64 sessionMetadataSize + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARMultipeerNetworking_SendDataToPeers + ( + IntPtr nativeHandle, + UInt32 tag, + byte[] data, + UInt64 dataSize, + byte[] peerIdentifiers, + UInt64 peerIdentifiersSize, + byte transportType + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARMultipeerNetworking_StorePersistentKeyValue + ( + IntPtr nativeHandle, + string key, + byte[] data, + UInt64 dataSize + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NARMultipeerNetworking_GetARMMessageSender(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARMultipeerNetworking_ReleaseARMMessageSender + ( + IntPtr armSenderNativeHandle + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARMultipeerNetworking_SendDataToARM + ( + IntPtr nativeHandle, + UInt32 tag, + byte[] data, + UInt64 dataSize + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARMultipeerNetworking_Set_didConnectCallback + ( + IntPtr context, + IntPtr nativeHandle, + _NARMultipeerNetworking_Did_Connect_Callback cb + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARMultipeerNetworking_Set_connectionDidFailWithErrorCallback + ( + IntPtr context, + IntPtr nativeHandle, + _NARMultipeerNetworking_Connection_Did_Fail_With_Error_Callback cb + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARMultipeerNetworking_Set_didReceiveDataFromPeerCallback + ( + IntPtr context, + IntPtr nativeHandle, + _NARMultipeerNetworking_Did_Receive_Data_From_Peer_Callback cb + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARMultipeerNetworking_Set_didAddPeerCallback + ( + IntPtr context, + IntPtr nativeHandle, + _NARMultipeerNetworking_Did_Add_Or_Remove_Peer_Callback cb + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARMultipeerNetworking_Set_didRemovePeerCallback + ( + IntPtr context, + IntPtr nativeHandle, + _NARMultipeerNetworking_Did_Add_Or_Remove_Peer_Callback cb + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARMultipeerNetworking_Set_didUpdatePersistentKeyValueCallback + ( + IntPtr context, + IntPtr nativeHandle, + _NARMultipeerNetworking_Did_Update_Persistent_KeyValue_Callback cb + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARMultipeerNetworking_Set_didReceiveDataFromARMCallback + ( + IntPtr context, + IntPtr nativeHandle, + _NARMultipeerNetworking_Did_Receive_Data_From_ARM_Callback cb + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARMultipeerNetworking_Set_didReceiveARMSessionStatusCallback + ( + IntPtr context, + IntPtr nativeHandle, + _NARMultipeerNetworking_Did_Receive_Session_Status_From_ARM_Callback cb + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARMultipeerNetworking_Set_didReceiveARMSessionResultCallback + ( + IntPtr context, + IntPtr nativeHandle, + _NARMultipeerNetworking_Did_Receive_Session_Result_From_ARM_Callback cb + ); + + private delegate void _NARMultipeerNetworking_Did_Connect_Callback + ( + IntPtr context, + IntPtr peer, + IntPtr host, + UInt32 isHost + ); + + private delegate void _NARMultipeerNetworking_Connection_Did_Fail_With_Error_Callback + ( + IntPtr context, + UInt32 errCode + ); + + private delegate void _NARMultipeerNetworking_Did_Receive_Data_From_Peer_Callback + ( + IntPtr context, + UInt32 tag, + IntPtr rawData, + UInt64 rawDataSize, + IntPtr peerInfo, + byte transportType + ); + + private delegate void _NARMultipeerNetworking_Did_Add_Or_Remove_Peer_Callback + ( + IntPtr context, + IntPtr peerIDPtr + ); + + private delegate void _NARMultipeerNetworking_Did_Update_Persistent_KeyValue_Callback + ( + IntPtr context, + string key, + IntPtr value, + UInt64 valueSize + ); + + private delegate void _NARMultipeerNetworking_Did_Receive_Data_From_ARM_Callback + ( + IntPtr context, + UInt32 tag, + IntPtr rawData, + UInt64 rawDataSize + ); + + private delegate void _NARMultipeerNetworking_Did_Receive_Session_Status_From_ARM_Callback + ( + IntPtr context, + UInt32 status + ); + + private delegate void _NARMultipeerNetworking_Did_Receive_Session_Result_From_ARM_Callback + ( + IntPtr context, + UInt32 outcome, + IntPtr rawDetails, + UInt64 rawDetailsSize + ); + } +} diff --git a/Assets/ARDK/Networking/_NativeMultipeerNetworking.cs.meta b/Assets/ARDK/Networking/_NativeMultipeerNetworking.cs.meta new file mode 100644 index 0000000..34e3884 --- /dev/null +++ b/Assets/ARDK/Networking/_NativeMultipeerNetworking.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c6ecaa12ba894a52922fa5a6a43211b1 +timeCreated: 1540321736 \ No newline at end of file diff --git a/Assets/ARDK/Networking/_Peer.cs b/Assets/ARDK/Networking/_Peer.cs new file mode 100644 index 0000000..d05b431 --- /dev/null +++ b/Assets/ARDK/Networking/_Peer.cs @@ -0,0 +1,113 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Runtime.InteropServices; + +using Niantic.ARDK.AR; +using Niantic.ARDK.Internals; +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.Networking +{ + /// + /// Represents a single peer/user in a networking session. + /// Each peer is identified by a GUID + /// + internal class _Peer: + IPeer + { + private static readonly _WeakValueDictionary _allPeers = + new _WeakValueDictionary(); + + private static readonly Func _createNativePeer = + (identifier) => new _Peer(identifier); + + internal static _Peer FromIdentifier(Guid identifier) + { + return _allPeers.GetOrAdd(identifier, _createNativePeer); + } + + internal static _Peer FromNativeHandle(IntPtr nativeHandle) + { + if (nativeHandle == IntPtr.Zero) + throw new ArgumentException("Must not be zero!", nameof(nativeHandle)); + + Guid identifier; + _NARPeerInfo_GetIdentifier(nativeHandle, out identifier); + _NARPeerInfo_Release(nativeHandle); + + return FromIdentifier(identifier); + } + + /// + public Guid Identifier { get; private set; } + + protected _Peer(Guid identifier) + { + Identifier = identifier; + } + + /// + /// Directly release a native peer without creating an object. + /// + internal static void _ReleasePeer(IntPtr rawPeer) + { + // Do not call into native if this is run during testing +#pragma warning disable CS0162 + if (NativeAccess.Mode == NativeAccess.ModeType.Testing) + return; +#pragma warning restore CS0162 + + _NARPeerInfo_Release(rawPeer); + } + + /// + /// Compares if a peer is equal to this through GUID + /// @param info Peer to compare against + /// + public bool Equals(IPeer info) + { + return info != null && Identifier.Equals(info.Identifier); + } + + /// + /// Compares an object to this through GUID + /// @param obj Some object to compare against + /// + public override bool Equals(object obj) + { + return Equals(obj as IPeer); + } + + /// + /// Returns the hashcode for this instance + /// + public override int GetHashCode() + { + return Identifier.GetHashCode(); + } + + public override string ToString() + { + return string.Format("Peer: {0}", Identifier); + } + + /// + /// ToString implementation that limits the guid length to a supplied number, for easy printing + /// + public string ToString(int count) + { + return string.Format("Peer: {0}", Identifier.ToString().Substring(0, count)); + } + + // Private pointers and callbacks to handle native code + + private IntPtr _nativeHandle = IntPtr.Zero; + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARPeerInfo_GetIdentifier(IntPtr nativeHandle, out Guid identifier); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARPeerInfo_Release(IntPtr nativeHandle); + } +} diff --git a/Assets/ARDK/Networking/_Peer.cs.meta b/Assets/ARDK/Networking/_Peer.cs.meta new file mode 100644 index 0000000..347b5ce --- /dev/null +++ b/Assets/ARDK/Networking/_Peer.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: bbf573a8642c44198a9323d45b42f621 +timeCreated: 1537211766 +licenseType: Pro +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins.meta b/Assets/ARDK/Plugins.meta new file mode 100644 index 0000000..090795a --- /dev/null +++ b/Assets/ARDK/Plugins.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e4075fe7c71c2449bb274fb85a2cda11 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/Niantic.Protobufs.meta b/Assets/ARDK/Plugins/Niantic.Protobufs.meta new file mode 100644 index 0000000..69cdb66 --- /dev/null +++ b/Assets/ARDK/Plugins/Niantic.Protobufs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f0036f4bc892841ff8e8cb523dafe3fd +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/Niantic.Protobufs/Google.Protobuf.3.19.4.meta b/Assets/ARDK/Plugins/Niantic.Protobufs/Google.Protobuf.3.19.4.meta new file mode 100644 index 0000000..e56f4c7 --- /dev/null +++ b/Assets/ARDK/Plugins/Niantic.Protobufs/Google.Protobuf.3.19.4.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 42891d82f9aec4b99b7ff3c193808734 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/Niantic.Protobufs/Google.Protobuf.3.19.4/net45.meta b/Assets/ARDK/Plugins/Niantic.Protobufs/Google.Protobuf.3.19.4/net45.meta new file mode 100644 index 0000000..d2e7c21 --- /dev/null +++ b/Assets/ARDK/Plugins/Niantic.Protobufs/Google.Protobuf.3.19.4/net45.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 38c14bf240c814cc5b74db85de762a55 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/Niantic.Protobufs/Google.Protobuf.3.19.4/net45/Niantic.Google.Protobuf.dll b/Assets/ARDK/Plugins/Niantic.Protobufs/Google.Protobuf.3.19.4/net45/Niantic.Google.Protobuf.dll new file mode 100644 index 0000000..c597569 Binary files /dev/null and b/Assets/ARDK/Plugins/Niantic.Protobufs/Google.Protobuf.3.19.4/net45/Niantic.Google.Protobuf.dll differ diff --git a/Assets/ARDK/Plugins/Niantic.Protobufs/Google.Protobuf.3.19.4/net45/Niantic.Google.Protobuf.dll.meta b/Assets/ARDK/Plugins/Niantic.Protobufs/Google.Protobuf.3.19.4/net45/Niantic.Google.Protobuf.dll.meta new file mode 100644 index 0000000..bbf3f2a --- /dev/null +++ b/Assets/ARDK/Plugins/Niantic.Protobufs/Google.Protobuf.3.19.4/net45/Niantic.Google.Protobuf.dll.meta @@ -0,0 +1,86 @@ +fileFormatVersion: 2 +guid: 94d509ca4f794415abadc3a9ad2e5c1c +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 1 + validateReferences: 1 + platformData: + - first: + : Any + second: + enabled: 0 + settings: + Exclude Android: 0 + Exclude Editor: 0 + Exclude Linux64: 0 + Exclude OSXUniversal: 0 + Exclude Win: 0 + Exclude Win64: 0 + Exclude iOS: 0 + - first: + Android: Android + second: + enabled: 1 + settings: + CPU: ARMv7 + - first: + Any: + second: + enabled: 1 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Standalone: Linux64 + second: + enabled: 1 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 1 + settings: + CPU: None + - first: + Standalone: Win + second: + enabled: 1 + settings: + CPU: x86 + - first: + Standalone: Win64 + second: + enabled: 1 + settings: + CPU: x86_64 + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + CPU: AnyCPU + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/Niantic.Protobufs/Google.Protobuf.3.19.4/net45/Niantic.Google.Protobuf.xml b/Assets/ARDK/Plugins/Niantic.Protobufs/Google.Protobuf.3.19.4/net45/Niantic.Google.Protobuf.xml new file mode 100644 index 0000000..2be3c2c --- /dev/null +++ b/Assets/ARDK/Plugins/Niantic.Protobufs/Google.Protobuf.3.19.4/net45/Niantic.Google.Protobuf.xml @@ -0,0 +1,10141 @@ + + + + Google.Protobuf + + + + + Provides a utility routine to copy small arrays much more quickly than Buffer.BlockCopy + + + + + The threshold above which you should use Buffer.BlockCopy rather than ByteArray.Copy + + + + + Determines which copy routine to use based on the number of bytes to be copied. + + + + + Reverses the order of bytes in the array + + + + + Immutable array of bytes. + + + + + Internal use only. Ensure that the provided memory is not mutated and belongs to this instance. + + + + + Internal use only. Ensure that the provided memory is not mutated and belongs to this instance. + This method encapsulates converting array to memory. Reduces need for SecuritySafeCritical + in .NET Framework. + + + + + Constructs a new ByteString from the given memory. The memory is + *not* copied, and must not be modified after this constructor is called. + + + + + Returns an empty ByteString. + + + + + Returns the length of this ByteString in bytes. + + + + + Returns true if this byte string is empty, false otherwise. + + + + + Provides read-only access to the data of this . + No data is copied so this is the most efficient way of accessing. + + + + + Provides read-only access to the data of this . + No data is copied so this is the most efficient way of accessing. + + + + + Converts this into a byte array. + + The data is copied - changes to the returned array will not be reflected in this ByteString. + A byte array with the same data as this ByteString. + + + + Converts this into a standard base64 representation. + + A base64 representation of this ByteString. + + + + Constructs a from the Base64 Encoded String. + + + + + Constructs a from data in the given stream, synchronously. + + If successful, will be read completely, from the position + at the start of the call. + The stream to copy into a ByteString. + A ByteString with content read from the given stream. + + + + Constructs a from data in the given stream, asynchronously. + + If successful, will be read completely, from the position + at the start of the call. + The stream to copy into a ByteString. + The cancellation token to use when reading from the stream, if any. + A ByteString with content read from the given stream. + + + + Constructs a from the given array. The contents + are copied, so further modifications to the array will not + be reflected in the returned ByteString. + This method can also be invoked in ByteString.CopyFrom(0xaa, 0xbb, ...) form + which is primarily useful for testing. + + + + + Constructs a from a portion of a byte array. + + + + + Constructs a from a read only span. The contents + are copied, so further modifications to the span will not + be reflected in the returned . + + + + + Creates a new by encoding the specified text with + the given encoding. + + + + + Creates a new by encoding the specified text in UTF-8. + + + + + Returns the byte at the given index. + + + + + Converts this into a string by applying the given encoding. + + + This method should only be used to convert binary data which was the result of encoding + text with the given encoding. + + The encoding to use to decode the binary data into text. + The result of decoding the binary data with the given decoding. + + + + Converts this into a string by applying the UTF-8 encoding. + + + This method should only be used to convert binary data which was the result of encoding + text with UTF-8. + + The result of decoding the binary data with the given decoding. + + + + Returns an iterator over the bytes in this . + + An iterator over the bytes in this object. + + + + Returns an iterator over the bytes in this . + + An iterator over the bytes in this object. + + + + Creates a CodedInputStream from this ByteString's data. + + + + + Compares two byte strings for equality. + + The first byte string to compare. + The second byte string to compare. + true if the byte strings are equal; false otherwise. + + + + Compares two byte strings for inequality. + + The first byte string to compare. + The second byte string to compare. + false if the byte strings are equal; true otherwise. + + + + Compares this byte string with another object. + + The object to compare this with. + true if refers to an equal ; false otherwise. + + + + Returns a hash code for this object. Two equal byte strings + will return the same hash code. + + A hash code for this object. + + + + Compares this byte string with another. + + The to compare this with. + true if refers to an equal byte string; false otherwise. + + + + Copies the entire byte array to the destination array provided at the offset specified. + + + + + Writes the entire byte array to the provided stream + + + + + SecuritySafeCritical attribute can not be placed on types with async methods. + This class has ByteString's async methods so it can be marked with SecuritySafeCritical. + + + + + Reads and decodes protocol message fields. + + + + This class is generally used by generated code to read appropriate + primitives from the stream. It effectively encapsulates the lowest + levels of protocol buffer format. + + + Repeated fields and map fields are not handled by this class; use + and to serialize such fields. + + + + + + Whether to leave the underlying stream open when disposing of this stream. + This is always true when there's no stream. + + + + + Buffer of data read from the stream or provided at construction time. + + + + + The stream to read further input from, or null if the byte array buffer was provided + directly on construction, with no further data available. + + + + + The parser state is kept separately so that other parse implementations can reuse the same + parsing primitives. + + + + + Creates a new CodedInputStream reading data from the given byte array. + + + + + Creates a new that reads from the given byte array slice. + + + + + Creates a new reading data from the given stream, which will be disposed + when the returned object is disposed. + + The stream to read from. + + + + Creates a new reading data from the given stream. + + The stream to read from. + true to leave open when the returned + is disposed; false to dispose of the given stream when the + returned object is disposed. + + + + Creates a new CodedInputStream reading data from the given + stream and buffer, using the default limits. + + + + + Creates a new CodedInputStream reading data from the given + stream and buffer, using the specified limits. + + + This chains to the version with the default limits instead of vice versa to avoid + having to check that the default values are valid every time. + + + + + Creates a with the specified size and recursion limits, reading + from an input stream. + + + This method exists separately from the constructor to reduce the number of constructor overloads. + It is likely to be used considerably less frequently than the constructors, as the default limits + are suitable for most use cases. + + The input stream to read from + The total limit of data to read from the stream. + The maximum recursion depth to allow while reading. + A CodedInputStream reading from with the specified size + and recursion limits. + + + + Returns the current position in the input stream, or the position in the input buffer + + + + + Returns the last tag read, or 0 if no tags have been read or we've read beyond + the end of the stream. + + + + + Returns the size limit for this stream. + + + This limit is applied when reading from the underlying stream, as a sanity check. It is + not applied when reading from a byte array data source without an underlying stream. + The default value is Int32.MaxValue. + + + The size limit. + + + + + Returns the recursion limit for this stream. This limit is applied whilst reading messages, + to avoid maliciously-recursive data. + + + The default limit is 100. + + + The recursion limit for this stream. + + + + + Internal-only property; when set to true, unknown fields will be discarded while parsing. + + + + + Internal-only property; provides extension identifiers to compatible messages while parsing. + + + + + Disposes of this instance, potentially closing any underlying stream. + + + As there is no flushing to perform here, disposing of a which + was constructed with the leaveOpen option parameter set to true (or one which + was constructed to read from a byte array) has no effect. + + + + + Verifies that the last call to ReadTag() returned tag 0 - in other words, + we've reached the end of the stream when we expected to. + + The + tag read was not the one specified + + + + Peeks at the next field tag. This is like calling , but the + tag is not consumed. (So a subsequent call to will return the + same value.) + + + + + Reads a field tag, returning the tag of 0 for "end of stream". + + + If this method returns 0, it doesn't necessarily mean the end of all + the data in this CodedInputStream; it may be the end of the logical stream + for an embedded message, for example. + + The next field tag, or 0 for end of stream. (0 is never a valid tag.) + + + + Skips the data for the field with the tag we've just read. + This should be called directly after , when + the caller wishes to skip an unknown field. + + + This method throws if the last-read tag was an end-group tag. + If a caller wishes to skip a group, they should skip the whole group, by calling this method after reading the + start-group tag. This behavior allows callers to call this method on any field they don't understand, correctly + resulting in an error if an end-group tag has not been paired with an earlier start-group tag. + + The last tag was an end-group tag + The last read operation read to the end of the logical stream + + + + Skip a group. + + + + + Reads a double field from the stream. + + + + + Reads a float field from the stream. + + + + + Reads a uint64 field from the stream. + + + + + Reads an int64 field from the stream. + + + + + Reads an int32 field from the stream. + + + + + Reads a fixed64 field from the stream. + + + + + Reads a fixed32 field from the stream. + + + + + Reads a bool field from the stream. + + + + + Reads a string field from the stream. + + + + + Reads an embedded message field value from the stream. + + + + + Reads an embedded group field from the stream. + + + + + Reads a bytes field value from the stream. + + + + + Reads a uint32 field value from the stream. + + + + + Reads an enum field value from the stream. + + + + + Reads an sfixed32 field value from the stream. + + + + + Reads an sfixed64 field value from the stream. + + + + + Reads an sint32 field value from the stream. + + + + + Reads an sint64 field value from the stream. + + + + + Reads a length for length-delimited data. + + + This is internally just reading a varint, but this method exists + to make the calling code clearer. + + + + + Peeks at the next tag in the stream. If it matches , + the tag is consumed and the method returns true; otherwise, the + stream is left in the original position and the method returns false. + + + + + Reads a raw Varint from the stream. If larger than 32 bits, discard the upper bits. + This method is optimised for the case where we've got lots of data in the buffer. + That means we can check the size just once, then just read directly from the buffer + without constant rechecking of the buffer length. + + + + + Reads a varint from the input one byte at a time, so that it does not + read any bytes after the end of the varint. If you simply wrapped the + stream in a CodedInputStream and used ReadRawVarint32(Stream) + then you would probably end up reading past the end of the varint since + CodedInputStream buffers its input. + + + + + + + Reads a raw varint from the stream. + + + + + Reads a 32-bit little-endian integer from the stream. + + + + + Reads a 64-bit little-endian integer from the stream. + + + + + Sets currentLimit to (current position) + byteLimit. This is called + when descending into a length-delimited embedded message. The previous + limit is returned. + + The old limit. + + + + Discards the current limit, returning the previous limit. + + + + + Returns whether or not all the data before the limit has been read. + + + + + + Returns true if the stream has reached the end of the input. This is the + case if either the end of the underlying input source has been reached or + the stream has reached a limit created using PushLimit. + + + + + Called when buffer is empty to read more bytes from the + input. If is true, RefillBuffer() guarantees that + either there will be at least one byte in the buffer when it returns + or it will throw an exception. If is false, + RefillBuffer() returns false if no more bytes were available. + + + + + + + Reads a fixed size of bytes from the input. + + + the end of the stream or the current limit was reached + + + + + Reads a top-level message or a nested message after the limits for this message have been pushed. + (parser will proceed until the end of the current limit) + NOTE: this method needs to be public because it's invoked by the generated code - e.g. msg.MergeFrom(CodedInputStream input) method + + + + + Encodes and writes protocol message fields. + + + + This class is generally used by generated code to write appropriate + primitives to the stream. It effectively encapsulates the lowest + levels of protocol buffer format. Unlike some other implementations, + this does not include combined "write tag and value" methods. Generated + code knows the exact byte representations of the tags they're going to write, + so there's no need to re-encode them each time. Manually-written code calling + this class should just call one of the WriteTag overloads before each value. + + + Repeated fields and map fields are not handled by this class; use RepeatedField<T> + and MapField<TKey, TValue> to serialize such fields. + + + + + + Computes the number of bytes that would be needed to encode a + double field, including the tag. + + + + + Computes the number of bytes that would be needed to encode a + float field, including the tag. + + + + + Computes the number of bytes that would be needed to encode a + uint64 field, including the tag. + + + + + Computes the number of bytes that would be needed to encode an + int64 field, including the tag. + + + + + Computes the number of bytes that would be needed to encode an + int32 field, including the tag. + + + + + Computes the number of bytes that would be needed to encode a + fixed64 field, including the tag. + + + + + Computes the number of bytes that would be needed to encode a + fixed32 field, including the tag. + + + + + Computes the number of bytes that would be needed to encode a + bool field, including the tag. + + + + + Computes the number of bytes that would be needed to encode a + string field, including the tag. + + + + + Computes the number of bytes that would be needed to encode a + group field, including the tag. + + + + + Computes the number of bytes that would be needed to encode an + embedded message field, including the tag. + + + + + Computes the number of bytes that would be needed to encode a + bytes field, including the tag. + + + + + Computes the number of bytes that would be needed to encode a + uint32 field, including the tag. + + + + + Computes the number of bytes that would be needed to encode a + enum field, including the tag. The caller is responsible for + converting the enum value to its numeric value. + + + + + Computes the number of bytes that would be needed to encode an + sfixed32 field, including the tag. + + + + + Computes the number of bytes that would be needed to encode an + sfixed64 field, including the tag. + + + + + Computes the number of bytes that would be needed to encode an + sint32 field, including the tag. + + + + + Computes the number of bytes that would be needed to encode an + sint64 field, including the tag. + + + + + Computes the number of bytes that would be needed to encode a length, + as written by . + + + + + Computes the number of bytes that would be needed to encode a varint. + + + + + Computes the number of bytes that would be needed to encode a varint. + + + + + Computes the number of bytes that would be needed to encode a tag. + + + + + The buffer size used by CreateInstance(Stream). + + + + + Creates a new CodedOutputStream that writes directly to the given + byte array. If more bytes are written than fit in the array, + OutOfSpaceException will be thrown. + + + + + Creates a new CodedOutputStream that writes directly to the given + byte array slice. If more bytes are written than fit in the array, + OutOfSpaceException will be thrown. + + + + + Creates a new which write to the given stream, and disposes of that + stream when the returned CodedOutputStream is disposed. + + The stream to write to. It will be disposed when the returned CodedOutputStream is disposed. + + + + Creates a new CodedOutputStream which write to the given stream and uses + the specified buffer size. + + The stream to write to. It will be disposed when the returned CodedOutputStream is disposed. + The size of buffer to use internally. + + + + Creates a new CodedOutputStream which write to the given stream. + + The stream to write to. + If true, is left open when the returned CodedOutputStream is disposed; + if false, the provided stream is disposed as well. + + + + Creates a new CodedOutputStream which write to the given stream and uses + the specified buffer size. + + The stream to write to. + The size of buffer to use internally. + If true, is left open when the returned CodedOutputStream is disposed; + if false, the provided stream is disposed as well. + + + + Returns the current position in the stream, or the position in the output buffer + + + + + Writes a double field value, without a tag, to the stream. + + The value to write + + + + Writes a float field value, without a tag, to the stream. + + The value to write + + + + Writes a uint64 field value, without a tag, to the stream. + + The value to write + + + + Writes an int64 field value, without a tag, to the stream. + + The value to write + + + + Writes an int32 field value, without a tag, to the stream. + + The value to write + + + + Writes a fixed64 field value, without a tag, to the stream. + + The value to write + + + + Writes a fixed32 field value, without a tag, to the stream. + + The value to write + + + + Writes a bool field value, without a tag, to the stream. + + The value to write + + + + Writes a string field value, without a tag, to the stream. + The data is length-prefixed. + + The value to write + + + + Writes a message, without a tag, to the stream. + The data is length-prefixed. + + The value to write + + + + Writes a message, without a tag, to the stream. + Only the message data is written, without a length-delimiter. + + The value to write + + + + Writes a group, without a tag, to the stream. + + The value to write + + + + Write a byte string, without a tag, to the stream. + The data is length-prefixed. + + The value to write + + + + Writes a uint32 value, without a tag, to the stream. + + The value to write + + + + Writes an enum value, without a tag, to the stream. + + The value to write + + + + Writes an sfixed32 value, without a tag, to the stream. + + The value to write. + + + + Writes an sfixed64 value, without a tag, to the stream. + + The value to write + + + + Writes an sint32 value, without a tag, to the stream. + + The value to write + + + + Writes an sint64 value, without a tag, to the stream. + + The value to write + + + + Writes a length (in bytes) for length-delimited data. + + + This method simply writes a rawint, but exists for clarity in calling code. + + Length value, in bytes. + + + + Encodes and writes a tag. + + The number of the field to write the tag for + The wire format type of the tag to write + + + + Writes an already-encoded tag. + + The encoded tag + + + + Writes the given single-byte tag directly to the stream. + + The encoded tag + + + + Writes the given two-byte tag directly to the stream. + + The first byte of the encoded tag + The second byte of the encoded tag + + + + Writes the given three-byte tag directly to the stream. + + The first byte of the encoded tag + The second byte of the encoded tag + The third byte of the encoded tag + + + + Writes the given four-byte tag directly to the stream. + + The first byte of the encoded tag + The second byte of the encoded tag + The third byte of the encoded tag + The fourth byte of the encoded tag + + + + Writes the given five-byte tag directly to the stream. + + The first byte of the encoded tag + The second byte of the encoded tag + The third byte of the encoded tag + The fourth byte of the encoded tag + The fifth byte of the encoded tag + + + + Writes a 32 bit value as a varint. The fast route is taken when + there's enough buffer space left to whizz through without checking + for each byte; otherwise, we resort to calling WriteRawByte each time. + + + + + Writes out an array of bytes. + + + + + Writes out part of an array of bytes. + + + + + Indicates that a CodedOutputStream wrapping a flat byte array + ran out of space. + + + + + Flushes any buffered data and optionally closes the underlying stream, if any. + + + + By default, any underlying stream is closed by this method. To configure this behaviour, + use a constructor overload with a leaveOpen parameter. If this instance does not + have an underlying stream, this method does nothing. + + + For the sake of efficiency, calling this method does not prevent future write calls - but + if a later write ends up writing to a stream which has been disposed, that is likely to + fail. It is recommend that you not call any other methods after this. + + + + + + Flushes any buffered data to the underlying stream (if there is one). + + + + + Verifies that SpaceLeft returns zero. It's common to create a byte array + that is exactly big enough to hold a message, then write to it with + a CodedOutputStream. Calling CheckNoSpaceLeft after writing verifies that + the message was actually as big as expected, which can help finding bugs. + + + + + If writing to a flat array, returns the space left in the array. Otherwise, + throws an InvalidOperationException. + + + + + Utility to compare if two Lists are the same, and the hash code + of a List. + + + + + Checks if two lists are equal. + + + + + Gets the list's hash code. + + + + + Representation of a map field in a Protocol Buffer message. + + Key type in the map. Must be a type supported by Protocol Buffer map keys. + Value type in the map. Must be a type supported by Protocol Buffers. + + + For string keys, the equality comparison is provided by . + + + Null values are not permitted in the map, either for wrapper types or regular messages. + If a map is deserialized from a data stream and the value is missing from an entry, a default value + is created instead. For primitive types, that is the regular default value (0, the empty string and so + on); for message types, an empty instance of the message is created, as if the map entry contained a 0-length + encoded value for the field. + + + This implementation does not generally prohibit the use of key/value types which are not + supported by Protocol Buffers (e.g. using a key type of byte) but nor does it guarantee + that all operations will work in such cases. + + + The order in which entries are returned when iterating over this object is undefined, and may change + in future versions. + + + + + + Creates a deep clone of this object. + + + A deep clone of this object. + + + + + Adds the specified key/value pair to the map. + + + This operation fails if the key already exists in the map. To replace an existing entry, use the indexer. + + The key to add + The value to add. + The given key already exists in map. + + + + Determines whether the specified key is present in the map. + + The key to check. + true if the map contains the given key; false otherwise. + + + + Removes the entry identified by the given key from the map. + + The key indicating the entry to remove from the map. + true if the map contained the given key before the entry was removed; false otherwise. + + + + Gets the value associated with the specified key. + + The key whose value to get. + When this method returns, the value associated with the specified key, if the key is found; + otherwise, the default value for the type of the parameter. + This parameter is passed uninitialized. + true if the map contains an element with the specified key; otherwise, false. + + + + Gets or sets the value associated with the specified key. + + The key of the value to get or set. + The property is retrieved and key does not exist in the collection. + The value associated with the specified key. If the specified key is not found, + a get operation throws a , and a set operation creates a new element with the specified key. + + + + Gets a collection containing the keys in the map. + + + + + Gets a collection containing the values in the map. + + + + + Adds the specified entries to the map. The keys and values are not automatically cloned. + + The entries to add to the map. + + + + Returns an enumerator that iterates through the collection. + + + An enumerator that can be used to iterate through the collection. + + + + + Returns an enumerator that iterates through a collection. + + + An object that can be used to iterate through the collection. + + + + + Adds the specified item to the map. + + The item to add to the map. + + + + Removes all items from the map. + + + + + Determines whether map contains an entry equivalent to the given key/value pair. + + The key/value pair to find. + + + + + Copies the key/value pairs in this map to an array. + + The array to copy the entries into. + The index of the array at which to start copying values. + + + + Removes the specified key/value pair from the map. + + Both the key and the value must be found for the entry to be removed. + The key/value pair to remove. + true if the key/value pair was found and removed; false otherwise. + + + + Gets the number of elements contained in the map. + + + + + Gets a value indicating whether the map is read-only. + + + + + Determines whether the specified , is equal to this instance. + + The to compare with this instance. + + true if the specified is equal to this instance; otherwise, false. + + + + + Returns a hash code for this instance. + + + A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + + + + + Compares this map with another for equality. + + + The order of the key/value pairs in the maps is not deemed significant in this comparison. + + The map to compare this with. + true if refers to an equal map; false otherwise. + + + + Adds entries to the map from the given stream. + + + It is assumed that the stream is initially positioned after the tag specified by the codec. + This method will continue reading entries from the stream until the end is reached, or + a different tag is encountered. + + Stream to read from + Codec describing how the key/value pairs are encoded + + + + Adds entries to the map from the given parse context. + + + It is assumed that the input is initially positioned after the tag specified by the codec. + This method will continue reading entries from the input until the end is reached, or + a different tag is encountered. + + Input to read from + Codec describing how the key/value pairs are encoded + + + + Writes the contents of this map to the given coded output stream, using the specified codec + to encode each entry. + + The output stream to write to. + The codec to use for each entry. + + + + Writes the contents of this map to the given write context, using the specified codec + to encode each entry. + + The write context to write to. + The codec to use for each entry. + + + + Calculates the size of this map based on the given entry codec. + + The codec to use to encode each entry. + + + + + Returns a string representation of this repeated field, in the same + way as it would be represented by the default JSON formatter. + + + + + A codec for a specific map field. This contains all the information required to encode and + decode the nested messages. + + + + + Creates a new entry codec based on a separate key codec and value codec, + and the tag to use for each map entry. + + The key codec. + The value codec. + The map tag to use to introduce each map entry. + + + + The key codec. + + + + + The value codec. + + + + + The tag used in the enclosing message to indicate map entries. + + + + + Provides a central place to implement equality comparisons, primarily for bitwise float/double equality. + + + + + Returns an equality comparer for suitable for Protobuf equality comparisons. + This is usually just the default equality comparer for the type, but floating point numbers are compared + bitwise. + + The type of equality comparer to return. + The equality comparer. + + + + Returns an equality comparer suitable for comparing 64-bit floating point values, by bitwise comparison. + (NaN values are considered equal, but only when they have the same representation.) + + + + + Returns an equality comparer suitable for comparing 32-bit floating point values, by bitwise comparison. + (NaN values are considered equal, but only when they have the same representation.) + + + + + Returns an equality comparer suitable for comparing nullable 64-bit floating point values, by bitwise comparison. + (NaN values are considered equal, but only when they have the same representation.) + + + + + Returns an equality comparer suitable for comparing nullable 32-bit floating point values, by bitwise comparison. + (NaN values are considered equal, but only when they have the same representation.) + + + + + Read-only wrapper around another dictionary. + + + + + The contents of a repeated field: essentially, a collection with some extra + restrictions (no null values) and capabilities (deep cloning). + + + This implementation does not generally prohibit the use of types which are not + supported by Protocol Buffers but nor does it guarantee that all operations will work in such cases. + + The element type of the repeated field. + + + + Creates a deep clone of this repeated field. + + + If the field type is + a message type, each element is also cloned; otherwise, it is + assumed that the field type is primitive (including string and + bytes, both of which are immutable) and so a simple copy is + equivalent to a deep clone. + + A deep clone of this repeated field. + + + + Adds the entries from the given input stream, decoding them with the specified codec. + + The input stream to read from. + The codec to use in order to read each entry. + + + + Adds the entries from the given parse context, decoding them with the specified codec. + + The input to read from. + The codec to use in order to read each entry. + + + + Calculates the size of this collection based on the given codec. + + The codec to use when encoding each field. + The number of bytes that would be written to an output by one of the WriteTo methods, + using the same codec. + + + + Writes the contents of this collection to the given , + encoding each value using the specified codec. + + The output stream to write to. + The codec to use when encoding each value. + + + + Writes the contents of this collection to the given write context, + encoding each value using the specified codec. + + The write context to write to. + The codec to use when encoding each value. + + + + Gets and sets the capacity of the RepeatedField's internal array. WHen set, the internal array is reallocated to the given capacity. + The new value is less than Count -or- when Count is less than 0. + + + + + Adds the specified item to the collection. + + The item to add. + + + + Removes all items from the collection. + + + + + Determines whether this collection contains the given item. + + The item to find. + true if this collection contains the given item; false otherwise. + + + + Copies this collection to the given array. + + The array to copy to. + The first index of the array to copy to. + + + + Removes the specified item from the collection + + The item to remove. + true if the item was found and removed; false otherwise. + + + + Gets the number of elements contained in the collection. + + + + + Gets a value indicating whether the collection is read-only. + + + + + Adds all of the specified values into this collection. + + The values to add to this collection. + + + + Adds all of the specified values into this collection. This method is present to + allow repeated fields to be constructed from queries within collection initializers. + Within non-collection-initializer code, consider using the equivalent + method instead for clarity. + + The values to add to this collection. + + + + Returns an enumerator that iterates through the collection. + + + An enumerator that can be used to iterate through the collection. + + + + + Determines whether the specified , is equal to this instance. + + The to compare with this instance. + + true if the specified is equal to this instance; otherwise, false. + + + + + Returns an enumerator that iterates through a collection. + + + An object that can be used to iterate through the collection. + + + + + Returns a hash code for this instance. + + + A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + + + + + Compares this repeated field with another for equality. + + The repeated field to compare this with. + true if refers to an equal repeated field; false otherwise. + + + + Returns the index of the given item within the collection, or -1 if the item is not + present. + + The item to find in the collection. + The zero-based index of the item, or -1 if it is not found. + + + + Inserts the given item at the specified index. + + The index at which to insert the item. + The item to insert. + + + + Removes the item at the given index. + + The zero-based index of the item to remove. + + + + Returns a string representation of this repeated field, in the same + way as it would be represented by the default JSON formatter. + + + + + Gets or sets the item at the specified index. + + + The element at the specified index. + + The zero-based index of the element to get or set. + The item at the specified index. + + + + Extension methods for , effectively providing + the familiar members from previous desktop framework versions while + targeting the newer releases, .NET Core etc. + + + + + Returns the public getter of a property, or null if there is no such getter + (either because it's read-only, or the getter isn't public). + + + + + Returns the public setter of a property, or null if there is no such setter + (either because it's write-only, or the setter isn't public). + + + + + Provides extension methods on Type that just proxy to TypeInfo. + These are used to support the new type system from .NET 4.5, without + having calls to GetTypeInfo all over the place. While the methods here are meant to be + broadly compatible with the desktop framework, there are some subtle differences in behaviour - but + they're not expected to affect our use cases. While the class is internal, that should be fine: we can + evaluate each new use appropriately. + + + + + See https://msdn.microsoft.com/en-us/library/system.type.isassignablefrom + + + + + Returns a representation of the public property associated with the given name in the given type, + including inherited properties or null if there is no such public property. + Here, "public property" means a property where either the getter, or the setter, or both, is public. + + + + + Returns a representation of the public method associated with the given name in the given type, + including inherited methods. + + + This has a few differences compared with Type.GetMethod in the desktop framework. It will throw + if there is an ambiguous match even between a private method and a public one, but it *won't* throw + if there are two overloads at different levels in the type hierarchy (e.g. class Base declares public void Foo(int) and + class Child : Base declares public void Foo(long)). + + One type in the hierarchy declared more than one method with the same name + + + + Represents a non-generic extension definition. This API is experimental and subject to change. + + + + + Internal use. Creates a new extension with the specified field number. + + + + + Gets the field number of this extension + + + + + Represents a type-safe extension identifier used for getting and setting single extension values in instances. + This API is experimental and subject to change. + + The message type this field applies to + The field value type of this extension + + + + Creates a new extension identifier with the specified field number and codec + + + + + Represents a type-safe extension identifier used for getting repeated extension values in instances. + This API is experimental and subject to change. + + The message type this field applies to + The repeated field value type of this extension + + + + Creates a new repeated extension identifier with the specified field number and codec + + + + + Provides extensions to messages while parsing. This API is experimental and subject to change. + + + + + Creates a new empty extension registry + + + + + Gets the total number of extensions in this extension registry + + + + + Returns whether the registry is readonly + + + + + Adds the specified extension to the registry + + + + + Adds the specified extensions to the registry + + + + + Clears the registry of all values + + + + + Gets whether the extension registry contains the specified extension + + + + + Copies the arrays in the registry set to the specified array at the specified index + + The array to copy to + The array index to start at + + + + Returns an enumerator to enumerate through the items in the registry + + Returns an enumerator for the extensions in this registry + + + + Removes the specified extension from the set + + The extension + true if the extension was removed, otherwise false + + + + Clones the registry into a new registry + + + + + Methods for managing s with null checking. + + Most users will not use this class directly and its API is experimental and subject to change. + + + + + Gets the value of the specified extension + + + + + Gets the value of the specified repeated extension or null if it doesn't exist in this set + + + + + Gets the value of the specified repeated extension, registering it if it doesn't exist + + + + + Sets the value of the specified extension. This will make a new instance of ExtensionSet if the set is null. + + + + + Gets whether the value of the specified extension is set + + + + + Clears the value of the specified extension + + + + + Clears the value of the specified extension + + + + + Tries to merge a field from the coded input, returning true if the field was merged. + If the set is null or the field was not otherwise merged, this returns false. + + + + + Tries to merge a field from the coded input, returning true if the field was merged. + If the set is null or the field was not otherwise merged, this returns false. + + + + + Merges the second set into the first set, creating a new instance if first is null + + + + + Clones the set into a new set. If the set is null, this returns null + + + + + Used for keeping track of extensions in messages. + methods route to this set. + + Most users will not need to use this class directly + + The message type that extensions in this set target + + + + Gets a hash code of the set + + + + + Returns whether this set is equal to the other object + + + + + Calculates the size of this extension set + + + + + Writes the extension values in this set to the output stream + + + + + Writes the extension values in this set to the write context + + + + + Factory methods for . + + + + + Retrieves a codec suitable for a string field with the given tag. + + The tag. + A codec for the given tag. + + + + Retrieves a codec suitable for a bytes field with the given tag. + + The tag. + A codec for the given tag. + + + + Retrieves a codec suitable for a bool field with the given tag. + + The tag. + A codec for the given tag. + + + + Retrieves a codec suitable for an int32 field with the given tag. + + The tag. + A codec for the given tag. + + + + Retrieves a codec suitable for an sint32 field with the given tag. + + The tag. + A codec for the given tag. + + + + Retrieves a codec suitable for a fixed32 field with the given tag. + + The tag. + A codec for the given tag. + + + + Retrieves a codec suitable for an sfixed32 field with the given tag. + + The tag. + A codec for the given tag. + + + + Retrieves a codec suitable for a uint32 field with the given tag. + + The tag. + A codec for the given tag. + + + + Retrieves a codec suitable for an int64 field with the given tag. + + The tag. + A codec for the given tag. + + + + Retrieves a codec suitable for an sint64 field with the given tag. + + The tag. + A codec for the given tag. + + + + Retrieves a codec suitable for a fixed64 field with the given tag. + + The tag. + A codec for the given tag. + + + + Retrieves a codec suitable for an sfixed64 field with the given tag. + + The tag. + A codec for the given tag. + + + + Retrieves a codec suitable for a uint64 field with the given tag. + + The tag. + A codec for the given tag. + + + + Retrieves a codec suitable for a float field with the given tag. + + The tag. + A codec for the given tag. + + + + Retrieves a codec suitable for a double field with the given tag. + + The tag. + A codec for the given tag. + + + + Retrieves a codec suitable for an enum field with the given tag. + + The tag. + A conversion function from to the enum type. + A conversion function from the enum type to . + A codec for the given tag. + + + + Retrieves a codec suitable for a string field with the given tag. + + The tag. + The default value. + A codec for the given tag. + + + + Retrieves a codec suitable for a bytes field with the given tag. + + The tag. + The default value. + A codec for the given tag. + + + + Retrieves a codec suitable for a bool field with the given tag. + + The tag. + The default value. + A codec for the given tag. + + + + Retrieves a codec suitable for an int32 field with the given tag. + + The tag. + The default value. + A codec for the given tag. + + + + Retrieves a codec suitable for an sint32 field with the given tag. + + The tag. + The default value. + A codec for the given tag. + + + + Retrieves a codec suitable for a fixed32 field with the given tag. + + The tag. + The default value. + A codec for the given tag. + + + + Retrieves a codec suitable for an sfixed32 field with the given tag. + + The tag. + The default value. + A codec for the given tag. + + + + Retrieves a codec suitable for a uint32 field with the given tag. + + The tag. + The default value. + A codec for the given tag. + + + + Retrieves a codec suitable for an int64 field with the given tag. + + The tag. + The default value. + A codec for the given tag. + + + + Retrieves a codec suitable for an sint64 field with the given tag. + + The tag. + The default value. + A codec for the given tag. + + + + Retrieves a codec suitable for a fixed64 field with the given tag. + + The tag. + The default value. + A codec for the given tag. + + + + Retrieves a codec suitable for an sfixed64 field with the given tag. + + The tag. + The default value. + A codec for the given tag. + + + + Retrieves a codec suitable for a uint64 field with the given tag. + + The tag. + The default value. + A codec for the given tag. + + + + Retrieves a codec suitable for a float field with the given tag. + + The tag. + The default value. + A codec for the given tag. + + + + Retrieves a codec suitable for a double field with the given tag. + + The tag. + The default value. + A codec for the given tag. + + + + Retrieves a codec suitable for an enum field with the given tag. + + The tag. + A conversion function from to the enum type. + A conversion function from the enum type to . + The default value. + A codec for the given tag. + + + + Retrieves a codec suitable for a message field with the given tag. + + The tag. + A parser to use for the message type. + A codec for the given tag. + + + + Retrieves a codec suitable for a group field with the given tag. + + The start group tag. + The end group tag. + A parser to use for the group message type. + A codec for given tag + + + + Creates a codec for a wrapper type of a class - which must be string or ByteString. + + + + + Creates a codec for a wrapper type of a struct - which must be Int32, Int64, UInt32, UInt64, + Bool, Single or Double. + + + + + Helper code to create codecs for wrapper types. + + + Somewhat ugly with all the static methods, but the conversions involved to/from nullable types make it + slightly tricky to improve. So long as we keep the public API (ForClassWrapper, ForStructWrapper) in place, + we can refactor later if we come up with something cleaner. + + + + + Returns a field codec which effectively wraps a value of type T in a message. + + + + + + + An encode/decode pair for a single field. This effectively encapsulates + all the information needed to read or write the field value from/to a coded + stream. + + + This class is public and has to be as it is used by generated code, but its public + API is very limited - just what the generated code needs to call directly. + + + + This never writes default values to the stream, and does not address "packedness" + in repeated fields itself, other than to know whether or not the field *should* be packed. + + + + + Merges an input stream into a value + + + + + Merges a value into a reference to another value, returning a boolean if the value was set + + + + + Returns a delegate to write a value (unconditionally) to a coded output stream. + + + + + Returns the size calculator for just a value. + + + + + Returns a delegate to read a value from a coded input stream. It is assumed that + the stream is already positioned on the appropriate tag. + + + + + Returns a delegate to merge a value from a coded input stream. + It is assumed that the stream is already positioned on the appropriate tag + + + + + Returns a delegate to merge two values together. + + + + + Returns the fixed size for an entry, or 0 if sizes vary. + + + + + Gets the tag of the codec. + + + The tag of the codec. + + + + + Gets the end tag of the codec or 0 if there is no end tag + + + The end tag of the codec. + + + + + Default value for this codec. Usually the same for every instance of the same type, but + for string/ByteString wrapper fields the codec's default value is null, whereas for + other string/ByteString fields it's "" or ByteString.Empty. + + + The default value of the codec's type. + + + + + Write a tag and the given value, *if* the value is not the default. + + + + + Write a tag and the given value, *if* the value is not the default. + + + + + Reads a value of the codec type from the given . + + The input stream to read from. + The value read from the stream. + + + + Reads a value of the codec type from the given . + + The parse context to read from. + The value read. + + + + Calculates the size required to write the given value, with a tag, + if the value is not the default. + + + + + Calculates the size required to write the given value, with a tag, even + if the value is the default. + + + + + A tree representation of a FieldMask. Each leaf node in this tree represent + a field path in the FieldMask. + + For example, FieldMask "foo.bar,foo.baz,bar.baz" as a tree will be: + + [root] -+- foo -+- bar + | | + | +- baz + | + +- bar --- baz + + + By representing FieldMasks with this tree structure we can easily convert + a FieldMask to a canonical form, merge two FieldMasks, calculate the + intersection to two FieldMasks and traverse all fields specified by the + FieldMask in a message tree. + + + + + Creates an empty FieldMaskTree. + + + + + Creates a FieldMaskTree for a given FieldMask. + + + + + Adds a field path to the tree. In a FieldMask, every field path matches the + specified field as well as all its sub-fields. For example, a field path + "foo.bar" matches field "foo.bar" and also "foo.bar.baz", etc. When adding + a field path to the tree, redundant sub-paths will be removed. That is, + after adding "foo.bar" to the tree, "foo.bar.baz" will be removed if it + exists, which will turn the tree node for "foo.bar" to a leaf node. + Likewise, if the field path to add is a sub-path of an existing leaf node, + nothing will be changed in the tree. + + + + + Merges all field paths in a FieldMask into this tree. + + + + + Converts this tree to a FieldMask. + + + + + Gathers all field paths in a sub-tree. + + + + + Adds the intersection of this tree with the given to . + + + + + Merges all fields specified by this FieldMaskTree from to . + + + + + Merges all fields specified by a sub-tree from to . + + + + + Class containing helpful workarounds for various platform compatibility + + + + + Interface for a Protocol Buffers message, supporting + parsing from and writing to . + + + + + Internal implementation of merging data from given parse context into this message. + Users should never invoke this method directly. + + + + + Internal implementation of writing this message to a given write context. + Users should never invoke this method directly. + + + + + A message type that has a custom string format for diagnostic purposes. + + + + Calling on a generated message type normally + returns the JSON representation. If a message type implements this interface, + then the method will be called instead of the regular + JSON formatting code, but only when ToString() is called either on the message itself + or on another message which contains it. This does not affect the normal JSON formatting of + the message. + + + For example, if you create a proto message representing a GUID, the internal + representation may be a bytes field or four fixed32 fields. However, when debugging + it may be more convenient to see a result in the same format as provides. + + This interface extends to avoid it accidentally being implemented + on types other than messages, where it would not be used by anything in the framework. + + + + + Returns a string representation of this object, for diagnostic purposes. + + + This method is called when a message is formatted as part of a + call. It does not affect the JSON representation used by other than + in calls to . While it is recommended + that the result is valid JSON, this is never assumed by the Protobuf library. + + A string representation of this object, for diagnostic purposes. + + + + Generic interface for a deeply cloneable type. + + + + All generated messages implement this interface, but so do some non-message types. + Additionally, due to the type constraint on T in , + it is simpler to keep this as a separate interface. + + + The type itself, returned by the method. + + + + Creates a deep clone of this object. + + A deep clone of this object. + + + + Generic interface for a Protocol Buffers message containing one or more extensions, where the type parameter is expected to be the same type as the implementation class. + This interface is experiemental and is subject to change. + + + + + Gets the value of the specified extension + + + + + Gets the value of the specified repeated extension or null if the extension isn't registered in this set. + For a version of this method that never returns null, use + + + + + Gets the value of the specified repeated extension, registering it if it hasn't already been registered. + + + + + Sets the value of the specified extension + + + + + Gets whether the value of the specified extension is set + + + + + Clears the value of the specified extension + + + + + Clears the value of the specified repeated extension + + + + + Interface for a Protocol Buffers message, supporting + basic operations required for serialization. + + + + + Merges the data from the specified coded input stream with the current message. + + See the user guide for precise merge semantics. + + + + + Writes the data to the given coded output stream. + + Coded output stream to write the data to. Must not be null. + + + + Calculates the size of this message in Protocol Buffer wire format, in bytes. + + The number of bytes required to write this message + to a coded output stream. + + + + Descriptor for this message. All instances are expected to return the same descriptor, + and for generated types this will be an explicitly-implemented member, returning the + same value as the static property declared on the type. + + + + + Generic interface for a Protocol Buffers message, + where the type parameter is expected to be the same type as + the implementation class. + + The message type. + + + + Merges the given message into this one. + + See the user guide for precise merge semantics. + The message to merge with this one. Must not be null. + + + + Thrown when an attempt is made to parse invalid JSON, e.g. using + a non-string property key, or including a redundant comma. Parsing a protocol buffer + message represented in JSON using can throw both this + exception and depending on the situation. This + exception is only thrown for "pure JSON" errors, whereas InvalidProtocolBufferException + is thrown when the JSON may be valid in and of itself, but cannot be parsed as a protocol buffer + message. + + + + + Thrown when a protocol message being parsed is invalid in some way, + e.g. it contains a malformed varint or a negative byte length. + + + + + Creates an exception for an error condition of an invalid tag being encountered. + + + + + Reflection-based converter from messages to JSON. + + + + Instances of this class are thread-safe, with no mutable state. + + + This is a simple start to get JSON formatting working. As it's reflection-based, + it's not as quick as baking calls into generated messages - but is a simpler implementation. + (This code is generally not heavily optimized.) + + + + + + Returns a formatter using the default settings. + + + + + The JSON representation of the first 160 characters of Unicode. + Empty strings are replaced by the static constructor. + + + + + Creates a new formatted with the given settings. + + The settings. + + + + Formats the specified message as JSON. + + The message to format. + The formatted message. + + + + Formats the specified message as JSON. + + The message to format. + The TextWriter to write the formatted message to. + The formatted message. + + + + Converts a message to JSON for diagnostic purposes with no extra context. + + + + This differs from calling on the default JSON + formatter in its handling of . As no type registry is available + in calls, the normal way of resolving the type of + an Any message cannot be applied. Instead, a JSON property named @value + is included with the base64 data from the property of the message. + + The value returned by this method is only designed to be used for diagnostic + purposes. It may not be parsable by , and may not be parsable + by other Protocol Buffer implementations. + + The message to format for diagnostic purposes. + The diagnostic-only JSON representation of the message + + + + Determines whether or not a field value should be serialized according to the field, + its value in the message, and the settings of this formatter. + + + + + Writes a single value to the given writer as JSON. Only types understood by + Protocol Buffers can be written in this way. This method is only exposed for + advanced use cases; most users should be using + or . + + The writer to write the value to. Must not be null. + The value to write. May be null. + + + + Central interception point for well-known type formatting. Any well-known types which + don't need special handling can fall back to WriteMessage. We avoid assuming that the + values are using the embedded well-known types, in order to allow for dynamic messages + in the future. + + + + + Writes a string (including leading and trailing double quotes) to a builder, escaping as required. + + + Other than surrogate pair handling, this code is mostly taken from src/google/protobuf/util/internal/json_escaping.cc. + + + + + Settings controlling JSON formatting. + + + + + Default settings, as used by + + + + + Whether fields which would otherwise not be included in the formatted data + should be formatted even when the value is not present, or has the default value. + This option only affects fields which don't support "presence" (e.g. + singular non-optional proto3 primitive fields). + + + + + The type registry used to format messages. + + + + + Whether to format enums as ints. Defaults to false. + + + + + Creates a new object with the specified formatting of default values + and an empty type registry. + + true if default values (0, empty strings etc) should be formatted; false otherwise. + + + + Creates a new object with the specified formatting of default values + and type registry. + + true if default values (0, empty strings etc) should be formatted; false otherwise. + The to use when formatting messages. + + + + Creates a new object with the specified parameters. + + true if default values (0, empty strings etc) should be formatted; false otherwise. + The to use when formatting messages. TypeRegistry.Empty will be used if it is null. + true to format the enums as integers; false to format enums as enum names. + + + + Creates a new object with the specified formatting of default values and the current settings. + + true if default values (0, empty strings etc) should be formatted; false otherwise. + + + + Creates a new object with the specified type registry and the current settings. + + The to use when formatting messages. + + + + Creates a new object with the specified enums formatting option and the current settings. + + true to format the enums as integers; false to format enums as enum names. + + + + Reflection-based converter from JSON to messages. + + + + Instances of this class are thread-safe, with no mutable state. + + + This is a simple start to get JSON parsing working. As it's reflection-based, + it's not as quick as baking calls into generated messages - but is a simpler implementation. + (This code is generally not heavily optimized.) + + + + + + Returns a formatter using the default settings. + + + + + Creates a new formatted with the given settings. + + The settings. + + + + Parses and merges the information into the given message. + + The message to merge the JSON information into. + The JSON to parse. + + + + Parses JSON read from and merges the information into the given message. + + The message to merge the JSON information into. + Reader providing the JSON to parse. + + + + Merges the given message using data from the given tokenizer. In most cases, the next + token should be a "start object" token, but wrapper types and nullity can invalidate + that assumption. This is implemented as an LL(1) recursive descent parser over the stream + of tokens provided by the tokenizer. This token stream is assumed to be valid JSON, with the + tokenizer performing that validation - but not every token stream is valid "protobuf JSON". + + + + + Parses into a new message. + + The type of message to create. + The JSON to parse. + The JSON does not comply with RFC 7159 + The JSON does not represent a Protocol Buffers message correctly + + + + Parses JSON read from into a new message. + + The type of message to create. + Reader providing the JSON to parse. + The JSON does not comply with RFC 7159 + The JSON does not represent a Protocol Buffers message correctly + + + + Parses into a new message. + + The JSON to parse. + Descriptor of message type to parse. + The JSON does not comply with RFC 7159 + The JSON does not represent a Protocol Buffers message correctly + + + + Parses JSON read from into a new message. + + Reader providing the JSON to parse. + Descriptor of message type to parse. + The JSON does not comply with RFC 7159 + The JSON does not represent a Protocol Buffers message correctly + + + + Creates a new instance of the message type for the given field. + + + + + Checks that any infinite/NaN values originated from the correct text. + This corrects the lenient whitespace handling of double.Parse/float.Parse, as well as the + way that Mono parses out-of-range values as infinity. + + + + + Settings controlling JSON parsing. + + + + + Default settings, as used by . This has the same default + recursion limit as , and an empty type registry. + + + + + The maximum depth of messages to parse. Note that this limit only applies to parsing + messages, not collections - so a message within a collection within a message only counts as + depth 2, not 3. + + + + + The type registry used to parse messages. + + + + + Whether the parser should ignore unknown fields (true) or throw an exception when + they are encountered (false). + + + + + Creates a new object with the specified recursion limit. + + The maximum depth of messages to parse + + + + Creates a new object with the specified recursion limit and type registry. + + The maximum depth of messages to parse + The type registry used to parse messages + + + + Creates a new object set to either ignore unknown fields, or throw an exception + when unknown fields are encountered. + + true if unknown fields should be ignored when parsing; false to throw an exception. + + + + Creates a new object based on this one, but with the specified recursion limit. + + The new recursion limit. + + + + Creates a new object based on this one, but with the specified type registry. + + The new type registry. Must not be null. + + + + Simple but strict JSON tokenizer, rigidly following RFC 7159. + + + + This tokenizer is stateful, and only returns "useful" tokens - names, values etc. + It does not create tokens for the separator between names and values, or for the comma + between values. It validates the token stream as it goes - so callers can assume that the + tokens it produces are appropriate. For example, it would never produce "start object, end array." + + Implementation details: the base class handles single token push-back and + Not thread-safe. + + + + + Creates a tokenizer that reads from the given text reader. + + + + + Creates a tokenizer that first replays the given list of tokens, then continues reading + from another tokenizer. Note that if the returned tokenizer is "pushed back", that does not push back + on the continuation tokenizer, or vice versa. Care should be taken when using this method - it was + created for the sake of Any parsing. + + + + + Returns the depth of the stack, purely in objects (not collections). + Informally, this is the number of remaining unclosed '{' characters we have. + + + + + Returns the next JSON token in the stream. An EndDocument token is returned to indicate the end of the stream, + after which point Next() should not be called again. + + This implementation provides single-token buffering, and calls if there is no buffered token. + The next token in the stream. This is never null. + This method is called after an EndDocument token has been returned + The input text does not comply with RFC 7159 + + + + Returns the next JSON token in the stream, when requested by the base class. (The method delegates + to this if it doesn't have a buffered token.) + + This method is called after an EndDocument token has been returned + The input text does not comply with RFC 7159 + + + + Skips the value we're about to read. This must only be called immediately after reading a property name. + If the value is an object or an array, the complete object/array is skipped. + + + + + Tokenizer which first exhausts a list of tokens, then consults another tokenizer. + + + + + Tokenizer which does all the *real* work of parsing JSON. + + + + + This method essentially just loops through characters skipping whitespace, validating and + changing state (e.g. from ObjectBeforeColon to ObjectAfterColon) + until it reaches something which will be a genuine token (e.g. a start object, or a value) at which point + it returns the token. Although the method is large, it would be relatively hard to break down further... most + of it is the large switch statement, which sometimes returns and sometimes doesn't. + + + + + Reads a string token. It is assumed that the opening " has already been read. + + + + + Reads an escaped character. It is assumed that the leading backslash has already been read. + + + + + Reads an escaped Unicode 4-nybble hex sequence. It is assumed that the leading \u has already been read. + + + + + Consumes a text-only literal, throwing an exception if the read text doesn't match it. + It is assumed that the first letter of the literal has already been read. + + + + + Validates that we're in a valid state to read a value (using the given error prefix if necessary) + and changes the state to the appropriate one, e.g. ObjectAfterColon to ObjectAfterProperty. + + + + + Pops the top-most container, and sets the state to the appropriate one for the end of a value + in the parent container. + + + + + Possible states of the tokenizer. + + + This is a flags enum purely so we can simply and efficiently represent a set of valid states + for checking. + + Each is documented with an example, + where ^ represents the current position within the text stream. The examples all use string values, + but could be any value, including nested objects/arrays. + The complete state of the tokenizer also includes a stack to indicate the contexts (arrays/objects). + Any additional notional state of "AfterValue" indicates that a value has been completed, at which + point there's an immediate transition to ExpectedEndOfDocument, ObjectAfterProperty or ArrayAfterValue. + + + These states were derived manually by reading RFC 7159 carefully. + + + + + + ^ { "foo": "bar" } + Before the value in a document. Next states: ObjectStart, ArrayStart, "AfterValue" + + + + + { "foo": "bar" } ^ + After the value in a document. Next states: ReaderExhausted + + + + + { "foo": "bar" } ^ (and already read to the end of the reader) + Terminal state. + + + + + { ^ "foo": "bar" } + Before the *first* property in an object. + Next states: + "AfterValue" (empty object) + ObjectBeforeColon (read a name) + + + + + { "foo" ^ : "bar", "x": "y" } + Next state: ObjectAfterColon + + + + + { "foo" : ^ "bar", "x": "y" } + Before any property other than the first in an object. + (Equivalently: after any property in an object) + Next states: + "AfterValue" (value is simple) + ObjectStart (value is object) + ArrayStart (value is array) + + + + + { "foo" : "bar" ^ , "x" : "y" } + At the end of a property, so expecting either a comma or end-of-object + Next states: ObjectAfterComma or "AfterValue" + + + + + { "foo":"bar", ^ "x":"y" } + Read the comma after the previous property, so expecting another property. + This is like ObjectStart, but closing brace isn't valid here + Next state: ObjectBeforeColon. + + + + + [ ^ "foo", "bar" ] + Before the *first* value in an array. + Next states: + "AfterValue" (read a value) + "AfterValue" (end of array; will pop stack) + + + + + [ "foo" ^ , "bar" ] + After any value in an array, so expecting either a comma or end-of-array + Next states: ArrayAfterComma or "AfterValue" + + + + + [ "foo", ^ "bar" ] + After a comma in an array, so there *must* be another value (simple or complex). + Next states: "AfterValue" (simple value), StartObject, StartArray + + + + + Wrapper around a text reader allowing small amounts of buffering and location handling. + + + + + The buffered next character, if we have one. + + + + + Returns the next character in the stream, or null if we have reached the end. + + + + + + Creates a new exception appropriate for the current state of the reader. + + + + + Stream implementation which proxies another stream, only allowing a certain amount + of data to be read. Note that this is only used to read delimited streams, so it + doesn't attempt to implement everything. + + + + + Extension methods on and . + + + + + Merges data from the given byte array into an existing message. + + The message to merge the data into. + The data to merge, which must be protobuf-encoded binary data. + + + + Merges data from the given byte array slice into an existing message. + + The message to merge the data into. + The data containing the slice to merge, which must be protobuf-encoded binary data. + The offset of the slice to merge. + The length of the slice to merge. + + + + Merges data from the given byte string into an existing message. + + The message to merge the data into. + The data to merge, which must be protobuf-encoded binary data. + + + + Merges data from the given stream into an existing message. + + The message to merge the data into. + Stream containing the data to merge, which must be protobuf-encoded binary data. + + + + Merges data from the given span into an existing message. + + The message to merge the data into. + Span containing the data to merge, which must be protobuf-encoded binary data. + + + + Merges length-delimited data from the given stream into an existing message. + + + The stream is expected to contain a length and then the data. Only the amount of data + specified by the length will be consumed. + + The message to merge the data into. + Stream containing the data to merge, which must be protobuf-encoded binary data. + + + + Converts the given message into a byte array in protobuf encoding. + + The message to convert. + The message data as a byte array. + + + + Writes the given message data to the given stream in protobuf encoding. + + The message to write to the stream. + The stream to write to. + + + + Writes the length and then data of the given message to a stream. + + The message to write. + The output stream to write to. + + + + Converts the given message into a byte string in protobuf encoding. + + The message to convert. + The message data as a byte string. + + + + Writes the given message data to the given buffer writer in protobuf encoding. + + The message to write to the stream. + The stream to write to. + + + + Writes the given message data to the given span in protobuf encoding. + The size of the destination span needs to fit the serialized size + of the message exactly, otherwise an exception is thrown. + + The message to write to the stream. + The span to write to. Size must match size of the message exactly. + + + + Checks if all required fields in a message have values set. For proto3 messages, this returns true + + + + + A general message parser, typically used by reflection-based code as all the methods + return simple . + + + + + Creates a template instance ready for population. + + An empty message. + + + + Parses a message from a byte array. + + The byte array containing the message. Must not be null. + The newly parsed message. + + + + Parses a message from a byte array slice. + + The byte array containing the message. Must not be null. + The offset of the slice to parse. + The length of the slice to parse. + The newly parsed message. + + + + Parses a message from the given byte string. + + The data to parse. + The parsed message. + + + + Parses a message from the given stream. + + The stream to parse. + The parsed message. + + + + Parses a message from the given sequence. + + The data to parse. + The parsed message. + + + + Parses a message from the given span. + + The data to parse. + The parsed message. + + + + Parses a length-delimited message from the given stream. + + + The stream is expected to contain a length and then the data. Only the amount of data + specified by the length will be consumed. + + The stream to parse. + The parsed message. + + + + Parses a message from the given coded input stream. + + The stream to parse. + The parsed message. + + + + Parses a message from the given JSON. + + The JSON to parse. + The parsed message. + The JSON does not comply with RFC 7159 + The JSON does not represent a Protocol Buffers message correctly + + + + Creates a new message parser which optionally discards unknown fields when parsing. + + Whether or not to discard unknown fields when parsing. + A newly configured message parser. + + + + Creates a new message parser which registers extensions from the specified registry upon creating the message instance + + The extensions to register + A newly configured message parser. + + + + A parser for a specific message type. + + +

+ This delegates most behavior to the + implementation within the original type, but + provides convenient overloads to parse from a variety of sources. +

+

+ Most applications will never need to create their own instances of this type; + instead, use the static Parser property of a generated message type to obtain a + parser for that type. +

+
+ The type of message to be parsed. +
+ + + Creates a new parser. + + + The factory method is effectively an optimization over using a generic constraint + to require a parameterless constructor: delegates are significantly faster to execute. + + Function to invoke when a new, empty message is required. + + + + Creates a template instance ready for population. + + An empty message. + + + + Parses a message from a byte array. + + The byte array containing the message. Must not be null. + The newly parsed message. + + + + Parses a message from a byte array slice. + + The byte array containing the message. Must not be null. + The offset of the slice to parse. + The length of the slice to parse. + The newly parsed message. + + + + Parses a message from the given byte string. + + The data to parse. + The parsed message. + + + + Parses a message from the given stream. + + The stream to parse. + The parsed message. + + + + Parses a message from the given sequence. + + The data to parse. + The parsed message. + + + + Parses a message from the given span. + + The data to parse. + The parsed message. + + + + Parses a length-delimited message from the given stream. + + + The stream is expected to contain a length and then the data. Only the amount of data + specified by the length will be consumed. + + The stream to parse. + The parsed message. + + + + Parses a message from the given coded input stream. + + The stream to parse. + The parsed message. + + + + Parses a message from the given JSON. + + The JSON to parse. + The parsed message. + The JSON does not comply with RFC 7159 + The JSON does not represent a Protocol Buffers message correctly + + + + Creates a new message parser which optionally discards unknown fields when parsing. + + Whether or not to discard unknown fields when parsing. + A newly configured message parser. + + + + Creates a new message parser which registers extensions from the specified registry upon creating the message instance + + The extensions to register + A newly configured message parser. + + + + Struct used to hold the keys for the fieldByNumber table in DescriptorPool and the keys for the + extensionByNumber table in ExtensionRegistry. + + + + + An opaque struct that represents the current parsing state and is passed along + as the parsing proceeds. + All the public methods are intended to be invoked only by the generated code, + users should never invoke them directly. + + + + + Initialize a , building all from defaults and + the given . + + + + + Initialize a using existing , e.g. from . + + + + + Creates a ParseContext instance from CodedInputStream. + WARNING: internally this copies the CodedInputStream's state, so after done with the ParseContext, + the CodedInputStream's state needs to be updated. + + + + + Returns the last tag read, or 0 if no tags have been read or we've read beyond + the end of the input. + + + + + Internal-only property; when set to true, unknown fields will be discarded while parsing. + + + + + Internal-only property; provides extension identifiers to compatible messages while parsing. + + + + + Reads a field tag, returning the tag of 0 for "end of input". + + + If this method returns 0, it doesn't necessarily mean the end of all + the data in this CodedInputReader; it may be the end of the logical input + for an embedded message, for example. + + The next field tag, or 0 for end of input. (0 is never a valid tag.) + + + + Reads a double field from the input. + + + + + Reads a float field from the input. + + + + + Reads a uint64 field from the input. + + + + + Reads an int64 field from the input. + + + + + Reads an int32 field from the input. + + + + + Reads a fixed64 field from the input. + + + + + Reads a fixed32 field from the input. + + + + + Reads a bool field from the input. + + + + + Reads a string field from the input. + + + + + Reads an embedded message field value from the input. + + + + + Reads an embedded group field from the input. + + + + + Reads a bytes field value from the input. + + + + + Reads a uint32 field value from the input. + + + + + Reads an enum field value from the input. + + + + + Reads an sfixed32 field value from the input. + + + + + Reads an sfixed64 field value from the input. + + + + + Reads an sint32 field value from the input. + + + + + Reads an sint64 field value from the input. + + + + + Reads a length for length-delimited data. + + + This is internally just reading a varint, but this method exists + to make the calling code clearer. + + + + + The position within the current buffer (i.e. the next byte to read) + + + + + Size of the current buffer + + + + + If we are currently inside a length-delimited block, this is the number of + bytes in the buffer that are still available once we leave the delimited block. + + + + + The absolute position of the end of the current length-delimited block (including totalBytesRetired) + + + + + The total number of consumed before the start of the current buffer. The + total bytes read up to the current position can be computed as + totalBytesRetired + bufferPos. + + + + + The last tag we read. 0 indicates we've read to the end of the stream + (or haven't read anything yet). + + + + + The next tag, used to store the value read by PeekTag. + + + + + Internal-only property; when set to true, unknown fields will be discarded while parsing. + + + + + Internal-only property; provides extension identifiers to compatible messages while parsing. + + + + + Primitives for parsing protobuf wire format. + + + + + Reads a length for length-delimited data. + + + This is internally just reading a varint, but this method exists + to make the calling code clearer. + + + + + Parses the next tag. + If the end of logical stream was reached, an invalid tag of 0 is returned. + + + + + Peeks at the next tag in the stream. If it matches , + the tag is consumed and the method returns true; otherwise, the + stream is left in the original position and the method returns false. + + + + + Peeks at the next field tag. This is like calling , but the + tag is not consumed. (So a subsequent call to will return the + same value.) + + + + + Parses a raw varint. + + + + + Parses a raw Varint. If larger than 32 bits, discard the upper bits. + This method is optimised for the case where we've got lots of data in the buffer. + That means we can check the size just once, then just read directly from the buffer + without constant rechecking of the buffer length. + + + + + Parses a 32-bit little-endian integer. + + + + + Parses a 64-bit little-endian integer. + + + + + Parses a double value. + + + + + Parses a float value. + + + + + Reads a fixed size of bytes from the input. + + + the end of the stream or the current limit was reached + + + + + Reads and discards bytes. + + the end of the stream + or the current limit was reached + + + + Reads a string field value from the input. + + + + + Reads a bytes field value from the input. + + + + + Reads a UTF-8 string from the next "length" bytes. + + + the end of the stream or the current limit was reached + + + + + Reads a string assuming that it is spread across multiple spans in a . + + + + + Validates that the specified size doesn't exceed the current limit. If it does then remaining bytes + are skipped and an error is thrown. + + + + + Reads a varint from the input one byte at a time, so that it does not + read any bytes after the end of the varint. If you simply wrapped the + stream in a CodedInputStream and used ReadRawVarint32(Stream) + then you would probably end up reading past the end of the varint since + CodedInputStream buffers its input. + + + + + + + Decode a 32-bit value with ZigZag encoding. + + + ZigZag encodes signed integers into values that can be efficiently + encoded with varint. (Otherwise, negative values must be + sign-extended to 32 bits to be varint encoded, thus always taking + 5 bytes on the wire.) + + + + + Decode a 64-bit value with ZigZag encoding. + + + ZigZag encodes signed integers into values that can be efficiently + encoded with varint. (Otherwise, negative values must be + sign-extended to 64 bits to be varint encoded, thus always taking + 10 bytes on the wire.) + + + + + Checks whether there is known data available of the specified size remaining to parse. + When parsing from a Stream this can return false because we have no knowledge of the amount + of data remaining in the stream until it is read. + + + + + Checks whether there is known data available of the specified size remaining to parse + in the underlying data source. + When parsing from a Stream this will return false because we have no knowledge of the amount + of data remaining in the stream until it is read. + + + + + Read raw bytes of the specified length into a span. The amount of data available and the current limit should + be checked before calling this method. + + + + + Reading and skipping messages / groups + + + + + Skip a group. + + + + + Verifies that the last call to ReadTag() returned tag 0 - in other words, + we've reached the end of the stream when we expected to. + + The + tag read was not the one specified + + + + Fast parsing primitives for wrapper types + + + + + Helper methods for throwing exceptions when preconditions are not met. + + + This class is used internally and by generated code; it is not particularly + expected to be used from application code, although nothing prevents it + from being used that way. + + + + + Throws an ArgumentNullException if the given value is null, otherwise + return the value to the caller. + + + + + Throws an ArgumentNullException if the given value is null, otherwise + return the value to the caller. + + + This is equivalent to but without the type parameter + constraint. In most cases, the constraint is useful to prevent you from calling CheckNotNull + with a value type - but it gets in the way if either you want to use it with a nullable + value type, or you want to use it with an unconstrained type parameter. + + + + + Container for a set of custom options specified within a message, field etc. + + + + This type is publicly immutable, but internally mutable. It is only populated + by the descriptor parsing code - by the time any user code is able to see an instance, + it will be fully initialized. + + + If an option is requested using the incorrect method, an answer may still be returned: all + of the numeric types are represented internally using 64-bit integers, for example. It is up to + the caller to ensure that they make the appropriate method call for the option they're interested in. + Note that enum options are simply stored as integers, so the value should be fetched using + and then cast appropriately. + + + Repeated options are currently not supported. Asking for a single value of an option + which was actually repeated will return the last value, except for message types where + all the set values are merged together. + + + + + + Retrieves a Boolean value for the specified option field. + + The field to fetch the value for. + The output variable to populate. + true if a suitable value for the field was found; false otherwise. + + + + Retrieves a signed 32-bit integer value for the specified option field. + + The field to fetch the value for. + The output variable to populate. + true if a suitable value for the field was found; false otherwise. + + + + Retrieves a signed 64-bit integer value for the specified option field. + + The field to fetch the value for. + The output variable to populate. + true if a suitable value for the field was found; false otherwise. + + + + Retrieves an unsigned 32-bit integer value for the specified option field, + assuming a fixed-length representation. + + The field to fetch the value for. + The output variable to populate. + true if a suitable value for the field was found; false otherwise. + + + + Retrieves an unsigned 64-bit integer value for the specified option field, + assuming a fixed-length representation. + + The field to fetch the value for. + The output variable to populate. + true if a suitable value for the field was found; false otherwise. + + + + Retrieves a signed 32-bit integer value for the specified option field, + assuming a fixed-length representation. + + The field to fetch the value for. + The output variable to populate. + true if a suitable value for the field was found; false otherwise. + + + + Retrieves a signed 64-bit integer value for the specified option field, + assuming a fixed-length representation. + + The field to fetch the value for. + The output variable to populate. + true if a suitable value for the field was found; false otherwise. + + + + Retrieves a signed 32-bit integer value for the specified option field, + assuming a zigzag encoding. + + The field to fetch the value for. + The output variable to populate. + true if a suitable value for the field was found; false otherwise. + + + + Retrieves a signed 64-bit integer value for the specified option field, + assuming a zigzag encoding. + + The field to fetch the value for. + The output variable to populate. + true if a suitable value for the field was found; false otherwise. + + + + Retrieves an unsigned 32-bit integer value for the specified option field. + + The field to fetch the value for. + The output variable to populate. + true if a suitable value for the field was found; false otherwise. + + + + Retrieves an unsigned 64-bit integer value for the specified option field. + + The field to fetch the value for. + The output variable to populate. + true if a suitable value for the field was found; false otherwise. + + + + Retrieves a 32-bit floating point value for the specified option field. + + The field to fetch the value for. + The output variable to populate. + true if a suitable value for the field was found; false otherwise. + + + + Retrieves a 64-bit floating point value for the specified option field. + + The field to fetch the value for. + The output variable to populate. + true if a suitable value for the field was found; false otherwise. + + + + Retrieves a string value for the specified option field. + + The field to fetch the value for. + The output variable to populate. + true if a suitable value for the field was found; false otherwise. + + + + Retrieves a bytes value for the specified option field. + + The field to fetch the value for. + The output variable to populate. + true if a suitable value for the field was found; false otherwise. + + + + Retrieves a message value for the specified option field. + + The field to fetch the value for. + The output variable to populate. + true if a suitable value for the field was found; false otherwise. + + + Holder for reflection information generated from google/protobuf/descriptor.proto + + + File descriptor for google/protobuf/descriptor.proto + + + + The protocol compiler can output a FileDescriptorSet containing the .proto + files it parses. + + + + Field number for the "file" field. + + + + Describes a complete .proto file. + + + + Field number for the "name" field. + + + + file name, relative to root of source tree + + + + Gets whether the "name" field is set + + + Clears the value of the "name" field + + + Field number for the "package" field. + + + + e.g. "foo", "foo.bar", etc. + + + + Gets whether the "package" field is set + + + Clears the value of the "package" field + + + Field number for the "dependency" field. + + + + Names of files imported by this file. + + + + Field number for the "public_dependency" field. + + + + Indexes of the public imported files in the dependency list above. + + + + Field number for the "weak_dependency" field. + + + + Indexes of the weak imported files in the dependency list. + For Google-internal migration only. Do not use. + + + + Field number for the "message_type" field. + + + + All top-level definitions in this file. + + + + Field number for the "enum_type" field. + + + Field number for the "service" field. + + + Field number for the "extension" field. + + + Field number for the "options" field. + + + Field number for the "source_code_info" field. + + + + This field contains optional information about the original source code. + You may safely remove this entire field without harming runtime + functionality of the descriptors -- the information is needed only by + development tools. + + + + Field number for the "syntax" field. + + + + The syntax of the proto file. + The supported values are "proto2" and "proto3". + + + + Gets whether the "syntax" field is set + + + Clears the value of the "syntax" field + + + + Describes a message type. + + + + Field number for the "name" field. + + + Gets whether the "name" field is set + + + Clears the value of the "name" field + + + Field number for the "field" field. + + + Field number for the "extension" field. + + + Field number for the "nested_type" field. + + + Field number for the "enum_type" field. + + + Field number for the "extension_range" field. + + + Field number for the "oneof_decl" field. + + + Field number for the "options" field. + + + Field number for the "reserved_range" field. + + + Field number for the "reserved_name" field. + + + + Reserved field names, which may not be used by fields in the same message. + A given name may only be reserved once. + + + + Container for nested types declared in the DescriptorProto message type. + + + Field number for the "start" field. + + + + Inclusive. + + + + Gets whether the "start" field is set + + + Clears the value of the "start" field + + + Field number for the "end" field. + + + + Exclusive. + + + + Gets whether the "end" field is set + + + Clears the value of the "end" field + + + Field number for the "options" field. + + + + Range of reserved tag numbers. Reserved tag numbers may not be used by + fields or extension ranges in the same message. Reserved ranges may + not overlap. + + + + Field number for the "start" field. + + + + Inclusive. + + + + Gets whether the "start" field is set + + + Clears the value of the "start" field + + + Field number for the "end" field. + + + + Exclusive. + + + + Gets whether the "end" field is set + + + Clears the value of the "end" field + + + Field number for the "uninterpreted_option" field. + + + + The parser stores options it doesn't recognize here. See above. + + + + + Describes a field within a message. + + + + Field number for the "name" field. + + + Gets whether the "name" field is set + + + Clears the value of the "name" field + + + Field number for the "number" field. + + + Gets whether the "number" field is set + + + Clears the value of the "number" field + + + Field number for the "label" field. + + + Gets whether the "label" field is set + + + Clears the value of the "label" field + + + Field number for the "type" field. + + + + If type_name is set, this need not be set. If both this and type_name + are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP. + + + + Gets whether the "type" field is set + + + Clears the value of the "type" field + + + Field number for the "type_name" field. + + + + For message and enum types, this is the name of the type. If the name + starts with a '.', it is fully-qualified. Otherwise, C++-like scoping + rules are used to find the type (i.e. first the nested types within this + message are searched, then within the parent, on up to the root + namespace). + + + + Gets whether the "type_name" field is set + + + Clears the value of the "type_name" field + + + Field number for the "extendee" field. + + + + For extensions, this is the name of the type being extended. It is + resolved in the same manner as type_name. + + + + Gets whether the "extendee" field is set + + + Clears the value of the "extendee" field + + + Field number for the "default_value" field. + + + + For numeric types, contains the original text representation of the value. + For booleans, "true" or "false". + For strings, contains the default text contents (not escaped in any way). + For bytes, contains the C escaped value. All bytes >= 128 are escaped. + TODO(kenton): Base-64 encode? + + + + Gets whether the "default_value" field is set + + + Clears the value of the "default_value" field + + + Field number for the "oneof_index" field. + + + + If set, gives the index of a oneof in the containing type's oneof_decl + list. This field is a member of that oneof. + + + + Gets whether the "oneof_index" field is set + + + Clears the value of the "oneof_index" field + + + Field number for the "json_name" field. + + + + JSON name of this field. The value is set by protocol compiler. If the + user has set a "json_name" option on this field, that option's value + will be used. Otherwise, it's deduced from the field's name by converting + it to camelCase. + + + + Gets whether the "json_name" field is set + + + Clears the value of the "json_name" field + + + Field number for the "options" field. + + + Field number for the "proto3_optional" field. + + + + If true, this is a proto3 "optional". When a proto3 field is optional, it + tracks presence regardless of field type. + + When proto3_optional is true, this field must be belong to a oneof to + signal to old proto3 clients that presence is tracked for this field. This + oneof is known as a "synthetic" oneof, and this field must be its sole + member (each proto3 optional field gets its own synthetic oneof). Synthetic + oneofs exist in the descriptor only, and do not generate any API. Synthetic + oneofs must be ordered after all "real" oneofs. + + For message fields, proto3_optional doesn't create any semantic change, + since non-repeated message fields always track presence. However it still + indicates the semantic detail of whether the user wrote "optional" or not. + This can be useful for round-tripping the .proto file. For consistency we + give message fields a synthetic oneof also, even though it is not required + to track presence. This is especially important because the parser can't + tell if a field is a message or an enum, so it must always create a + synthetic oneof. + + Proto2 optional fields do not set this flag, because they already indicate + optional with `LABEL_OPTIONAL`. + + + + Gets whether the "proto3_optional" field is set + + + Clears the value of the "proto3_optional" field + + + Container for nested types declared in the FieldDescriptorProto message type. + + + + 0 is reserved for errors. + Order is weird for historical reasons. + + + + + Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if + negative values are likely. + + + + + Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if + negative values are likely. + + + + + Tag-delimited aggregate. + Group type is deprecated and not supported in proto3. However, Proto3 + implementations should still be able to parse the group wire format and + treat group fields as unknown fields. + + + + + Length-delimited aggregate. + + + + + New in version 2. + + + + + Uses ZigZag encoding. + + + + + Uses ZigZag encoding. + + + + + 0 is reserved for errors + + + + + Describes a oneof. + + + + Field number for the "name" field. + + + Gets whether the "name" field is set + + + Clears the value of the "name" field + + + Field number for the "options" field. + + + + Describes an enum type. + + + + Field number for the "name" field. + + + Gets whether the "name" field is set + + + Clears the value of the "name" field + + + Field number for the "value" field. + + + Field number for the "options" field. + + + Field number for the "reserved_range" field. + + + + Range of reserved numeric values. Reserved numeric values may not be used + by enum values in the same enum declaration. Reserved ranges may not + overlap. + + + + Field number for the "reserved_name" field. + + + + Reserved enum value names, which may not be reused. A given name may only + be reserved once. + + + + Container for nested types declared in the EnumDescriptorProto message type. + + + + Range of reserved numeric values. Reserved values may not be used by + entries in the same enum. Reserved ranges may not overlap. + + Note that this is distinct from DescriptorProto.ReservedRange in that it + is inclusive such that it can appropriately represent the entire int32 + domain. + + + + Field number for the "start" field. + + + + Inclusive. + + + + Gets whether the "start" field is set + + + Clears the value of the "start" field + + + Field number for the "end" field. + + + + Inclusive. + + + + Gets whether the "end" field is set + + + Clears the value of the "end" field + + + + Describes a value within an enum. + + + + Field number for the "name" field. + + + Gets whether the "name" field is set + + + Clears the value of the "name" field + + + Field number for the "number" field. + + + Gets whether the "number" field is set + + + Clears the value of the "number" field + + + Field number for the "options" field. + + + + Describes a service. + + + + Field number for the "name" field. + + + Gets whether the "name" field is set + + + Clears the value of the "name" field + + + Field number for the "method" field. + + + Field number for the "options" field. + + + + Describes a method of a service. + + + + Field number for the "name" field. + + + Gets whether the "name" field is set + + + Clears the value of the "name" field + + + Field number for the "input_type" field. + + + + Input and output type names. These are resolved in the same way as + FieldDescriptorProto.type_name, but must refer to a message type. + + + + Gets whether the "input_type" field is set + + + Clears the value of the "input_type" field + + + Field number for the "output_type" field. + + + Gets whether the "output_type" field is set + + + Clears the value of the "output_type" field + + + Field number for the "options" field. + + + Field number for the "client_streaming" field. + + + + Identifies if client streams multiple client messages + + + + Gets whether the "client_streaming" field is set + + + Clears the value of the "client_streaming" field + + + Field number for the "server_streaming" field. + + + + Identifies if server streams multiple server messages + + + + Gets whether the "server_streaming" field is set + + + Clears the value of the "server_streaming" field + + + Field number for the "java_package" field. + + + + Sets the Java package where classes generated from this .proto will be + placed. By default, the proto package is used, but this is often + inappropriate because proto packages do not normally start with backwards + domain names. + + + + Gets whether the "java_package" field is set + + + Clears the value of the "java_package" field + + + Field number for the "java_outer_classname" field. + + + + Controls the name of the wrapper Java class generated for the .proto file. + That class will always contain the .proto file's getDescriptor() method as + well as any top-level extensions defined in the .proto file. + If java_multiple_files is disabled, then all the other classes from the + .proto file will be nested inside the single wrapper outer class. + + + + Gets whether the "java_outer_classname" field is set + + + Clears the value of the "java_outer_classname" field + + + Field number for the "java_multiple_files" field. + + + + If enabled, then the Java code generator will generate a separate .java + file for each top-level message, enum, and service defined in the .proto + file. Thus, these types will *not* be nested inside the wrapper class + named by java_outer_classname. However, the wrapper class will still be + generated to contain the file's getDescriptor() method as well as any + top-level extensions defined in the file. + + + + Gets whether the "java_multiple_files" field is set + + + Clears the value of the "java_multiple_files" field + + + Field number for the "java_generate_equals_and_hash" field. + + + + This option does nothing. + + + + Gets whether the "java_generate_equals_and_hash" field is set + + + Clears the value of the "java_generate_equals_and_hash" field + + + Field number for the "java_string_check_utf8" field. + + + + If set true, then the Java2 code generator will generate code that + throws an exception whenever an attempt is made to assign a non-UTF-8 + byte sequence to a string field. + Message reflection will do the same. + However, an extension field still accepts non-UTF-8 byte sequences. + This option has no effect on when used with the lite runtime. + + + + Gets whether the "java_string_check_utf8" field is set + + + Clears the value of the "java_string_check_utf8" field + + + Field number for the "optimize_for" field. + + + Gets whether the "optimize_for" field is set + + + Clears the value of the "optimize_for" field + + + Field number for the "go_package" field. + + + + Sets the Go package where structs generated from this .proto will be + placed. If omitted, the Go package will be derived from the following: + - The basename of the package import path, if provided. + - Otherwise, the package statement in the .proto file, if present. + - Otherwise, the basename of the .proto file, without extension. + + + + Gets whether the "go_package" field is set + + + Clears the value of the "go_package" field + + + Field number for the "cc_generic_services" field. + + + + Should generic services be generated in each language? "Generic" services + are not specific to any particular RPC system. They are generated by the + main code generators in each language (without additional plugins). + Generic services were the only kind of service generation supported by + early versions of google.protobuf. + + Generic services are now considered deprecated in favor of using plugins + that generate code specific to your particular RPC system. Therefore, + these default to false. Old code which depends on generic services should + explicitly set them to true. + + + + Gets whether the "cc_generic_services" field is set + + + Clears the value of the "cc_generic_services" field + + + Field number for the "java_generic_services" field. + + + Gets whether the "java_generic_services" field is set + + + Clears the value of the "java_generic_services" field + + + Field number for the "py_generic_services" field. + + + Gets whether the "py_generic_services" field is set + + + Clears the value of the "py_generic_services" field + + + Field number for the "php_generic_services" field. + + + Gets whether the "php_generic_services" field is set + + + Clears the value of the "php_generic_services" field + + + Field number for the "deprecated" field. + + + + Is this file deprecated? + Depending on the target platform, this can emit Deprecated annotations + for everything in the file, or it will be completely ignored; in the very + least, this is a formalization for deprecating files. + + + + Gets whether the "deprecated" field is set + + + Clears the value of the "deprecated" field + + + Field number for the "cc_enable_arenas" field. + + + + Enables the use of arenas for the proto messages in this file. This applies + only to generated classes for C++. + + + + Gets whether the "cc_enable_arenas" field is set + + + Clears the value of the "cc_enable_arenas" field + + + Field number for the "objc_class_prefix" field. + + + + Sets the objective c class prefix which is prepended to all objective c + generated classes from this .proto. There is no default. + + + + Gets whether the "objc_class_prefix" field is set + + + Clears the value of the "objc_class_prefix" field + + + Field number for the "csharp_namespace" field. + + + + Namespace for generated classes; defaults to the package. + + + + Gets whether the "csharp_namespace" field is set + + + Clears the value of the "csharp_namespace" field + + + Field number for the "swift_prefix" field. + + + + By default Swift generators will take the proto package and CamelCase it + replacing '.' with underscore and use that to prefix the types/symbols + defined. When this options is provided, they will use this value instead + to prefix the types/symbols defined. + + + + Gets whether the "swift_prefix" field is set + + + Clears the value of the "swift_prefix" field + + + Field number for the "php_class_prefix" field. + + + + Sets the php class prefix which is prepended to all php generated classes + from this .proto. Default is empty. + + + + Gets whether the "php_class_prefix" field is set + + + Clears the value of the "php_class_prefix" field + + + Field number for the "php_namespace" field. + + + + Use this option to change the namespace of php generated classes. Default + is empty. When this option is empty, the package name will be used for + determining the namespace. + + + + Gets whether the "php_namespace" field is set + + + Clears the value of the "php_namespace" field + + + Field number for the "php_metadata_namespace" field. + + + + Use this option to change the namespace of php generated metadata classes. + Default is empty. When this option is empty, the proto file name will be + used for determining the namespace. + + + + Gets whether the "php_metadata_namespace" field is set + + + Clears the value of the "php_metadata_namespace" field + + + Field number for the "ruby_package" field. + + + + Use this option to change the package of ruby generated classes. Default + is empty. When this option is not set, the package name will be used for + determining the ruby package. + + + + Gets whether the "ruby_package" field is set + + + Clears the value of the "ruby_package" field + + + Field number for the "uninterpreted_option" field. + + + + The parser stores options it doesn't recognize here. + See the documentation for the "Options" section above. + + + + Container for nested types declared in the FileOptions message type. + + + + Generated classes can be optimized for speed or code size. + + + + + Generate complete code for parsing, serialization, + + + + + etc. + + + + + Generate code using MessageLite and the lite runtime. + + + + Field number for the "message_set_wire_format" field. + + + + Set true to use the old proto1 MessageSet wire format for extensions. + This is provided for backwards-compatibility with the MessageSet wire + format. You should not use this for any other reason: It's less + efficient, has fewer features, and is more complicated. + + The message must be defined exactly as follows: + message Foo { + option message_set_wire_format = true; + extensions 4 to max; + } + Note that the message cannot have any defined fields; MessageSets only + have extensions. + + All extensions of your type must be singular messages; e.g. they cannot + be int32s, enums, or repeated messages. + + Because this is an option, the above two restrictions are not enforced by + the protocol compiler. + + + + Gets whether the "message_set_wire_format" field is set + + + Clears the value of the "message_set_wire_format" field + + + Field number for the "no_standard_descriptor_accessor" field. + + + + Disables the generation of the standard "descriptor()" accessor, which can + conflict with a field of the same name. This is meant to make migration + from proto1 easier; new code should avoid fields named "descriptor". + + + + Gets whether the "no_standard_descriptor_accessor" field is set + + + Clears the value of the "no_standard_descriptor_accessor" field + + + Field number for the "deprecated" field. + + + + Is this message deprecated? + Depending on the target platform, this can emit Deprecated annotations + for the message, or it will be completely ignored; in the very least, + this is a formalization for deprecating messages. + + + + Gets whether the "deprecated" field is set + + + Clears the value of the "deprecated" field + + + Field number for the "map_entry" field. + + + + Whether the message is an automatically generated map entry type for the + maps field. + + For maps fields: + map<KeyType, ValueType> map_field = 1; + The parsed descriptor looks like: + message MapFieldEntry { + option map_entry = true; + optional KeyType key = 1; + optional ValueType value = 2; + } + repeated MapFieldEntry map_field = 1; + + Implementations may choose not to generate the map_entry=true message, but + use a native map in the target language to hold the keys and values. + The reflection APIs in such implementations still need to work as + if the field is a repeated message field. + + NOTE: Do not set the option in .proto files. Always use the maps syntax + instead. The option should only be implicitly set by the proto compiler + parser. + + + + Gets whether the "map_entry" field is set + + + Clears the value of the "map_entry" field + + + Field number for the "uninterpreted_option" field. + + + + The parser stores options it doesn't recognize here. See above. + + + + Field number for the "ctype" field. + + + + The ctype option instructs the C++ code generator to use a different + representation of the field than it normally would. See the specific + options below. This option is not yet implemented in the open source + release -- sorry, we'll try to include it in a future version! + + + + Gets whether the "ctype" field is set + + + Clears the value of the "ctype" field + + + Field number for the "packed" field. + + + + The packed option can be enabled for repeated primitive fields to enable + a more efficient representation on the wire. Rather than repeatedly + writing the tag and type for each element, the entire array is encoded as + a single length-delimited blob. In proto3, only explicit setting it to + false will avoid using packed encoding. + + + + Gets whether the "packed" field is set + + + Clears the value of the "packed" field + + + Field number for the "jstype" field. + + + + The jstype option determines the JavaScript type used for values of the + field. The option is permitted only for 64 bit integral and fixed types + (int64, uint64, sint64, fixed64, sfixed64). A field with jstype JS_STRING + is represented as JavaScript string, which avoids loss of precision that + can happen when a large value is converted to a floating point JavaScript. + Specifying JS_NUMBER for the jstype causes the generated JavaScript code to + use the JavaScript "number" type. The behavior of the default option + JS_NORMAL is implementation dependent. + + This option is an enum to permit additional types to be added, e.g. + goog.math.Integer. + + + + Gets whether the "jstype" field is set + + + Clears the value of the "jstype" field + + + Field number for the "lazy" field. + + + + Should this field be parsed lazily? Lazy applies only to message-type + fields. It means that when the outer message is initially parsed, the + inner message's contents will not be parsed but instead stored in encoded + form. The inner message will actually be parsed when it is first accessed. + + This is only a hint. Implementations are free to choose whether to use + eager or lazy parsing regardless of the value of this option. However, + setting this option true suggests that the protocol author believes that + using lazy parsing on this field is worth the additional bookkeeping + overhead typically needed to implement it. + + This option does not affect the public interface of any generated code; + all method signatures remain the same. Furthermore, thread-safety of the + interface is not affected by this option; const methods remain safe to + call from multiple threads concurrently, while non-const methods continue + to require exclusive access. + + Note that implementations may choose not to check required fields within + a lazy sub-message. That is, calling IsInitialized() on the outer message + may return true even if the inner message has missing required fields. + This is necessary because otherwise the inner message would have to be + parsed in order to perform the check, defeating the purpose of lazy + parsing. An implementation which chooses not to check required fields + must be consistent about it. That is, for any particular sub-message, the + implementation must either *always* check its required fields, or *never* + check its required fields, regardless of whether or not the message has + been parsed. + + + + Gets whether the "lazy" field is set + + + Clears the value of the "lazy" field + + + Field number for the "deprecated" field. + + + + Is this field deprecated? + Depending on the target platform, this can emit Deprecated annotations + for accessors, or it will be completely ignored; in the very least, this + is a formalization for deprecating fields. + + + + Gets whether the "deprecated" field is set + + + Clears the value of the "deprecated" field + + + Field number for the "weak" field. + + + + For Google-internal migration only. Do not use. + + + + Gets whether the "weak" field is set + + + Clears the value of the "weak" field + + + Field number for the "uninterpreted_option" field. + + + + The parser stores options it doesn't recognize here. See above. + + + + Container for nested types declared in the FieldOptions message type. + + + + Default mode. + + + + + Use the default type. + + + + + Use JavaScript strings. + + + + + Use JavaScript numbers. + + + + Field number for the "uninterpreted_option" field. + + + + The parser stores options it doesn't recognize here. See above. + + + + Field number for the "allow_alias" field. + + + + Set this option to true to allow mapping different tag names to the same + value. + + + + Gets whether the "allow_alias" field is set + + + Clears the value of the "allow_alias" field + + + Field number for the "deprecated" field. + + + + Is this enum deprecated? + Depending on the target platform, this can emit Deprecated annotations + for the enum, or it will be completely ignored; in the very least, this + is a formalization for deprecating enums. + + + + Gets whether the "deprecated" field is set + + + Clears the value of the "deprecated" field + + + Field number for the "uninterpreted_option" field. + + + + The parser stores options it doesn't recognize here. See above. + + + + Field number for the "deprecated" field. + + + + Is this enum value deprecated? + Depending on the target platform, this can emit Deprecated annotations + for the enum value, or it will be completely ignored; in the very least, + this is a formalization for deprecating enum values. + + + + Gets whether the "deprecated" field is set + + + Clears the value of the "deprecated" field + + + Field number for the "uninterpreted_option" field. + + + + The parser stores options it doesn't recognize here. See above. + + + + Field number for the "deprecated" field. + + + + Is this service deprecated? + Depending on the target platform, this can emit Deprecated annotations + for the service, or it will be completely ignored; in the very least, + this is a formalization for deprecating services. + + + + Gets whether the "deprecated" field is set + + + Clears the value of the "deprecated" field + + + Field number for the "uninterpreted_option" field. + + + + The parser stores options it doesn't recognize here. See above. + + + + Field number for the "deprecated" field. + + + + Is this method deprecated? + Depending on the target platform, this can emit Deprecated annotations + for the method, or it will be completely ignored; in the very least, + this is a formalization for deprecating methods. + + + + Gets whether the "deprecated" field is set + + + Clears the value of the "deprecated" field + + + Field number for the "idempotency_level" field. + + + Gets whether the "idempotency_level" field is set + + + Clears the value of the "idempotency_level" field + + + Field number for the "uninterpreted_option" field. + + + + The parser stores options it doesn't recognize here. See above. + + + + Container for nested types declared in the MethodOptions message type. + + + + Is this method side-effect-free (or safe in HTTP parlance), or idempotent, + or neither? HTTP based RPC implementation may choose GET verb for safe + methods, and PUT verb for idempotent methods instead of the default POST. + + + + + implies idempotent + + + + + idempotent, but may have side effects + + + + + A message representing a option the parser does not recognize. This only + appears in options protos created by the compiler::Parser class. + DescriptorPool resolves these when building Descriptor objects. Therefore, + options protos in descriptor objects (e.g. returned by Descriptor::options(), + or produced by Descriptor::CopyTo()) will never have UninterpretedOptions + in them. + + + + Field number for the "name" field. + + + Field number for the "identifier_value" field. + + + + The value of the uninterpreted option, in whatever type the tokenizer + identified it as during parsing. Exactly one of these should be set. + + + + Gets whether the "identifier_value" field is set + + + Clears the value of the "identifier_value" field + + + Field number for the "positive_int_value" field. + + + Gets whether the "positive_int_value" field is set + + + Clears the value of the "positive_int_value" field + + + Field number for the "negative_int_value" field. + + + Gets whether the "negative_int_value" field is set + + + Clears the value of the "negative_int_value" field + + + Field number for the "double_value" field. + + + Gets whether the "double_value" field is set + + + Clears the value of the "double_value" field + + + Field number for the "string_value" field. + + + Gets whether the "string_value" field is set + + + Clears the value of the "string_value" field + + + Field number for the "aggregate_value" field. + + + Gets whether the "aggregate_value" field is set + + + Clears the value of the "aggregate_value" field + + + Container for nested types declared in the UninterpretedOption message type. + + + + The name of the uninterpreted option. Each string represents a segment in + a dot-separated name. is_extension is true iff a segment represents an + extension (denoted with parentheses in options specs in .proto files). + E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents + "foo.(bar.baz).qux". + + + + Field number for the "name_part" field. + + + Gets whether the "name_part" field is set + + + Clears the value of the "name_part" field + + + Field number for the "is_extension" field. + + + Gets whether the "is_extension" field is set + + + Clears the value of the "is_extension" field + + + + Encapsulates information about the original source file from which a + FileDescriptorProto was generated. + + + + Field number for the "location" field. + + + + A Location identifies a piece of source code in a .proto file which + corresponds to a particular definition. This information is intended + to be useful to IDEs, code indexers, documentation generators, and similar + tools. + + For example, say we have a file like: + message Foo { + optional string foo = 1; + } + Let's look at just the field definition: + optional string foo = 1; + ^ ^^ ^^ ^ ^^^ + a bc de f ghi + We have the following locations: + span path represents + [a,i) [ 4, 0, 2, 0 ] The whole field definition. + [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). + [c,d) [ 4, 0, 2, 0, 5 ] The type (string). + [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). + [g,h) [ 4, 0, 2, 0, 3 ] The number (1). + + Notes: + - A location may refer to a repeated field itself (i.e. not to any + particular index within it). This is used whenever a set of elements are + logically enclosed in a single code segment. For example, an entire + extend block (possibly containing multiple extension definitions) will + have an outer location whose path refers to the "extensions" repeated + field without an index. + - Multiple locations may have the same path. This happens when a single + logical declaration is spread out across multiple places. The most + obvious example is the "extend" block again -- there may be multiple + extend blocks in the same scope, each of which will have the same path. + - A location's span is not always a subset of its parent's span. For + example, the "extendee" of an extension declaration appears at the + beginning of the "extend" block and is shared by all extensions within + the block. + - Just because a location's span is a subset of some other location's span + does not mean that it is a descendant. For example, a "group" defines + both a type and a field in a single declaration. Thus, the locations + corresponding to the type and field and their components will overlap. + - Code which tries to interpret locations should probably be designed to + ignore those that it doesn't understand, as more types of locations could + be recorded in the future. + + + + Container for nested types declared in the SourceCodeInfo message type. + + + Field number for the "path" field. + + + + Identifies which part of the FileDescriptorProto was defined at this + location. + + Each element is a field number or an index. They form a path from + the root FileDescriptorProto to the place where the definition. For + example, this path: + [ 4, 3, 2, 7, 1 ] + refers to: + file.message_type(3) // 4, 3 + .field(7) // 2, 7 + .name() // 1 + This is because FileDescriptorProto.message_type has field number 4: + repeated DescriptorProto message_type = 4; + and DescriptorProto.field has field number 2: + repeated FieldDescriptorProto field = 2; + and FieldDescriptorProto.name has field number 1: + optional string name = 1; + + Thus, the above path gives the location of a field name. If we removed + the last element: + [ 4, 3, 2, 7 ] + this path refers to the whole field declaration (from the beginning + of the label to the terminating semicolon). + + + + Field number for the "span" field. + + + + Always has exactly three or four elements: start line, start column, + end line (optional, otherwise assumed same as start line), end column. + These are packed into a single field for efficiency. Note that line + and column numbers are zero-based -- typically you will want to add + 1 to each before displaying to a user. + + + + Field number for the "leading_comments" field. + + + + If this SourceCodeInfo represents a complete declaration, these are any + comments appearing before and after the declaration which appear to be + attached to the declaration. + + A series of line comments appearing on consecutive lines, with no other + tokens appearing on those lines, will be treated as a single comment. + + leading_detached_comments will keep paragraphs of comments that appear + before (but not connected to) the current element. Each paragraph, + separated by empty lines, will be one comment element in the repeated + field. + + Only the comment content is provided; comment markers (e.g. //) are + stripped out. For block comments, leading whitespace and an asterisk + will be stripped from the beginning of each line other than the first. + Newlines are included in the output. + + Examples: + + optional int32 foo = 1; // Comment attached to foo. + // Comment attached to bar. + optional int32 bar = 2; + + optional string baz = 3; + // Comment attached to baz. + // Another line attached to baz. + + // Comment attached to qux. + // + // Another line attached to qux. + optional double qux = 4; + + // Detached comment for corge. This is not leading or trailing comments + // to qux or corge because there are blank lines separating it from + // both. + + // Detached comment for corge paragraph 2. + + optional string corge = 5; + /* Block comment attached + * to corge. Leading asterisks + * will be removed. */ + /* Block comment attached to + * grault. */ + optional int32 grault = 6; + + // ignored detached comments. + + + + Gets whether the "leading_comments" field is set + + + Clears the value of the "leading_comments" field + + + Field number for the "trailing_comments" field. + + + Gets whether the "trailing_comments" field is set + + + Clears the value of the "trailing_comments" field + + + Field number for the "leading_detached_comments" field. + + + + Describes the relationship between generated code and its original source + file. A GeneratedCodeInfo message is associated with only one generated + source file, but may contain references to different source .proto files. + + + + Field number for the "annotation" field. + + + + An Annotation connects some span of text in generated code to an element + of its generating .proto file. + + + + Container for nested types declared in the GeneratedCodeInfo message type. + + + Field number for the "path" field. + + + + Identifies the element in the original source .proto file. This field + is formatted the same as SourceCodeInfo.Location.path. + + + + Field number for the "source_file" field. + + + + Identifies the filesystem path to the original source .proto. + + + + Gets whether the "source_file" field is set + + + Clears the value of the "source_file" field + + + Field number for the "begin" field. + + + + Identifies the starting offset in bytes in the generated code + that relates to the identified object. + + + + Gets whether the "begin" field is set + + + Clears the value of the "begin" field + + + Field number for the "end" field. + + + + Identifies the ending offset in bytes in the generated code that + relates to the identified offset. The end offset should be one past + the last relevant byte (so the length of the text = end - begin). + + + + Gets whether the "end" field is set + + + Clears the value of the "end" field + + + + Base class for nearly all descriptors, providing common functionality. + + + + + The index of this descriptor within its parent descriptor. + + + This returns the index of this descriptor within its parent, for + this descriptor's type. (There can be duplicate values for different + types, e.g. one enum type with index 0 and one message type with index 0.) + + + + + Returns the name of the entity (field, message etc) being described. + + + + + The fully qualified name of the descriptor's target. + + + + + The file this descriptor was declared in. + + + + + The declaration information about the descriptor, or null if no declaration information + is available for this descriptor. + + + This information is typically only available for dynamically loaded descriptors, + for example within a protoc plugin where the full descriptors, including source info, + are passed to the code by protoc. + + + + + Retrieves the list of nested descriptors corresponding to the given field number, if any. + If the field is unknown or not a nested descriptor list, return null to terminate the search. + The default implementation returns null. + + + + + Provides additional information about the declaration of a descriptor, + such as source location and comments. + + + + + The descriptor this declaration relates to. + + + + + The start line of the declaration within the source file. This value is 1-based. + + + + + The start column of the declaration within the source file. This value is 1-based. + + + + + // The end line of the declaration within the source file. This value is 1-based. + + + + + The end column of the declaration within the source file. This value is 1-based, and + exclusive. (The final character of the declaration is on the column before this value.) + + + + + Comments appearing before the declaration. Never null, but may be empty. Multi-line comments + are represented as a newline-separated string. Leading whitespace and the comment marker ("//") + are removed from each line. + + + + + Comments appearing after the declaration. Never null, but may be empty. Multi-line comments + are represented as a newline-separated string. Leading whitespace and the comment marker ("//") + are removed from each line. + + + + + Comments appearing before the declaration, but separated from it by blank + lines. Each string represents a newline-separated paragraph of comments. + Leading whitespace and the comment marker ("//") are removed from each line. + The list is never null, but may be empty. Likewise each element is never null, but may be empty. + + + + + Contains lookup tables containing all the descriptors defined in a particular file. + + + + + Finds a symbol of the given name within the pool. + + The type of symbol to look for + Fully-qualified name to look up + The symbol with the given name and type, + or null if the symbol doesn't exist or has the wrong type + + + + Adds a package to the symbol tables. If a package by the same name + already exists, that is fine, but if some other kind of symbol + exists under the same name, an exception is thrown. If the package + has multiple components, this also adds the parent package(s). + + + + + Adds a symbol to the symbol table. + + The symbol already existed + in the symbol table. + + + + Verifies that the descriptor's name is valid (i.e. it contains + only letters, digits and underscores, and does not start with a digit). + + + + + + Returns the field with the given number in the given descriptor, + or null if it can't be found. + + + + + Adds a field to the fieldsByNumber table. + + A field with the same + containing type and number already exists. + + + + Adds an enum value to the enumValuesByNumber table. If an enum value + with the same type and number already exists, this method does nothing. + (This is allowed; the first value defined with the number takes precedence.) + + + + + Looks up a descriptor by name, relative to some other descriptor. + The name may be fully-qualified (with a leading '.'), partially-qualified, + or unqualified. C++-like name lookup semantics are used to search for the + matching descriptor. + + + This isn't heavily optimized, but it's only used during cross linking anyway. + If it starts being used more widely, we should look at performance more carefully. + + + + + Internal class containing utility methods when working with descriptors. + + + + + Equivalent to Func[TInput, int, TOutput] but usable in .NET 2.0. Only used to convert + arrays. + + + + + Converts the given array into a read-only list, applying the specified conversion to + each input element. + + + + + Thrown when building descriptors fails because the source DescriptorProtos + are not valid. + + + + + The full name of the descriptor where the error occurred. + + + + + A human-readable description of the error. (The Message property + is made up of the descriptor's name and this description.) + + + + + Descriptor for an enum type in a .proto file. + + + + + The brief name of the descriptor's target. + + + + + The CLR type for this enum. For generated code, this will be a CLR enum type. + + + + + If this is a nested type, get the outer descriptor, otherwise null. + + + + + An unmodifiable list of defined value descriptors for this enum. + + + + + Finds an enum value by number. If multiple enum values have the + same number, this returns the first defined value with that number. + If there is no value for the given number, this returns null. + + + + + Finds an enum value by name. + + The unqualified name of the value (e.g. "FOO"). + The value's descriptor, or null if not found. + + + + The (possibly empty) set of custom options for this enum. + + + + + The EnumOptions, defined in descriptor.proto. + If the options message is not present (i.e. there are no options), null is returned. + Custom options can be retrieved as extensions of the returned message. + NOTE: A defensive copy is created each time this property is retrieved. + + + + + Gets a single value enum option for this descriptor + + + + + Gets a repeated value enum option for this descriptor + + + + + Descriptor for a single enum value within an enum in a .proto file. + + + + + Returns the name of the enum value described by this object. + + + + + Returns the number associated with this enum value. + + + + + Returns the enum descriptor that this value is part of. + + + + + The (possibly empty) set of custom options for this enum value. + + + + + The EnumValueOptions, defined in descriptor.proto. + If the options message is not present (i.e. there are no options), null is returned. + Custom options can be retrieved as extensions of the returned message. + NOTE: A defensive copy is created each time this property is retrieved. + + + + + Gets a single value enum value option for this descriptor + + + + + Gets a repeated value enum value option for this descriptor + + + + + A collection to simplify retrieving the descriptors of extensions in a descriptor for a message + + + + + Returns a readonly list of all the extensions defined in this type in + the order they were defined in the source .proto file + + + + + Returns a readonly list of all the extensions define in this type that extend + the provided descriptor type in the order they were defined in the source .proto file + + + + + Returns a readonly list of all the extensions define in this type that extend + the provided descriptor type in accending field order + + + + + Base class for field accessors. + + + + + Descriptor for a field or extension within a message in a .proto file. + + + + + Get the field's containing message type, or null if it is a field defined at the top level of a file as an extension. + + + + + Returns the oneof containing this field, or null if it is not part of a oneof. + + + + + Returns the oneof containing this field if it's a "real" oneof, or null if either this + field is not part of a oneof, or the oneof is synthetic. + + + + + The effective JSON name for this field. This is usually the lower-camel-cased form of the field name, + but can be overridden using the json_name option in the .proto file. + + + + + The name of the property in the ContainingType.ClrType class. + + + + + Indicates whether this field supports presence, either implicitly (e.g. due to it being a message + type field) or explicitly via Has/Clear members. If this returns true, it is safe to call + and + on this field's accessor with a suitable message. + + + + + An extension identifier for this field, or null if this field isn't an extension. + + + + + The brief name of the descriptor's target. + + + + + Returns the accessor for this field. + + + + While a describes the field, it does not provide + any way of obtaining or changing the value of the field within a specific message; + that is the responsibility of the accessor. + + + In descriptors for generated code, the value returned by this property will be non-null for all + regular fields. However, if a message containing a map field is introspected, the list of nested messages will include + an auto-generated nested key/value pair message for the field. This is not represented in any + generated type, and the value of the map field itself is represented by a dictionary in the + reflection API. There are never instances of those "hidden" messages, so no accessor is provided + and this property will return null. + + + In dynamically loaded descriptors, the value returned by this property will current be null; + if and when dynamic messages are supported, it will return a suitable accessor to work with + them. + + + + + + Maps a field type as included in the .proto file to a FieldType. + + + + + Returns true if this field is a repeated field; false otherwise. + + + + + Returns true if this field is a required field; false otherwise. + + + + + Returns true if this field is a map field; false otherwise. + + + + + Returns true if this field is a packed, repeated field; false otherwise. + + + + + Returns true if this field extends another message type; false otherwise. + + + + + Returns the type of the field. + + + + + Returns the field number declared in the proto file. + + + + + Compares this descriptor with another one, ordering in "canonical" order + which simply means ascending order by field number. + must be a field of the same type, i.e. the of + both fields must be the same. + + + + + For enum fields, returns the field's type. + + + + + For embedded message and group fields, returns the field's type. + + + + + For extension fields, returns the extended type + + + + + The (possibly empty) set of custom options for this field. + + + + + The FieldOptions, defined in descriptor.proto. + If the options message is not present (i.e. there are no options), null is returned. + Custom options can be retrieved as extensions of the returned message. + NOTE: A defensive copy is created each time this property is retrieved. + + + + + Gets a single value field option for this descriptor + + + + + Gets a repeated value field option for this descriptor + + + + + Look up and cross-link all field types etc. + + + + + Enumeration of all the possible field types. + + + + + The double field type. + + + + + The float field type. + + + + + The int64 field type. + + + + + The uint64 field type. + + + + + The int32 field type. + + + + + The fixed64 field type. + + + + + The fixed32 field type. + + + + + The bool field type. + + + + + The string field type. + + + + + The field type used for groups. + + + + + The field type used for message fields. + + + + + The bytes field type. + + + + + The uint32 field type. + + + + + The sfixed32 field type. + + + + + The sfixed64 field type. + + + + + The sint32 field type. + + + + + The sint64 field type. + + + + + The field type used for enum fields. + + + + + The syntax of a .proto file + + + + + Proto2 syntax + + + + + Proto3 syntax + + + + + An unknown declared syntax + + + + + Describes a .proto file, including everything defined within. + IDescriptor is implemented such that the File property returns this descriptor, + and the FullName is the same as the Name. + + + + + Computes the full name of a descriptor within this file, with an optional parent message. + + + + + Extracts public dependencies from direct dependencies. This is a static method despite its + first parameter, as the value we're in the middle of constructing is only used for exceptions. + + + + + The descriptor in its protocol message representation. + + + + + The syntax of the file + + + + + The file name. + + + + + The package as declared in the .proto file. This may or may not + be equivalent to the .NET namespace of the generated classes. + + + + + Unmodifiable list of top-level message types declared in this file. + + + + + Unmodifiable list of top-level enum types declared in this file. + + + + + Unmodifiable list of top-level services declared in this file. + + + + + Unmodifiable list of top-level extensions declared in this file. + Note that some extensions may be incomplete (FieldDescriptor.Extension may be null) + if this descriptor was generated using a version of protoc that did not fully + support extensions in C#. + + + + + Unmodifiable list of this file's dependencies (imports). + + + + + Unmodifiable list of this file's public dependencies (public imports). + + + + + The original serialized binary form of this descriptor. + + + + + Implementation of IDescriptor.FullName - just returns the same as Name. + + + + + Implementation of IDescriptor.File - just returns this descriptor. + + + + + Pool containing symbol descriptors. + + + + + Finds a type (message, enum, service or extension) in the file by name. Does not find nested types. + + The unqualified type name to look for. + The type of descriptor to look for + The type's descriptor, or null if not found. + + + + Builds a FileDescriptor from its protocol buffer representation. + + The original serialized descriptor data. + We have only limited proto2 support, so serializing FileDescriptorProto + would not necessarily give us this. + The protocol message form of the FileDescriptor. + FileDescriptors corresponding to all of the + file's dependencies, in the exact order listed in the .proto file. May be null, + in which case it is treated as an empty array. + Whether unknown dependencies are ignored (true) or cause an exception to be thrown (false). + Details about generated code, for the purposes of reflection. + If is not + a valid descriptor. This can occur for a number of reasons, such as a field + having an undefined type or because two messages were defined with the same name. + + + + Creates a descriptor for generated code. + + + This method is only designed to be used by the results of generating code with protoc, + which creates the appropriate dependencies etc. It has to be public because the generated + code is "external", but should not be called directly by end users. + + + + + Converts the given descriptor binary data into FileDescriptor objects. + Note: reflection using the returned FileDescriptors is not currently supported. + + The binary file descriptor proto data. Must not be null, and any + dependencies must come before the descriptor which depends on them. (If A depends on B, and B + depends on C, then the descriptors must be presented in the order C, B, A.) This is compatible + with the order in which protoc provides descriptors to plugins. + The extension registry to use when parsing, or null if no extensions are required. + The file descriptors corresponding to . + + + + Converts the given descriptor binary data into FileDescriptor objects. + Note: reflection using the returned FileDescriptors is not currently supported. + + The binary file descriptor proto data. Must not be null, and any + dependencies must come before the descriptor which depends on them. (If A depends on B, and B + depends on C, then the descriptors must be presented in the order C, B, A.) This is compatible + with the order in which protoc provides descriptors to plugins. + The file descriptors corresponding to . + + + + Returns a that represents this instance. + + + A that represents this instance. + + + + + Returns the file descriptor for descriptor.proto. + + + This is used for protos which take a direct dependency on descriptor.proto, typically for + annotations. While descriptor.proto is a proto2 file, it is built into the Google.Protobuf + runtime for reflection purposes. The messages are internal to the runtime as they would require + proto2 semantics for full support, but the file descriptor is available via this property. The + C# codegen in protoc automatically uses this property when it detects a dependency on descriptor.proto. + + + The file descriptor for descriptor.proto. + + + + + The (possibly empty) set of custom options for this file. + + + + + The FileOptions, defined in descriptor.proto. + If the options message is not present (i.e. there are no options), null is returned. + Custom options can be retrieved as extensions of the returned message. + NOTE: A defensive copy is created each time this property is retrieved. + + + + + Gets a single value file option for this descriptor + + + + + Gets a repeated value file option for this descriptor + + + + + Performs initialization for the given generic type argument. + + + This method is present for the sake of AOT compilers. It allows code (whether handwritten or generated) + to make calls into the reflection machinery of this library to express an intention to use that type + reflectively (e.g. for JSON parsing and formatting). The call itself does almost nothing, but AOT compilers + attempting to determine which generic type arguments need to be handled will spot the code path and act + accordingly. + + The type to force initialization for. + + + + Extra information provided by generated code when initializing a message or file descriptor. + These are constructed as required, and are not long-lived. Hand-written code should + never need to use this type. + + + + + Irrelevant for file descriptors; the CLR type for the message for message descriptors. + + + + + Irrelevant for file descriptors; the parser for message descriptors. + + + + + Irrelevant for file descriptors; the CLR property names (in message descriptor field order) + for fields in the message for message descriptors. + + + + + The extensions defined within this file/message descriptor + + + + + Irrelevant for file descriptors; the CLR property "base" names (in message descriptor oneof order) + for oneofs in the message for message descriptors. It is expected that for a oneof name of "Foo", + there will be a "FooCase" property and a "ClearFoo" method. + + + + + The reflection information for types within this file/message descriptor. Elements may be null + if there is no corresponding generated type, e.g. for map entry types. + + + + + The CLR types for enums within this file/message descriptor. + + + + + Creates a GeneratedClrTypeInfo for a message descriptor, with nested types, nested enums, the CLR type, property names and oneof names. + Each array parameter may be null, to indicate a lack of values. + The parameter order is designed to make it feasible to format the generated code readably. + + + + + Creates a GeneratedClrTypeInfo for a message descriptor, with nested types, nested enums, the CLR type, property names and oneof names. + Each array parameter may be null, to indicate a lack of values. + The parameter order is designed to make it feasible to format the generated code readably. + + + + + Creates a GeneratedClrTypeInfo for a file descriptor, with only types, enums, and extensions. + + + + + Creates a GeneratedClrTypeInfo for a file descriptor, with only types and enums. + + + + + Interface implemented by all descriptor types. + + + + + Returns the name of the entity (message, field etc) being described. + + + + + Returns the fully-qualified name of the entity being described. + + + + + Returns the descriptor for the .proto file that this entity is part of. + + + + + Allows fields to be reflectively accessed. + + + + + Returns the descriptor associated with this field. + + + + + Clears the field in the specified message. (For repeated fields, + this clears the list.) + + + + + Fetches the field value. For repeated values, this will be an + implementation. For map values, this will be an + implementation. + + + + + Indicates whether the field in the specified message is set. + For proto3 fields that aren't explicitly optional, this throws an + + + + + Mutator for single "simple" fields only. + + + Repeated fields are mutated by fetching the value and manipulating it as a list. + Map fields are mutated by fetching the value and manipulating it as a dictionary. + + The field is not a "simple" field. + + + + Accessor for map fields. + + + + + Describes a message type. + + + + + The brief name of the descriptor's target. + + + + + The CLR type used to represent message instances from this descriptor. + + + + The value returned by this property will be non-null for all regular fields. However, + if a message containing a map field is introspected, the list of nested messages will include + an auto-generated nested key/value pair message for the field. This is not represented in any + generated type, so this property will return null in such cases. + + + For wrapper types ( and the like), the type returned here + will be the generated message type, not the native type used by reflection for fields of those types. Code + using reflection should call to determine whether a message descriptor represents + a wrapper type, and handle the result appropriately. + + + + + + A parser for this message type. + + + + As is not generic, this cannot be statically + typed to the relevant type, but it should produce objects of a type compatible with . + + + The value returned by this property will be non-null for all regular fields. However, + if a message containing a map field is introspected, the list of nested messages will include + an auto-generated nested key/value pair message for the field. No message parser object is created for + such messages, so this property will return null in such cases. + + + For wrapper types ( and the like), the parser returned here + will be the generated message type, not the native type used by reflection for fields of those types. Code + using reflection should call to determine whether a message descriptor represents + a wrapper type, and handle the result appropriately. + + + + + + Returns whether this message is one of the "well known types" which may have runtime/protoc support. + + + + + Returns whether this message is one of the "wrapper types" used for fields which represent primitive values + with the addition of presence. + + + + + If this is a nested type, get the outer descriptor, otherwise null. + + + + + A collection of fields, which can be retrieved by name or field number. + + + + + An unmodifiable list of extensions defined in this message's scope. + Note that some extensions may be incomplete (FieldDescriptor.Extension may be null) + if they are declared in a file generated using a version of protoc that did not fully + support extensions in C#. + + + + + An unmodifiable list of this message type's nested types. + + + + + An unmodifiable list of this message type's enum types. + + + + + An unmodifiable list of the "oneof" field collections in this message type. + All "real" oneofs (where returns false) + come before synthetic ones. + + + + + The number of real "oneof" descriptors in this message type. Every element in + with an index less than this will have a property value + of false; every element with an index greater than or equal to this will have a + property value of true. + + + + + Finds a field by field name. + + The unqualified name of the field (e.g. "foo"). + The field's descriptor, or null if not found. + + + + Finds a field by field number. + + The field number within this message type. + The field's descriptor, or null if not found. + + + + Finds a nested descriptor by name. The is valid for fields, nested + message types, oneofs and enums. + + The unqualified name of the descriptor, e.g. "Foo" + The descriptor, or null if not found. + + + + The (possibly empty) set of custom options for this message. + + + + + The MessageOptions, defined in descriptor.proto. + If the options message is not present (i.e. there are no options), null is returned. + Custom options can be retrieved as extensions of the returned message. + NOTE: A defensive copy is created each time this property is retrieved. + + + + + Gets a single value message option for this descriptor + + + + + Gets a repeated value message option for this descriptor + + + + + Looks up and cross-links all fields and nested types. + + + + + A collection to simplify retrieving the field accessor for a particular field. + + + + + Returns the fields in the message as an immutable list, in the order in which they + are declared in the source .proto file. + + + + + Returns the fields in the message as an immutable list, in ascending field number + order. Field numbers need not be contiguous, so there is no direct mapping from the + index in the list to the field number; to retrieve a field by field number, it is better + to use the indexer. + + + + + Returns a read-only dictionary mapping the field names in this message as they're available + in the JSON representation to the field descriptors. For example, a field foo_bar + in the message would result two entries, one with a key fooBar and one with a key + foo_bar, both referring to the same field. + + + + + Retrieves the descriptor for the field with the given number. + + Number of the field to retrieve the descriptor for + The accessor for the given field + The message descriptor does not contain a field + with the given number + + + + Retrieves the descriptor for the field with the given name. + + Name of the field to retrieve the descriptor for + The descriptor for the given field + The message descriptor does not contain a field + with the given name + + + + Describes a single method in a service. + + + + + The service this method belongs to. + + + + + The method's input type. + + + + + The method's input type. + + + + + Indicates if client streams multiple requests. + + + + + Indicates if server streams multiple responses. + + + + + The (possibly empty) set of custom options for this method. + + + + + The MethodOptions, defined in descriptor.proto. + If the options message is not present (i.e. there are no options), null is returned. + Custom options can be retrieved as extensions of the returned message. + NOTE: A defensive copy is created each time this property is retrieved. + + + + + Gets a single value method option for this descriptor + + + + + Gets a repeated value method option for this descriptor + + + + + The brief name of the descriptor's target. + + + + + Reflection access for a oneof, allowing clear and "get case" actions. + + + + + Gets the descriptor for this oneof. + + + The descriptor of the oneof. + + + + + Clears the oneof in the specified message. + + + + + Indicates which field in the oneof is set for specified message + + + + + Describes a "oneof" field collection in a message type: a set of + fields of which at most one can be set in any particular message. + + + + + The brief name of the descriptor's target. + + + + + Gets the message type containing this oneof. + + + The message type containing this oneof. + + + + + Gets the fields within this oneof, in declaration order. + + + The fields within this oneof, in declaration order. + + + + + Returns true if this oneof is a synthetic oneof containing a proto3 optional field; + false otherwise. + + + + + Gets an accessor for reflective access to the values associated with the oneof + in a particular message. + + + + In descriptors for generated code, the value returned by this property will always be non-null. + + + In dynamically loaded descriptors, the value returned by this property will current be null; + if and when dynamic messages are supported, it will return a suitable accessor to work with + them. + + + + The accessor used for reflective access. + + + + + The (possibly empty) set of custom options for this oneof. + + + + + The OneofOptions, defined in descriptor.proto. + If the options message is not present (i.e. there are no options), null is returned. + Custom options can be retrieved as extensions of the returned message. + NOTE: A defensive copy is created each time this property is retrieved. + + + + + Gets a single value oneof option for this descriptor + + + + + Gets a repeated value oneof option for this descriptor + + + + + Specifies the original name (in the .proto file) of a named element, + such as an enum value. + + + + + The name of the element in the .proto file. + + + + + If the name is preferred in the .proto file. + + + + + Constructs a new attribute instance for the given name. + + The name of the element in the .proto file. + + + + Represents a package in the symbol table. We use PackageDescriptors + just as placeholders so that someone cannot define, say, a message type + that has the same name as an existing package. + + + + + The methods in this class are somewhat evil, and should not be tampered with lightly. + Basically they allow the creation of relatively weakly typed delegates from MethodInfos + which are more strongly typed. They do this by creating an appropriate strongly typed + delegate from the MethodInfo, and then calling that within an anonymous method. + Mind-bending stuff (at least to your humble narrator) but the resulting delegates are + very fast compared with calling Invoke later on. + + + + + Empty Type[] used when calling GetProperty to force property instead of indexer fetching. + + + + + Creates a delegate which will cast the argument to the type that declares the method, + call the method on it, then convert the result to object. + + The method to create a delegate for, which must be declared in an IMessage + implementation. + + + + Creates a delegate which will cast the argument to the type that declares the method, + call the method on it, then convert the result to the specified type. The method is expected + to actually return an enum (because of where we're calling it - for oneof cases). Sometimes that + means we need some extra work to perform conversions. + + The method to create a delegate for, which must be declared in an IMessage + implementation. + + + + Creates a delegate which will execute the given method after casting the first argument to + the type that declares the method, and the second argument to the first parameter type of the method. + + The method to create a delegate for, which must be declared in an IMessage + implementation. + + + + Creates a delegate which will execute the given method after casting the first argument to + type that declares the method. + + The method to create a delegate for, which must be declared in an IMessage + implementation. + + + + Creates a delegate which will execute the given method after casting the first argument to + the type that declares the method, and the second argument to the first parameter type of the method. + + + + + Creates a reflection helper for the given type arguments. Currently these are created on demand + rather than cached; this will be "busy" when initially loading a message's descriptor, but after that + they can be garbage collected. We could cache them by type if that proves to be important, but creating + an object is pretty cheap. + + + + + Accessor for repeated fields. + + + + + Describes a service type. + + + + + The brief name of the descriptor's target. + + + + + An unmodifiable list of methods in this service. + + + + + Finds a method by name. + + The unqualified name of the method (e.g. "Foo"). + The method's descriptor, or null if not found. + + + + The (possibly empty) set of custom options for this service. + + + + + The ServiceOptions, defined in descriptor.proto. + If the options message is not present (i.e. there are no options), null is returned. + Custom options can be retrieved as extensions of the returned message. + NOTE: A defensive copy is created each time this property is retrieved. + + + + + Gets a single value service option for this descriptor + + + + + Gets a repeated value service option for this descriptor + + + + + Accessor for single fields. + + + + + An immutable registry of types which can be looked up by their full name. + + + + + An empty type registry, containing no types. + + + + + Attempts to find a message descriptor by its full name. + + The full name of the message, which is the dot-separated + combination of package, containing messages and message name + The message descriptor corresponding to or null + if there is no such message descriptor. + + + + Creates a type registry from the specified set of file descriptors. + + + This is a convenience overload for + to allow calls such as TypeRegistry.FromFiles(descriptor1, descriptor2). + + The set of files to include in the registry. Must not contain null values. + A type registry for the given files. + + + + Creates a type registry from the specified set of file descriptors. + + + All message types within all the specified files are added to the registry, and + the dependencies of the specified files are also added, recursively. + + The set of files to include in the registry. Must not contain null values. + A type registry for the given files. + + + + Creates a type registry from the file descriptor parents of the specified set of message descriptors. + + + This is a convenience overload for + to allow calls such as TypeRegistry.FromFiles(descriptor1, descriptor2). + + The set of message descriptors to use to identify file descriptors to include in the registry. + Must not contain null values. + A type registry for the given files. + + + + Creates a type registry from the file descriptor parents of the specified set of message descriptors. + + + The specified message descriptors are only used to identify their file descriptors; the returned registry + contains all the types within the file descriptors which contain the specified message descriptors (and + the dependencies of those files), not just the specified messages. + + The set of message descriptors to use to identify file descriptors to include in the registry. + Must not contain null values. + A type registry for the given files. + + + + Builder class which isn't exposed, but acts as a convenient alternative to passing round two dictionaries in recursive calls. + + + + + Abstraction for reading from a stream / read only sequence. + Parsing from the buffer is a loop of reading from current buffer / refreshing the buffer once done. + + + + + Initialize an instance with a coded input stream. + This approach is faster than using a constructor because the instance to initialize is passed by reference + and we can write directly into it without copying. + + + + + Initialize an instance with a read only sequence. + This approach is faster than using a constructor because the instance to initialize is passed by reference + and we can write directly into it without copying. + + + + + Sets currentLimit to (current position) + byteLimit. This is called + when descending into a length-delimited embedded message. The previous + limit is returned. + + The old limit. + + + + Discards the current limit, returning the previous limit. + + + + + Returns whether or not all the data before the limit has been read. + + + + + + Returns true if the stream has reached the end of the input. This is the + case if either the end of the underlying input source has been reached or + the stream has reached a limit created using PushLimit. + + + + + Represents a single field in an UnknownFieldSet. + + An UnknownField consists of four lists of values. The lists correspond + to the four "wire types" used in the protocol buffer binary format. + Normally, only one of the four lists will contain any values, since it + is impossible to define a valid message type that declares two different + types for the same field number. However, the code is designed to allow + for the case where the same unknown field number is encountered using + multiple different wire types. + + + + + + Creates a new UnknownField. + + + + + Checks if two unknown field are equal. + + + + + Get the hash code of the unknown field. + + + + + Serializes the field, including the field number, and writes it to + + + The unknown field number. + The write context to write to. + + + + Computes the number of bytes required to encode this field, including field + number. + + + + + Merge the values in into this field. For each list + of values, 's values are append to the ones in this + field. + + + + + Returns a new list containing all of the given specified values from + both the and lists. + If is null and is null or empty, + null is returned. Otherwise, either a new list is created (if + is null) or the elements of are added to . + + + + + Adds a varint value. + + + + + Adds a fixed32 value. + + + + + Adds a fixed64 value. + + + + + Adds a length-delimited value. + + + + + Adds to the , creating + a new list if is null. The list is returned - either + the original reference or the new list. + + + + + Used to keep track of fields which were seen when parsing a protocol message + but whose field numbers or types are unrecognized. This most frequently + occurs when new fields are added to a message type and then messages containing + those fields are read by old software that was built before the new types were + added. + + Most users will never need to use this class directly. + + + + + Creates a new UnknownFieldSet. + + + + + Checks whether or not the given field number is present in the set. + + + + + Serializes the set and writes it to . + + + + + Serializes the set and writes it to . + + + + + Gets the number of bytes required to encode this set. + + + + + Checks if two unknown field sets are equal. + + + + + Gets the unknown field set's hash code. + + + + + Adds a field to the set. If a field with the same number already exists, it + is replaced. + + + + + Parse a single field from and merge it + into this set. + + The parse context from which to read the field + false if the tag is an "end group" tag, true otherwise + + + + Create a new UnknownFieldSet if unknownFields is null. + Parse a single field from and merge it + into unknownFields. If is configured to discard unknown fields, + will be returned as-is and the field will be skipped. + + The UnknownFieldSet which need to be merged + The coded input stream containing the field + The merged UnknownFieldSet + + + + Create a new UnknownFieldSet if unknownFields is null. + Parse a single field from and merge it + into unknownFields. If is configured to discard unknown fields, + will be returned as-is and the field will be skipped. + + The UnknownFieldSet which need to be merged + The parse context from which to read the field + The merged UnknownFieldSet + + + + Merges the fields from into this set. + If a field number exists in both sets, the values in + will be appended to the values in this set. + + + + + Created a new UnknownFieldSet to if + needed and merges the fields from into the first set. + If a field number exists in both sets, the values in + will be appended to the values in this set. + + + + + Adds a field to the unknown field set. If a field with the same + number already exists, the two are merged. + + + + + Clone an unknown field set from . + + + + + Provides a number of unsafe byte operations to be used by advanced applications with high performance + requirements. These methods are referred to as "unsafe" due to the fact that they potentially expose + the backing buffer of a to the application. + + + + The methods in this class should only be called if it is guaranteed that the buffer backing the + will never change! Mutation of a can lead to unexpected + and undesirable consequences in your application, and will likely be difficult to debug. Proceed with caution! + + + This can have a number of significant side affects that have spooky-action-at-a-distance-like behavior. In + particular, if the bytes value changes out from under a Protocol Buffer: + + + + serialization may throw + + + serialization may succeed but the wrong bytes may be written out + + + objects that are normally immutable (such as ByteString) are no longer immutable + + + hashCode may be incorrect + + + + + + + Constructs a new from the given bytes. The bytes are not copied, + and must not be modified while the is in use. + This API is experimental and subject to change. + + + + Holder for reflection information generated from google/protobuf/any.proto + + + File descriptor for google/protobuf/any.proto + + + + `Any` contains an arbitrary serialized protocol buffer message along with a + URL that describes the type of the serialized message. + + Protobuf library provides support to pack/unpack Any values in the form + of utility functions or additional generated methods of the Any type. + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := anypb.New(foo) + if err != nil { + ... + } + ... + foo := &pb.Foo{} + if err := any.UnmarshalTo(foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by default use + 'type.googleapis.com/full.type.name' as the type URL and the unpack + methods only use the fully qualified type name after the last '/' + in the type URL, for example "foo.bar.com/x/y.z" will yield type + name "y.z". + + JSON + ==== + The JSON representation of an `Any` value uses the regular + representation of the deserialized, embedded message, with an + additional field `@type` which contains the type URL. Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": <string>, + "lastName": <string> + } + + If the embedded message type is well-known and has a custom JSON + representation, that representation will be embedded adding a field + `value` which holds the custom JSON in addition to the `@type` + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + + + + Field number for the "type_url" field. + + + + A URL/resource name that uniquely identifies the type of the serialized + protocol buffer message. This string must contain at least + one "/" character. The last segment of the URL's path must represent + the fully qualified name of the type (as in + `path/google.protobuf.Duration`). The name should be in a canonical form + (e.g., leading "." is not accepted). + + In practice, teams usually precompile into the binary all types that they + expect it to use in the context of Any. However, for URLs which use the + scheme `http`, `https`, or no scheme, one can optionally set up a type + server that maps type URLs to message definitions as follows: + + * If no scheme is provided, `https` is assumed. + * An HTTP GET on the URL must yield a [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in the official + protobuf release, and it is not used for type URLs beginning with + type.googleapis.com. + + Schemes other than `http`, `https` (or the empty scheme) might be + used with implementation specific semantics. + + + + Field number for the "value" field. + + + + Must be a valid serialized protocol buffer of the above specified type. + + + + + Retrieves the type name for a type URL, matching the + of the packed message type. + + + + This is always just the last part of the URL, after the final slash. No validation of + anything before the trailing slash is performed. If the type URL does not include a slash, + an empty string is returned rather than an exception being thrown; this won't match any types, + and the calling code is probably in a better position to give a meaningful error. + + + There is no handling of fragments or queries at the moment. + + + The URL to extract the type name from + The type name + + + + Returns a bool indictating whether this Any message is of the target message type + + The descriptor of the message type + true if the type name matches the descriptor's full name or false otherwise + + + + Unpacks the content of this Any message into the target message type, + which must match the type URL within this Any message. + + The type of message to unpack the content into. + The unpacked message. + The target message type doesn't match the type URL in this message + + + + Attempts to unpack the content of this Any message into the target message type, + if it matches the type URL within this Any message. + + The type of message to attempt to unpack the content into. + true if the message was successfully unpacked; false if the type name didn't match + + + + Packs the specified message into an Any message using a type URL prefix of "type.googleapis.com". + + The message to pack. + An Any message with the content and type URL of . + + + + Packs the specified message into an Any message using the specified type URL prefix. + + The message to pack. + The prefix for the type URL. + An Any message with the content and type URL of . + + + Holder for reflection information generated from google/protobuf/api.proto + + + File descriptor for google/protobuf/api.proto + + + + Api is a light-weight descriptor for an API Interface. + + Interfaces are also described as "protocol buffer services" in some contexts, + such as by the "service" keyword in a .proto file, but they are different + from API Services, which represent a concrete implementation of an interface + as opposed to simply a description of methods and bindings. They are also + sometimes simply referred to as "APIs" in other contexts, such as the name of + this message itself. See https://cloud.google.com/apis/design/glossary for + detailed terminology. + + + + Field number for the "name" field. + + + + The fully qualified name of this interface, including package name + followed by the interface's simple name. + + + + Field number for the "methods" field. + + + + The methods of this interface, in unspecified order. + + + + Field number for the "options" field. + + + + Any metadata attached to the interface. + + + + Field number for the "version" field. + + + + A version string for this interface. If specified, must have the form + `major-version.minor-version`, as in `1.10`. If the minor version is + omitted, it defaults to zero. If the entire version field is empty, the + major version is derived from the package name, as outlined below. If the + field is not empty, the version in the package name will be verified to be + consistent with what is provided here. + + The versioning schema uses [semantic + versioning](http://semver.org) where the major version number + indicates a breaking change and the minor version an additive, + non-breaking change. Both version numbers are signals to users + what to expect from different versions, and should be carefully + chosen based on the product plan. + + The major version is also reflected in the package name of the + interface, which must end in `v<major-version>`, as in + `google.feature.v1`. For major versions 0 and 1, the suffix can + be omitted. Zero major versions must only be used for + experimental, non-GA interfaces. + + + + Field number for the "source_context" field. + + + + Source context for the protocol buffer service represented by this + message. + + + + Field number for the "mixins" field. + + + + Included interfaces. See [Mixin][]. + + + + Field number for the "syntax" field. + + + + The source syntax of the service. + + + + + Method represents a method of an API interface. + + + + Field number for the "name" field. + + + + The simple name of this method. + + + + Field number for the "request_type_url" field. + + + + A URL of the input message type. + + + + Field number for the "request_streaming" field. + + + + If true, the request is streamed. + + + + Field number for the "response_type_url" field. + + + + The URL of the output message type. + + + + Field number for the "response_streaming" field. + + + + If true, the response is streamed. + + + + Field number for the "options" field. + + + + Any metadata attached to the method. + + + + Field number for the "syntax" field. + + + + The source syntax of this method. + + + + + Declares an API Interface to be included in this interface. The including + interface must redeclare all the methods from the included interface, but + documentation and options are inherited as follows: + + - If after comment and whitespace stripping, the documentation + string of the redeclared method is empty, it will be inherited + from the original method. + + - Each annotation belonging to the service config (http, + visibility) which is not set in the redeclared method will be + inherited. + + - If an http annotation is inherited, the path pattern will be + modified as follows. Any version prefix will be replaced by the + version of the including interface plus the [root][] path if + specified. + + Example of a simple mixin: + + package google.acl.v1; + service AccessControl { + // Get the underlying ACL object. + rpc GetAcl(GetAclRequest) returns (Acl) { + option (google.api.http).get = "/v1/{resource=**}:getAcl"; + } + } + + package google.storage.v2; + service Storage { + rpc GetAcl(GetAclRequest) returns (Acl); + + // Get a data record. + rpc GetData(GetDataRequest) returns (Data) { + option (google.api.http).get = "/v2/{resource=**}"; + } + } + + Example of a mixin configuration: + + apis: + - name: google.storage.v2.Storage + mixins: + - name: google.acl.v1.AccessControl + + The mixin construct implies that all methods in `AccessControl` are + also declared with same name and request/response types in + `Storage`. A documentation generator or annotation processor will + see the effective `Storage.GetAcl` method after inheriting + documentation and annotations as follows: + + service Storage { + // Get the underlying ACL object. + rpc GetAcl(GetAclRequest) returns (Acl) { + option (google.api.http).get = "/v2/{resource=**}:getAcl"; + } + ... + } + + Note how the version in the path pattern changed from `v1` to `v2`. + + If the `root` field in the mixin is specified, it should be a + relative path under which inherited HTTP paths are placed. Example: + + apis: + - name: google.storage.v2.Storage + mixins: + - name: google.acl.v1.AccessControl + root: acls + + This implies the following inherited HTTP annotation: + + service Storage { + // Get the underlying ACL object. + rpc GetAcl(GetAclRequest) returns (Acl) { + option (google.api.http).get = "/v2/acls/{resource=**}:getAcl"; + } + ... + } + + + + Field number for the "name" field. + + + + The fully qualified name of the interface which is included. + + + + Field number for the "root" field. + + + + If non-empty specifies a path under which inherited HTTP paths + are rooted. + + + + Holder for reflection information generated from google/protobuf/duration.proto + + + File descriptor for google/protobuf/duration.proto + + + + A Duration represents a signed, fixed-length span of time represented + as a count of seconds and fractions of seconds at nanosecond + resolution. It is independent of any calendar and concepts like "day" + or "month". It is related to Timestamp in that the difference between + two Timestamp values is a Duration and it can be added or subtracted + from a Timestamp. Range is approximately +-10,000 years. + + # Examples + + Example 1: Compute Duration from two Timestamps in pseudo code. + + Timestamp start = ...; + Timestamp end = ...; + Duration duration = ...; + + duration.seconds = end.seconds - start.seconds; + duration.nanos = end.nanos - start.nanos; + + if (duration.seconds < 0 && duration.nanos > 0) { + duration.seconds += 1; + duration.nanos -= 1000000000; + } else if (duration.seconds > 0 && duration.nanos < 0) { + duration.seconds -= 1; + duration.nanos += 1000000000; + } + + Example 2: Compute Timestamp from Timestamp + Duration in pseudo code. + + Timestamp start = ...; + Duration duration = ...; + Timestamp end = ...; + + end.seconds = start.seconds + duration.seconds; + end.nanos = start.nanos + duration.nanos; + + if (end.nanos < 0) { + end.seconds -= 1; + end.nanos += 1000000000; + } else if (end.nanos >= 1000000000) { + end.seconds += 1; + end.nanos -= 1000000000; + } + + Example 3: Compute Duration from datetime.timedelta in Python. + + td = datetime.timedelta(days=3, minutes=10) + duration = Duration() + duration.FromTimedelta(td) + + # JSON Mapping + + In JSON format, the Duration type is encoded as a string rather than an + object, where the string ends in the suffix "s" (indicating seconds) and + is preceded by the number of seconds, with nanoseconds expressed as + fractional seconds. For example, 3 seconds with 0 nanoseconds should be + encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should + be expressed in JSON format as "3.000000001s", and 3 seconds and 1 + microsecond should be expressed in JSON format as "3.000001s". + + + + Field number for the "seconds" field. + + + + Signed seconds of the span of time. Must be from -315,576,000,000 + to +315,576,000,000 inclusive. Note: these bounds are computed from: + 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years + + + + Field number for the "nanos" field. + + + + Signed fractions of a second at nanosecond resolution of the span + of time. Durations less than one second are represented with a 0 + `seconds` field and a positive or negative `nanos` field. For durations + of one second or more, a non-zero value for the `nanos` field must be + of the same sign as the `seconds` field. Must be from -999,999,999 + to +999,999,999 inclusive. + + + + + The number of nanoseconds in a second. + + + + + The number of nanoseconds in a BCL tick (as used by and ). + + + + + The maximum permitted number of seconds. + + + + + The minimum permitted number of seconds. + + + + + Converts this to a . + + If the duration is not a precise number of ticks, it is truncated towards 0. + The value of this duration, as a TimeSpan. + This value isn't a valid normalized duration, as + described in the documentation. + + + + Converts the given to a . + + The TimeSpan to convert. + The value of the given TimeSpan, as a Duration. + + + + Returns the result of negating the duration. For example, the negation of 5 minutes is -5 minutes. + + The duration to negate. Must not be null. + The negated value of this duration. + + + + Adds the two specified values together. + + The first value to add. Must not be null. + The second value to add. Must not be null. + + + + + Subtracts one from another. + + The duration to subtract from. Must not be null. + The duration to subtract. Must not be null. + The difference between the two specified durations. + + + + Creates a duration with the normalized values from the given number of seconds and + nanoseconds, conforming with the description in the proto file. + + + + + Converts a duration specified in seconds/nanoseconds to a string. + + + If the value is a normalized duration in the range described in duration.proto, + is ignored. Otherwise, if the parameter is true, + a JSON object with a warning is returned; if it is false, an is thrown. + + Seconds portion of the duration. + Nanoseconds portion of the duration. + Determines the handling of non-normalized values + The represented duration is invalid, and is false. + + + + Returns a string representation of this for diagnostic purposes. + + + Normally the returned value will be a JSON string value (including leading and trailing quotes) but + when the value is non-normalized or out of range, a JSON object representation will be returned + instead, including a warning. This is to avoid exceptions being thrown when trying to + diagnose problems - the regular JSON formatter will still throw an exception for non-normalized + values. + + A string representation of this value. + + + + Appends a number of nanoseconds to a StringBuilder. Either 0 digits are added (in which + case no "." is appended), or 3 6 or 9 digits. This is internal for use in Timestamp as well + as Duration. + + + + Holder for reflection information generated from google/protobuf/empty.proto + + + File descriptor for google/protobuf/empty.proto + + + + A generic empty message that you can re-use to avoid defining duplicated + empty messages in your APIs. A typical example is to use it as the request + or the response type of an API method. For instance: + + service Foo { + rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); + } + + The JSON representation for `Empty` is empty JSON object `{}`. + + + + Holder for reflection information generated from google/protobuf/field_mask.proto + + + File descriptor for google/protobuf/field_mask.proto + + + + `FieldMask` represents a set of symbolic field paths, for example: + + paths: "f.a" + paths: "f.b.d" + + Here `f` represents a field in some root message, `a` and `b` + fields in the message found in `f`, and `d` a field found in the + message in `f.b`. + + Field masks are used to specify a subset of fields that should be + returned by a get operation or modified by an update operation. + Field masks also have a custom JSON encoding (see below). + + # Field Masks in Projections + + When used in the context of a projection, a response message or + sub-message is filtered by the API to only contain those fields as + specified in the mask. For example, if the mask in the previous + example is applied to a response message as follows: + + f { + a : 22 + b { + d : 1 + x : 2 + } + y : 13 + } + z: 8 + + The result will not contain specific values for fields x,y and z + (their value will be set to the default, and omitted in proto text + output): + + f { + a : 22 + b { + d : 1 + } + } + + A repeated field is not allowed except at the last position of a + paths string. + + If a FieldMask object is not present in a get operation, the + operation applies to all fields (as if a FieldMask of all fields + had been specified). + + Note that a field mask does not necessarily apply to the + top-level response message. In case of a REST get operation, the + field mask applies directly to the response, but in case of a REST + list operation, the mask instead applies to each individual message + in the returned resource list. In case of a REST custom method, + other definitions may be used. Where the mask applies will be + clearly documented together with its declaration in the API. In + any case, the effect on the returned resource/resources is required + behavior for APIs. + + # Field Masks in Update Operations + + A field mask in update operations specifies which fields of the + targeted resource are going to be updated. The API is required + to only change the values of the fields as specified in the mask + and leave the others untouched. If a resource is passed in to + describe the updated values, the API ignores the values of all + fields not covered by the mask. + + If a repeated field is specified for an update operation, new values will + be appended to the existing repeated field in the target resource. Note that + a repeated field is only allowed in the last position of a `paths` string. + + If a sub-message is specified in the last position of the field mask for an + update operation, then new value will be merged into the existing sub-message + in the target resource. + + For example, given the target message: + + f { + b { + d: 1 + x: 2 + } + c: [1] + } + + And an update message: + + f { + b { + d: 10 + } + c: [2] + } + + then if the field mask is: + + paths: ["f.b", "f.c"] + + then the result will be: + + f { + b { + d: 10 + x: 2 + } + c: [1, 2] + } + + An implementation may provide options to override this default behavior for + repeated and message fields. + + In order to reset a field's value to the default, the field must + be in the mask and set to the default value in the provided resource. + Hence, in order to reset all fields of a resource, provide a default + instance of the resource and set all fields in the mask, or do + not provide a mask as described below. + + If a field mask is not present on update, the operation applies to + all fields (as if a field mask of all fields has been specified). + Note that in the presence of schema evolution, this may mean that + fields the client does not know and has therefore not filled into + the request will be reset to their default. If this is unwanted + behavior, a specific service may require a client to always specify + a field mask, producing an error if not. + + As with get operations, the location of the resource which + describes the updated values in the request message depends on the + operation kind. In any case, the effect of the field mask is + required to be honored by the API. + + ## Considerations for HTTP REST + + The HTTP kind of an update operation which uses a field mask must + be set to PATCH instead of PUT in order to satisfy HTTP semantics + (PUT must only be used for full updates). + + # JSON Encoding of Field Masks + + In JSON, a field mask is encoded as a single string where paths are + separated by a comma. Fields name in each path are converted + to/from lower-camel naming conventions. + + As an example, consider the following message declarations: + + message Profile { + User user = 1; + Photo photo = 2; + } + message User { + string display_name = 1; + string address = 2; + } + + In proto a field mask for `Profile` may look as such: + + mask { + paths: "user.display_name" + paths: "photo" + } + + In JSON, the same mask is represented as below: + + { + mask: "user.displayName,photo" + } + + # Field Masks and Oneof Fields + + Field masks treat fields in oneofs just as regular fields. Consider the + following message: + + message SampleMessage { + oneof test_oneof { + string name = 4; + SubMessage sub_message = 9; + } + } + + The field mask can be: + + mask { + paths: "name" + } + + Or: + + mask { + paths: "sub_message" + } + + Note that oneof type names ("test_oneof" in this case) cannot be used in + paths. + + ## Field Mask Verification + + The implementation of any API method which has a FieldMask type field in the + request should verify the included field paths, and return an + `INVALID_ARGUMENT` error if any path is unmappable. + + + + Field number for the "paths" field. + + + + The set of field mask paths. + + + + + Converts a field mask specified by paths to a string. + + + If the value is a normalized duration in the range described in field_mask.proto, + is ignored. Otherwise, if the parameter is true, + a JSON object with a warning is returned; if it is false, an is thrown. + + Paths in the field mask + Determines the handling of non-normalized values + The represented field mask is invalid, and is false. + + + + Returns a string representation of this for diagnostic purposes. + + + Normally the returned value will be a JSON string value (including leading and trailing quotes) but + when the value is non-normalized or out of range, a JSON object representation will be returned + instead, including a warning. This is to avoid exceptions being thrown when trying to + diagnose problems - the regular JSON formatter will still throw an exception for non-normalized + values. + + A string representation of this value. + + + + Parses from a string to a FieldMask. + + + + + Parses from a string to a FieldMask and validates all field paths. + + The type to validate the field paths against. + + + + Constructs a FieldMask for a list of field paths in a certain type. + + The type to validate the field paths against. + + + + Constructs a FieldMask from the passed field numbers. + + The type to validate the field paths against. + + + + Constructs a FieldMask from the passed field numbers. + + The type to validate the field paths against. + + + + Checks whether the given path is valid for a field mask. + + true if the path is valid; false otherwise + + + + Checks whether paths in a given fields mask are valid. + + The type to validate the field paths against. + + + + Checks whether paths in a given fields mask are valid. + + + + + Checks whether a given field path is valid. + + The type to validate the field paths against. + + + + Checks whether paths in a given fields mask are valid. + + + + + Converts this FieldMask to its canonical form. In the canonical form of a + FieldMask, all field paths are sorted alphabetically and redundant field + paths are removed. + + + + + Creates a union of two or more FieldMasks. + + + + + Calculates the intersection of two FieldMasks. + + + + + Merges fields specified by this FieldMask from one message to another with the + specified merge options. + + + + + Merges fields specified by this FieldMask from one message to another. + + + + + Options to customize merging behavior. + + + + + Whether to replace message fields(i.e., discard existing content in + destination message fields) when merging. + Default behavior is to merge the source message field into the + destination message field. + + + + + Whether to replace repeated fields (i.e., discard existing content in + destination repeated fields) when merging. + Default behavior is to append elements from source repeated field to the + destination repeated field. + + + + + Whether to replace primitive (non-repeated and non-message) fields in + destination message fields with the source primitive fields (i.e., if the + field is set in the source, the value is copied to the + destination; if the field is unset in the source, the field is cleared + from the destination) when merging. + + Default behavior is to always set the value of the source primitive + field to the destination primitive field, and if the source field is + unset, the default value of the source field is copied to the + destination. + + + + Holder for reflection information generated from google/protobuf/source_context.proto + + + File descriptor for google/protobuf/source_context.proto + + + + `SourceContext` represents information about the source of a + protobuf element, like the file in which it is defined. + + + + Field number for the "file_name" field. + + + + The path-qualified name of the .proto file that contained the associated + protobuf element. For example: `"google/protobuf/source_context.proto"`. + + + + Holder for reflection information generated from google/protobuf/struct.proto + + + File descriptor for google/protobuf/struct.proto + + + + `NullValue` is a singleton enumeration to represent the null value for the + `Value` type union. + + The JSON representation for `NullValue` is JSON `null`. + + + + + Null value. + + + + + `Struct` represents a structured data value, consisting of fields + which map to dynamically typed values. In some languages, `Struct` + might be supported by a native representation. For example, in + scripting languages like JS a struct is represented as an + object. The details of that representation are described together + with the proto support for the language. + + The JSON representation for `Struct` is JSON object. + + + + Field number for the "fields" field. + + + + Unordered map of dynamically typed values. + + + + + `Value` represents a dynamically typed value which can be either + null, a number, a string, a boolean, a recursive struct value, or a + list of values. A producer of value is expected to set one of these + variants. Absence of any variant indicates an error. + + The JSON representation for `Value` is JSON value. + + + + Field number for the "null_value" field. + + + + Represents a null value. + + + + Field number for the "number_value" field. + + + + Represents a double value. + + + + Field number for the "string_value" field. + + + + Represents a string value. + + + + Field number for the "bool_value" field. + + + + Represents a boolean value. + + + + Field number for the "struct_value" field. + + + + Represents a structured value. + + + + Field number for the "list_value" field. + + + + Represents a repeated `Value`. + + + + Enum of possible cases for the "kind" oneof. + + + + Convenience method to create a Value message with a string value. + + Value to set for the StringValue property. + A newly-created Value message with the given value. + + + + Convenience method to create a Value message with a number value. + + Value to set for the NumberValue property. + A newly-created Value message with the given value. + + + + Convenience method to create a Value message with a Boolean value. + + Value to set for the BoolValue property. + A newly-created Value message with the given value. + + + + Convenience method to create a Value message with a null initial value. + + A newly-created Value message a null initial value. + + + + Convenience method to create a Value message with an initial list of values. + + The values provided are not cloned; the references are copied directly. + A newly-created Value message an initial list value. + + + + Convenience method to create a Value message with an initial struct value + + The value provided is not cloned; the reference is copied directly. + A newly-created Value message an initial struct value. + + + + `ListValue` is a wrapper around a repeated field of values. + + The JSON representation for `ListValue` is JSON array. + + + + Field number for the "values" field. + + + + Repeated field of dynamically typed values. + + + + + Extension methods on BCL time-related types, converting to protobuf types. + + + + + Converts the given to a . + + The date and time to convert to a timestamp. + The value has a other than Utc. + The converted timestamp. + + + + Converts the given to a + + The offset is taken into consideration when converting the value (so the same instant in time + is represented) but is not a separate part of the resulting value. In other words, there is no + roundtrip operation to retrieve the original DateTimeOffset. + The date and time (with UTC offset) to convert to a timestamp. + The converted timestamp. + + + + Converts the given to a . + + The time span to convert. + The converted duration. + + + Holder for reflection information generated from google/protobuf/timestamp.proto + + + File descriptor for google/protobuf/timestamp.proto + + + + A Timestamp represents a point in time independent of any time zone or local + calendar, encoded as a count of seconds and fractions of seconds at + nanosecond resolution. The count is relative to an epoch at UTC midnight on + January 1, 1970, in the proleptic Gregorian calendar which extends the + Gregorian calendar backwards to year one. + + All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap + second table is needed for interpretation, using a [24-hour linear + smear](https://developers.google.com/time/smear). + + The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By + restricting to that range, we ensure that we can convert to and from [RFC + 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings. + + # Examples + + Example 1: Compute Timestamp from POSIX `time()`. + + Timestamp timestamp; + timestamp.set_seconds(time(NULL)); + timestamp.set_nanos(0); + + Example 2: Compute Timestamp from POSIX `gettimeofday()`. + + struct timeval tv; + gettimeofday(&tv, NULL); + + Timestamp timestamp; + timestamp.set_seconds(tv.tv_sec); + timestamp.set_nanos(tv.tv_usec * 1000); + + Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. + + FILETIME ft; + GetSystemTimeAsFileTime(&ft); + UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; + + // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z + // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. + Timestamp timestamp; + timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); + timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); + + Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. + + long millis = System.currentTimeMillis(); + + Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) + .setNanos((int) ((millis % 1000) * 1000000)).build(); + + Example 5: Compute Timestamp from Java `Instant.now()`. + + Instant now = Instant.now(); + + Timestamp timestamp = + Timestamp.newBuilder().setSeconds(now.getEpochSecond()) + .setNanos(now.getNano()).build(); + + Example 6: Compute Timestamp from current time in Python. + + timestamp = Timestamp() + timestamp.GetCurrentTime() + + # JSON Mapping + + In JSON format, the Timestamp type is encoded as a string in the + [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the + format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" + where {year} is always expressed using four digits while {month}, {day}, + {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional + seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), + are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone + is required. A proto3 JSON serializer should always use UTC (as indicated by + "Z") when printing the Timestamp type and a proto3 JSON parser should be + able to accept both UTC and other timezones (as indicated by an offset). + + For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past + 01:30 UTC on January 15, 2017. + + In JavaScript, one can convert a Date object to this format using the + standard + [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) + method. In Python, a standard `datetime.datetime` object can be converted + to this format using + [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with + the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use + the Joda Time's [`ISODateTimeFormat.dateTime()`]( + http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D + ) to obtain a formatter capable of generating timestamps in this format. + + + + Field number for the "seconds" field. + + + + Represents seconds of UTC time since Unix epoch + 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to + 9999-12-31T23:59:59Z inclusive. + + + + Field number for the "nanos" field. + + + + Non-negative fractions of a second at nanosecond resolution. Negative + second values with fractions must still have non-negative nanos values + that count forward in time. Must be from 0 to 999,999,999 + inclusive. + + + + + Returns the difference between one and another, as a . + + The timestamp to subtract from. Must not be null. + The timestamp to subtract. Must not be null. + The difference between the two specified timestamps. + + + + Adds a to a , to obtain another Timestamp. + + The timestamp to add the duration to. Must not be null. + The duration to add. Must not be null. + The result of adding the duration to the timestamp. + + + + Subtracts a from a , to obtain another Timestamp. + + The timestamp to subtract the duration from. Must not be null. + The duration to subtract. + The result of subtracting the duration from the timestamp. + + + + Converts this timestamp into a . + + + The resulting DateTime will always have a Kind of Utc. + If the timestamp is not a precise number of ticks, it will be truncated towards the start + of time. For example, a timestamp with a value of 99 will result in a + value precisely on a second. + + This timestamp as a DateTime. + The timestamp contains invalid values; either it is + incorrectly normalized or is outside the valid range. + + + + Converts this timestamp into a . + + + The resulting DateTimeOffset will always have an Offset of zero. + If the timestamp is not a precise number of ticks, it will be truncated towards the start + of time. For example, a timestamp with a value of 99 will result in a + value precisely on a second. + + This timestamp as a DateTimeOffset. + The timestamp contains invalid values; either it is + incorrectly normalized or is outside the valid range. + + + + Converts the specified to a . + + + The Kind of is not DateTimeKind.Utc. + The converted timestamp. + + + + Converts the given to a + + The offset is taken into consideration when converting the value (so the same instant in time + is represented) but is not a separate part of the resulting value. In other words, there is no + roundtrip operation to retrieve the original DateTimeOffset. + The date and time (with UTC offset) to convert to a timestamp. + The converted timestamp. + + + + Converts a timestamp specified in seconds/nanoseconds to a string. + + + If the value is a normalized duration in the range described in timestamp.proto, + is ignored. Otherwise, if the parameter is true, + a JSON object with a warning is returned; if it is false, an is thrown. + + Seconds portion of the duration. + Nanoseconds portion of the duration. + Determines the handling of non-normalized values + The represented duration is invalid, and is false. + + + + Given another timestamp, returns 0 if the timestamps are equivalent, -1 if this timestamp precedes the other, and 1 otherwise + + + Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. + + Timestamp to compare + an integer indicating whether this timestamp precedes or follows the other + + + + Compares two timestamps and returns whether the first is less than (chronologically precedes) the second + + + Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. + + + + true if a precedes b + + + + Compares two timestamps and returns whether the first is greater than (chronologically follows) the second + + + Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. + + + + true if a follows b + + + + Compares two timestamps and returns whether the first is less than (chronologically precedes) the second + + + Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. + + + + true if a precedes b + + + + Compares two timestamps and returns whether the first is greater than (chronologically follows) the second + + + Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. + + + + true if a follows b + + + + Returns whether two timestamps are equivalent + + + Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. + + + + true if the two timestamps refer to the same nanosecond + + + + Returns whether two timestamps differ + + + Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. + + + + true if the two timestamps differ + + + + Returns a string representation of this for diagnostic purposes. + + + Normally the returned value will be a JSON string value (including leading and trailing quotes) but + when the value is non-normalized or out of range, a JSON object representation will be returned + instead, including a warning. This is to avoid exceptions being thrown when trying to + diagnose problems - the regular JSON formatter will still throw an exception for non-normalized + values. + + A string representation of this value. + + + Holder for reflection information generated from google/protobuf/type.proto + + + File descriptor for google/protobuf/type.proto + + + + The syntax in which a protocol buffer element is defined. + + + + + Syntax `proto2`. + + + + + Syntax `proto3`. + + + + + A protocol buffer message type. + + + + Field number for the "name" field. + + + + The fully qualified message name. + + + + Field number for the "fields" field. + + + + The list of fields. + + + + Field number for the "oneofs" field. + + + + The list of types appearing in `oneof` definitions in this type. + + + + Field number for the "options" field. + + + + The protocol buffer options. + + + + Field number for the "source_context" field. + + + + The source context. + + + + Field number for the "syntax" field. + + + + The source syntax. + + + + + A single field of a message type. + + + + Field number for the "kind" field. + + + + The field type. + + + + Field number for the "cardinality" field. + + + + The field cardinality. + + + + Field number for the "number" field. + + + + The field number. + + + + Field number for the "name" field. + + + + The field name. + + + + Field number for the "type_url" field. + + + + The field type URL, without the scheme, for message or enumeration + types. Example: `"type.googleapis.com/google.protobuf.Timestamp"`. + + + + Field number for the "oneof_index" field. + + + + The index of the field type in `Type.oneofs`, for message or enumeration + types. The first type has index 1; zero means the type is not in the list. + + + + Field number for the "packed" field. + + + + Whether to use alternative packed wire representation. + + + + Field number for the "options" field. + + + + The protocol buffer options. + + + + Field number for the "json_name" field. + + + + The field JSON name. + + + + Field number for the "default_value" field. + + + + The string value of the default value of this field. Proto2 syntax only. + + + + Container for nested types declared in the Field message type. + + + + Basic field types. + + + + + Field type unknown. + + + + + Field type double. + + + + + Field type float. + + + + + Field type int64. + + + + + Field type uint64. + + + + + Field type int32. + + + + + Field type fixed64. + + + + + Field type fixed32. + + + + + Field type bool. + + + + + Field type string. + + + + + Field type group. Proto2 syntax only, and deprecated. + + + + + Field type message. + + + + + Field type bytes. + + + + + Field type uint32. + + + + + Field type enum. + + + + + Field type sfixed32. + + + + + Field type sfixed64. + + + + + Field type sint32. + + + + + Field type sint64. + + + + + Whether a field is optional, required, or repeated. + + + + + For fields with unknown cardinality. + + + + + For optional fields. + + + + + For required fields. Proto2 syntax only. + + + + + For repeated fields. + + + + + Enum type definition. + + + + Field number for the "name" field. + + + + Enum type name. + + + + Field number for the "enumvalue" field. + + + + Enum value definitions. + + + + Field number for the "options" field. + + + + Protocol buffer options. + + + + Field number for the "source_context" field. + + + + The source context. + + + + Field number for the "syntax" field. + + + + The source syntax. + + + + + Enum value definition. + + + + Field number for the "name" field. + + + + Enum value name. + + + + Field number for the "number" field. + + + + Enum value number. + + + + Field number for the "options" field. + + + + Protocol buffer options. + + + + + A protocol buffer option, which can be attached to a message, field, + enumeration, etc. + + + + Field number for the "name" field. + + + + The option's name. For protobuf built-in options (options defined in + descriptor.proto), this is the short name. For example, `"map_entry"`. + For custom options, it should be the fully-qualified name. For example, + `"google.api.http"`. + + + + Field number for the "value" field. + + + + The option's value packed in an Any message. If the value is a primitive, + the corresponding wrapper type defined in google/protobuf/wrappers.proto + should be used. If the value is an enum, it should be stored as an int32 + value using the google.protobuf.Int32Value type. + + + + Holder for reflection information generated from google/protobuf/wrappers.proto + + + File descriptor for google/protobuf/wrappers.proto + + + + Field number for the single "value" field in all wrapper types. + + + + + Wrapper message for `double`. + + The JSON representation for `DoubleValue` is JSON number. + + + + Field number for the "value" field. + + + + The double value. + + + + + Wrapper message for `float`. + + The JSON representation for `FloatValue` is JSON number. + + + + Field number for the "value" field. + + + + The float value. + + + + + Wrapper message for `int64`. + + The JSON representation for `Int64Value` is JSON string. + + + + Field number for the "value" field. + + + + The int64 value. + + + + + Wrapper message for `uint64`. + + The JSON representation for `UInt64Value` is JSON string. + + + + Field number for the "value" field. + + + + The uint64 value. + + + + + Wrapper message for `int32`. + + The JSON representation for `Int32Value` is JSON number. + + + + Field number for the "value" field. + + + + The int32 value. + + + + + Wrapper message for `uint32`. + + The JSON representation for `UInt32Value` is JSON number. + + + + Field number for the "value" field. + + + + The uint32 value. + + + + + Wrapper message for `bool`. + + The JSON representation for `BoolValue` is JSON `true` and `false`. + + + + Field number for the "value" field. + + + + The bool value. + + + + + Wrapper message for `string`. + + The JSON representation for `StringValue` is JSON string. + + + + Field number for the "value" field. + + + + The string value. + + + + + Wrapper message for `bytes`. + + The JSON representation for `BytesValue` is JSON string. + + + + Field number for the "value" field. + + + + The bytes value. + + + + + This class is used internally by the Protocol Buffer Library and generated + message implementations. It is public only for the sake of those generated + messages. Others should not use this class directly. + + This class contains constants and helper functions useful for dealing with + the Protocol Buffer wire format. + + + + + + Wire types within protobuf encoding. + + + + + Variable-length integer. + + + + + A fixed-length 64-bit value. + + + + + A length-delimited value, i.e. a length followed by that many bytes of data. + + + + + A "start group" value + + + + + An "end group" value + + + + + A fixed-length 32-bit value. + + + + + Given a tag value, determines the wire type (lower 3 bits). + + + + + Given a tag value, determines the field number (the upper 29 bits). + + + + + Makes a tag value given a field number and wire type. + + + + + Abstraction for writing to a steam / IBufferWriter + + + + + Initialize an instance with a coded output stream. + This approach is faster than using a constructor because the instance to initialize is passed by reference + and we can write directly into it without copying. + + + + + Initialize an instance with a buffer writer. + This approach is faster than using a constructor because the instance to initialize is passed by reference + and we can write directly into it without copying. + + + + + Initialize an instance with a buffer represented by a single span (i.e. buffer cannot be refreshed) + This approach is faster than using a constructor because the instance to initialize is passed by reference + and we can write directly into it without copying. + + + + + Verifies that SpaceLeft returns zero. + + + + + If writing to a flat array, returns the space left in the array. Otherwise, + throws an InvalidOperationException. + + + + + An opaque struct that represents the current serialization state and is passed along + as the serialization proceeds. + All the public methods are intended to be invoked only by the generated code, + users should never invoke them directly. + + + + + Creates a WriteContext instance from CodedOutputStream. + WARNING: internally this copies the CodedOutputStream's state, so after done with the WriteContext, + the CodedOutputStream's state needs to be updated. + + + + + Writes a double field value, without a tag. + + The value to write + + + + Writes a float field value, without a tag. + + The value to write + + + + Writes a uint64 field value, without a tag. + + The value to write + + + + Writes an int64 field value, without a tag. + + The value to write + + + + Writes an int32 field value, without a tag. + + The value to write + + + + Writes a fixed64 field value, without a tag. + + The value to write + + + + Writes a fixed32 field value, without a tag. + + The value to write + + + + Writes a bool field value, without a tag. + + The value to write + + + + Writes a string field value, without a tag. + The data is length-prefixed. + + The value to write + + + + Writes a message, without a tag. + The data is length-prefixed. + + The value to write + + + + Writes a group, without a tag, to the stream. + + The value to write + + + + Write a byte string, without a tag, to the stream. + The data is length-prefixed. + + The value to write + + + + Writes a uint32 value, without a tag. + + The value to write + + + + Writes an enum value, without a tag. + + The value to write + + + + Writes an sfixed32 value, without a tag. + + The value to write. + + + + Writes an sfixed64 value, without a tag. + + The value to write + + + + Writes an sint32 value, without a tag. + + The value to write + + + + Writes an sint64 value, without a tag. + + The value to write + + + + Writes a length (in bytes) for length-delimited data. + + + This method simply writes a rawint, but exists for clarity in calling code. + + Length value, in bytes. + + + + Encodes and writes a tag. + + The number of the field to write the tag for + The wire format type of the tag to write + + + + Writes an already-encoded tag. + + The encoded tag + + + + Writes the given single-byte tag. + + The encoded tag + + + + Writes the given two-byte tag. + + The first byte of the encoded tag + The second byte of the encoded tag + + + + Writes the given three-byte tag. + + The first byte of the encoded tag + The second byte of the encoded tag + The third byte of the encoded tag + + + + Writes the given four-byte tag. + + The first byte of the encoded tag + The second byte of the encoded tag + The third byte of the encoded tag + The fourth byte of the encoded tag + + + + Writes the given five-byte tag. + + The first byte of the encoded tag + The second byte of the encoded tag + The third byte of the encoded tag + The fourth byte of the encoded tag + The fifth byte of the encoded tag + + + + Primitives for encoding protobuf wire format. + + + + + Writes a double field value, without a tag, to the stream. + + + + + Writes a float field value, without a tag, to the stream. + + + + + Writes a uint64 field value, without a tag, to the stream. + + + + + Writes an int64 field value, without a tag, to the stream. + + + + + Writes an int32 field value, without a tag, to the stream. + + + + + Writes a fixed64 field value, without a tag, to the stream. + + + + + Writes a fixed32 field value, without a tag, to the stream. + + + + + Writes a bool field value, without a tag, to the stream. + + + + + Writes a string field value, without a tag, to the stream. + The data is length-prefixed. + + + + + Given a QWORD which represents a buffer of 4 ASCII chars in machine-endian order, + narrows each WORD to a BYTE, then writes the 4-byte result to the output buffer + also in machine-endian order. + + + + + Write a byte string, without a tag, to the stream. + The data is length-prefixed. + + + + + Writes a uint32 value, without a tag, to the stream. + + + + + Writes an enum value, without a tag, to the stream. + + + + + Writes an sfixed32 value, without a tag, to the stream. + + + + + Writes an sfixed64 value, without a tag, to the stream. + + + + + Writes an sint32 value, without a tag, to the stream. + + + + + Writes an sint64 value, without a tag, to the stream. + + + + + Writes a length (in bytes) for length-delimited data. + + + This method simply writes a rawint, but exists for clarity in calling code. + + + + + Writes a 32 bit value as a varint. The fast route is taken when + there's enough buffer space left to whizz through without checking + for each byte; otherwise, we resort to calling WriteRawByte each time. + + + + + Writes out an array of bytes. + + + + + Writes out part of an array of bytes. + + + + + Writes out part of an array of bytes. + + + + + Encodes and writes a tag. + + + + + Writes an already-encoded tag. + + + + + Writes the given single-byte tag directly to the stream. + + + + + Writes the given two-byte tag directly to the stream. + + + + + Writes the given three-byte tag directly to the stream. + + + + + Writes the given four-byte tag directly to the stream. + + + + + Writes the given five-byte tag directly to the stream. + + + + + Encode a 32-bit value with ZigZag encoding. + + + ZigZag encodes signed integers into values that can be efficiently + encoded with varint. (Otherwise, negative values must be + sign-extended to 64 bits to be varint encoded, thus always taking + 10 bytes on the wire.) + + + + + Encode a 64-bit value with ZigZag encoding. + + + ZigZag encodes signed integers into values that can be efficiently + encoded with varint. (Otherwise, negative values must be + sign-extended to 64 bits to be varint encoded, thus always taking + 10 bytes on the wire.) + + + + + Writing messages / groups. + + + + + Writes a message, without a tag. + The data is length-prefixed. + + + + + Writes a group, without a tag. + + + + + Writes a message, without a tag. + Message will be written without a length prefix. + + +
+
diff --git a/Assets/ARDK/Plugins/Niantic.Protobufs/Google.Protobuf.3.19.4/net45/Niantic.Google.Protobuf.xml.meta b/Assets/ARDK/Plugins/Niantic.Protobufs/Google.Protobuf.3.19.4/net45/Niantic.Google.Protobuf.xml.meta new file mode 100644 index 0000000..0c77a5f --- /dev/null +++ b/Assets/ARDK/Plugins/Niantic.Protobufs/Google.Protobuf.3.19.4/net45/Niantic.Google.Protobuf.xml.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 0589e59b454e047ab90a42eb580fd345 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/Niantic.Protobufs/System.Buffers.4.4.0.meta b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Buffers.4.4.0.meta new file mode 100644 index 0000000..3c27b28 --- /dev/null +++ b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Buffers.4.4.0.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d3c7167f97c504d308e3bedeb2dea5a7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/Niantic.Protobufs/System.Buffers.4.4.0/netstandard2.0.meta b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Buffers.4.4.0/netstandard2.0.meta new file mode 100644 index 0000000..c384c89 --- /dev/null +++ b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Buffers.4.4.0/netstandard2.0.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d81219f5ed364487fb594a80b2276c60 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/Niantic.Protobufs/System.Buffers.4.4.0/netstandard2.0/Niantic.System.Buffers.dll b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Buffers.4.4.0/netstandard2.0/Niantic.System.Buffers.dll new file mode 100644 index 0000000..25548ab Binary files /dev/null and b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Buffers.4.4.0/netstandard2.0/Niantic.System.Buffers.dll differ diff --git a/Assets/ARDK/Plugins/Niantic.Protobufs/System.Buffers.4.4.0/netstandard2.0/Niantic.System.Buffers.dll.meta b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Buffers.4.4.0/netstandard2.0/Niantic.System.Buffers.dll.meta new file mode 100644 index 0000000..c7ecda1 --- /dev/null +++ b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Buffers.4.4.0/netstandard2.0/Niantic.System.Buffers.dll.meta @@ -0,0 +1,86 @@ +fileFormatVersion: 2 +guid: 7d15b4cd5bcad4f42b2fed294e16c0bc +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 1 + validateReferences: 1 + platformData: + - first: + : Any + second: + enabled: 0 + settings: + Exclude Android: 0 + Exclude Editor: 0 + Exclude Linux64: 0 + Exclude OSXUniversal: 0 + Exclude Win: 0 + Exclude Win64: 0 + Exclude iOS: 0 + - first: + Android: Android + second: + enabled: 1 + settings: + CPU: ARMv7 + - first: + Any: + second: + enabled: 1 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Standalone: Linux64 + second: + enabled: 1 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 1 + settings: + CPU: None + - first: + Standalone: Win + second: + enabled: 1 + settings: + CPU: x86 + - first: + Standalone: Win64 + second: + enabled: 1 + settings: + CPU: x86_64 + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + CPU: AnyCPU + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/Niantic.Protobufs/System.Buffers.4.4.0/netstandard2.0/Niantic.System.Buffers.xml b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Buffers.4.4.0/netstandard2.0/Niantic.System.Buffers.xml new file mode 100644 index 0000000..d3d239e --- /dev/null +++ b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Buffers.4.4.0/netstandard2.0/Niantic.System.Buffers.xml @@ -0,0 +1,39 @@ + + + + System.Buffers + + + + Provides a resource pool that enables reusing instances of type . + The type of the objects that are in the resource pool. + + + Initializes a new instance of the class. + + + Creates a new instance of the class. + A new instance of the class. + + + Creates a new instance of the class using the specifed configuration. + The maximum length of an array instance that may be stored in the pool. + The maximum number of array instances that may be stored in each bucket in the pool. The pool groups arrays of similar lengths into buckets for faster access. + A new instance of the class with the specified configuration. + + + Retrieves a buffer that is at least the requested length. + The minimum length of the array. + An array of type that is at least minimumLength in length. + + + Returns an array to the pool that was previously obtained using the method on the same instance. + A buffer to return to the pool that was previously obtained using the method. + Indicates whether the contents of the buffer should be cleared before reuse. If bufferLength is set to true, and if the pool will store the buffer to enable subsequent reuse, the method will clear the array of its contents so that a subsequent caller using the method will not see the content of the previous caller. If bufferLength is set to false or if the pool will release the buffer, the array's contents are left unchanged. + + + Gets a shared instance. + A shared instance. + + + \ No newline at end of file diff --git a/Assets/ARDK/Plugins/Niantic.Protobufs/System.Buffers.4.4.0/netstandard2.0/Niantic.System.Buffers.xml.meta b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Buffers.4.4.0/netstandard2.0/Niantic.System.Buffers.xml.meta new file mode 100644 index 0000000..102d185 --- /dev/null +++ b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Buffers.4.4.0/netstandard2.0/Niantic.System.Buffers.xml.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ecded3c989b824715a54bf89f7807677 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/Niantic.Protobufs/System.Memory.4.5.3.meta b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Memory.4.5.3.meta new file mode 100644 index 0000000..6365540 --- /dev/null +++ b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Memory.4.5.3.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b2d549ae292e64ac6b06cec1294bbe46 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/Niantic.Protobufs/System.Memory.4.5.3/netstandard2.0.meta b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Memory.4.5.3/netstandard2.0.meta new file mode 100644 index 0000000..a0e969a --- /dev/null +++ b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Memory.4.5.3/netstandard2.0.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 475bab86b8f7e4c88a7220f2c62edc73 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/Niantic.Protobufs/System.Memory.4.5.3/netstandard2.0/Niantic.System.Memory.dll b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Memory.4.5.3/netstandard2.0/Niantic.System.Memory.dll new file mode 100644 index 0000000..071d6d0 Binary files /dev/null and b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Memory.4.5.3/netstandard2.0/Niantic.System.Memory.dll differ diff --git a/Assets/ARDK/Plugins/Niantic.Protobufs/System.Memory.4.5.3/netstandard2.0/Niantic.System.Memory.dll.meta b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Memory.4.5.3/netstandard2.0/Niantic.System.Memory.dll.meta new file mode 100644 index 0000000..f68b9d0 --- /dev/null +++ b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Memory.4.5.3/netstandard2.0/Niantic.System.Memory.dll.meta @@ -0,0 +1,86 @@ +fileFormatVersion: 2 +guid: 8847b3efeda6c4f1b8ed8655c3b9ebe9 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 1 + validateReferences: 1 + platformData: + - first: + : Any + second: + enabled: 0 + settings: + Exclude Android: 0 + Exclude Editor: 0 + Exclude Linux64: 0 + Exclude OSXUniversal: 0 + Exclude Win: 0 + Exclude Win64: 0 + Exclude iOS: 0 + - first: + Android: Android + second: + enabled: 1 + settings: + CPU: ARMv7 + - first: + Any: + second: + enabled: 1 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Standalone: Linux64 + second: + enabled: 1 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 1 + settings: + CPU: None + - first: + Standalone: Win + second: + enabled: 1 + settings: + CPU: x86 + - first: + Standalone: Win64 + second: + enabled: 1 + settings: + CPU: x86_64 + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + CPU: AnyCPU + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/Niantic.Protobufs/System.Memory.4.5.3/netstandard2.0/Niantic.System.Memory.xml b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Memory.4.5.3/netstandard2.0/Niantic.System.Memory.xml new file mode 100644 index 0000000..4d12fd7 --- /dev/null +++ b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Memory.4.5.3/netstandard2.0/Niantic.System.Memory.xml @@ -0,0 +1,355 @@ + + + System.Memory + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assets/ARDK/Plugins/Niantic.Protobufs/System.Memory.4.5.3/netstandard2.0/Niantic.System.Memory.xml.meta b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Memory.4.5.3/netstandard2.0/Niantic.System.Memory.xml.meta new file mode 100644 index 0000000..821b341 --- /dev/null +++ b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Memory.4.5.3/netstandard2.0/Niantic.System.Memory.xml.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: cd562b3d1530645488cedad2a769d72a +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/Niantic.Protobufs/System.Numerics.Vectors.4.4.0.meta b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Numerics.Vectors.4.4.0.meta new file mode 100644 index 0000000..a001379 --- /dev/null +++ b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Numerics.Vectors.4.4.0.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3cc2a6dfe285c4c7da05ba7fe813ca86 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/Niantic.Protobufs/System.Numerics.Vectors.4.4.0/netstandard2.0.meta b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Numerics.Vectors.4.4.0/netstandard2.0.meta new file mode 100644 index 0000000..4864851 --- /dev/null +++ b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Numerics.Vectors.4.4.0/netstandard2.0.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a8a1a1543a876472587df7ae2d601b00 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/Niantic.Protobufs/System.Numerics.Vectors.4.4.0/netstandard2.0/Niantic.System.Numerics.Vectors.dll b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Numerics.Vectors.4.4.0/netstandard2.0/Niantic.System.Numerics.Vectors.dll new file mode 100644 index 0000000..a8fcee8 Binary files /dev/null and b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Numerics.Vectors.4.4.0/netstandard2.0/Niantic.System.Numerics.Vectors.dll differ diff --git a/Assets/ARDK/Plugins/Niantic.Protobufs/System.Numerics.Vectors.4.4.0/netstandard2.0/Niantic.System.Numerics.Vectors.dll.meta b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Numerics.Vectors.4.4.0/netstandard2.0/Niantic.System.Numerics.Vectors.dll.meta new file mode 100644 index 0000000..d802589 --- /dev/null +++ b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Numerics.Vectors.4.4.0/netstandard2.0/Niantic.System.Numerics.Vectors.dll.meta @@ -0,0 +1,86 @@ +fileFormatVersion: 2 +guid: b59966061ab4648e4a568d99f2a56aab +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 1 + validateReferences: 1 + platformData: + - first: + : Any + second: + enabled: 0 + settings: + Exclude Android: 0 + Exclude Editor: 0 + Exclude Linux64: 0 + Exclude OSXUniversal: 0 + Exclude Win: 0 + Exclude Win64: 0 + Exclude iOS: 0 + - first: + Android: Android + second: + enabled: 1 + settings: + CPU: ARMv7 + - first: + Any: + second: + enabled: 1 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Standalone: Linux64 + second: + enabled: 1 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 1 + settings: + CPU: None + - first: + Standalone: Win + second: + enabled: 1 + settings: + CPU: x86 + - first: + Standalone: Win64 + second: + enabled: 1 + settings: + CPU: x86_64 + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + CPU: AnyCPU + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/Niantic.Protobufs/System.Numerics.Vectors.4.4.0/netstandard2.0/Niantic.System.Numerics.Vectors.xml b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Numerics.Vectors.4.4.0/netstandard2.0/Niantic.System.Numerics.Vectors.xml new file mode 100644 index 0000000..5129793 --- /dev/null +++ b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Numerics.Vectors.4.4.0/netstandard2.0/Niantic.System.Numerics.Vectors.xml @@ -0,0 +1,2597 @@ + + + + System.Numerics.Vectors + + + + Represents a 3x2 matrix. + + + Creates a 3x2 matrix from the specified components. + The value to assign to the first element in the first row. + The value to assign to the second element in the first row. + The value to assign to the first element in the second row. + The value to assign to the second element in the second row. + The value to assign to the first element in the third row. + The value to assign to the second element in the third row. + + + Adds each element in one matrix with its corresponding element in a second matrix. + The first matrix. + The second matrix. + The matrix that contains the summed values of value1 and value2. + + + Creates a rotation matrix using the given rotation in radians. + The amount of rotation, in radians. + The rotation matrix. + + + Creates a rotation matrix using the specified rotation in radians and a center point. + The amount of rotation, in radians. + The center point. + The rotation matrix. + + + Creates a scaling matrix from the specified X and Y components. + The value to scale by on the X axis. + The value to scale by on the Y axis. + The scaling matrix. + + + Creates a scaling matrix that scales uniformly with the specified scale with an offset from the specified center. + The uniform scale to use. + The center offset. + The scaling matrix. + + + Creates a scaling matrix that is offset by a given center point. + The value to scale by on the X axis. + The value to scale by on the Y axis. + The center point. + The scaling matrix. + + + Creates a scaling matrix that scales uniformly with the given scale. + The uniform scale to use. + The scaling matrix. + + + Creates a scaling matrix from the specified vector scale. + The scale to use. + The scaling matrix. + + + Creates a scaling matrix from the specified vector scale with an offset from the specified center point. + The scale to use. + The center offset. + The scaling matrix. + + + Creates a skew matrix from the specified angles in radians. + The X angle, in radians. + The Y angle, in radians. + The skew matrix. + + + Creates a skew matrix from the specified angles in radians and a center point. + The X angle, in radians. + The Y angle, in radians. + The center point. + The skew matrix. + + + Creates a translation matrix from the specified 2-dimensional vector. + The translation position. + The translation matrix. + + + Creates a translation matrix from the specified X and Y components. + The X position. + The Y position. + The translation matrix. + + + Returns a value that indicates whether this instance and another 3x2 matrix are equal. + The other matrix. + true if the two matrices are equal; otherwise, false. + + + Returns a value that indicates whether this instance and a specified object are equal. + The object to compare with the current instance. + true if the current instance and obj are equal; otherwise, false```. If <code data-dev-comment-type="paramref">obj</code> isnull, the method returnsfalse`. + + + Calculates the determinant for this matrix. + The determinant. + + + Returns the hash code for this instance. + The hash code. + + + Gets the multiplicative identity matrix. + The multiplicative identify matrix. + + + Inverts the specified matrix. The return value indicates whether the operation succeeded. + The matrix to invert. + When this method returns, contains the inverted matrix if the operation succeeded. + true if matrix was converted successfully; otherwise, false. + + + Indicates whether the current matrix is the identity matrix. + true if the current matrix is the identity matrix; otherwise, false. + + + Performs a linear interpolation from one matrix to a second matrix based on a value that specifies the weighting of the second matrix. + The first matrix. + The second matrix. + The relative weighting of matrix2. + The interpolated matrix. + + + The first element of the first row. + + + + The second element of the first row. + + + + The first element of the second row. + + + + The second element of the second row. + + + + The first element of the third row. + + + + The second element of the third row. + + + + Returns the matrix that results from multiplying two matrices together. + The first matrix. + The second matrix. + The product matrix. + + + Returns the matrix that results from scaling all the elements of a specified matrix by a scalar factor. + The matrix to scale. + The scaling value to use. + The scaled matrix. + + + Negates the specified matrix by multiplying all its values by -1. + The matrix to negate. + The negated matrix. + + + Adds each element in one matrix with its corresponding element in a second matrix. + The first matrix. + The second matrix. + The matrix that contains the summed values. + + + Returns a value that indicates whether the specified matrices are equal. + The first matrix to compare. + The second matrix to compare. + true if value1 and value2 are equal; otherwise, false. + + + Returns a value that indicates whether the specified matrices are not equal. + The first matrix to compare. + The second matrix to compare. + true if value1 and value2 are not equal; otherwise, false. + + + Returns the matrix that results from multiplying two matrices together. + The first matrix. + The second matrix. + The product matrix. + + + Returns the matrix that results from scaling all the elements of a specified matrix by a scalar factor. + The matrix to scale. + The scaling value to use. + The scaled matrix. + + + Subtracts each element in a second matrix from its corresponding element in a first matrix. + The first matrix. + The second matrix. + The matrix containing the values that result from subtracting each element in value2 from its corresponding element in value1. + + + Negates the specified matrix by multiplying all its values by -1. + The matrix to negate. + The negated matrix. + + + Subtracts each element in a second matrix from its corresponding element in a first matrix. + The first matrix. + The second matrix. + The matrix containing the values that result from subtracting each element in value2 from its corresponding element in value1. + + + Returns a string that represents this matrix. + The string representation of this matrix. + + + Gets or sets the translation component of this matrix. + The translation component of the current instance. + + + Represents a 4x4 matrix. + + + Creates a object from a specified object. + A 3x2 matrix. + + + Creates a 4x4 matrix from the specified components. + The value to assign to the first element in the first row. + The value to assign to the second element in the first row. + The value to assign to the third element in the first row. + The value to assign to the fourth element in the first row. + The value to assign to the first element in the second row. + The value to assign to the second element in the second row. + The value to assign to the third element in the second row. + The value to assign to the third element in the second row. + The value to assign to the first element in the third row. + The value to assign to the second element in the third row. + The value to assign to the third element in the third row. + The value to assign to the fourth element in the third row. + The value to assign to the first element in the fourth row. + The value to assign to the second element in the fourth row. + The value to assign to the third element in the fourth row. + The value to assign to the fourth element in the fourth row. + + + Adds each element in one matrix with its corresponding element in a second matrix. + The first matrix. + The second matrix. + The matrix that contains the summed values of value1 and value2. + + + Creates a spherical billboard that rotates around a specified object position. + The position of the object that the billboard will rotate around. + The position of the camera. + The up vector of the camera. + The forward vector of the camera. + The created billboard. + + + Creates a cylindrical billboard that rotates around a specified axis. + The position of the object that the billboard will rotate around. + The position of the camera. + The axis to rotate the billboard around. + The forward vector of the camera. + The forward vector of the object. + The billboard matrix. + + + Creates a matrix that rotates around an arbitrary vector. + The axis to rotate around. + The angle to rotate around axis, in radians. + The rotation matrix. + + + Creates a rotation matrix from the specified Quaternion rotation value. + The source Quaternion. + The rotation matrix. + + + Creates a rotation matrix from the specified yaw, pitch, and roll. + The angle of rotation, in radians, around the Y axis. + The angle of rotation, in radians, around the X axis. + The angle of rotation, in radians, around the Z axis. + The rotation matrix. + + + Creates a view matrix. + The position of the camera. + The target towards which the camera is pointing. + The direction that is "up" from the camera's point of view. + The view matrix. + + + Creates an orthographic perspective matrix from the given view volume dimensions. + The width of the view volume. + The height of the view volume. + The minimum Z-value of the view volume. + The maximum Z-value of the view volume. + The orthographic projection matrix. + + + Creates a customized orthographic projection matrix. + The minimum X-value of the view volume. + The maximum X-value of the view volume. + The minimum Y-value of the view volume. + The maximum Y-value of the view volume. + The minimum Z-value of the view volume. + The maximum Z-value of the view volume. + The orthographic projection matrix. + + + Creates a perspective projection matrix from the given view volume dimensions. + The width of the view volume at the near view plane. + The height of the view volume at the near view plane. + The distance to the near view plane. + The distance to the far view plane. + The perspective projection matrix. + nearPlaneDistance is less than or equal to zero. -or- farPlaneDistance is less than or equal to zero. -or- nearPlaneDistance is greater than or equal to farPlaneDistance. + + + Creates a perspective projection matrix based on a field of view, aspect ratio, and near and far view plane distances. + The field of view in the y direction, in radians. + The aspect ratio, defined as view space width divided by height. + The distance to the near view plane. + The distance to the far view plane. + The perspective projection matrix. + fieldOfView is less than or equal to zero. -or- fieldOfView is greater than or equal to . nearPlaneDistance is less than or equal to zero. -or- farPlaneDistance is less than or equal to zero. -or- nearPlaneDistance is greater than or equal to farPlaneDistance. + + + Creates a customized perspective projection matrix. + The minimum x-value of the view volume at the near view plane. + The maximum x-value of the view volume at the near view plane. + The minimum y-value of the view volume at the near view plane. + The maximum y-value of the view volume at the near view plane. + The distance to the near view plane. + The distance to the far view plane. + The perspective projection matrix. + nearPlaneDistance is less than or equal to zero. -or- farPlaneDistance is less than or equal to zero. -or- nearPlaneDistance is greater than or equal to farPlaneDistance. + + + Creates a matrix that reflects the coordinate system about a specified plane. + The plane about which to create a reflection. + A new matrix expressing the reflection. + + + Creates a matrix for rotating points around the X axis. + The amount, in radians, by which to rotate around the X axis. + The rotation matrix. + + + Creates a matrix for rotating points around the X axis from a center point. + The amount, in radians, by which to rotate around the X axis. + The center point. + The rotation matrix. + + + The amount, in radians, by which to rotate around the Y axis from a center point. + The amount, in radians, by which to rotate around the Y-axis. + The center point. + The rotation matrix. + + + Creates a matrix for rotating points around the Y axis. + The amount, in radians, by which to rotate around the Y-axis. + The rotation matrix. + + + Creates a matrix for rotating points around the Z axis. + The amount, in radians, by which to rotate around the Z-axis. + The rotation matrix. + + + Creates a matrix for rotating points around the Z axis from a center point. + The amount, in radians, by which to rotate around the Z-axis. + The center point. + The rotation matrix. + + + Creates a scaling matrix from the specified vector scale. + The scale to use. + The scaling matrix. + + + Creates a uniform scaling matrix that scale equally on each axis. + The uniform scaling factor. + The scaling matrix. + + + Creates a scaling matrix with a center point. + The vector that contains the amount to scale on each axis. + The center point. + The scaling matrix. + + + Creates a uniform scaling matrix that scales equally on each axis with a center point. + The uniform scaling factor. + The center point. + The scaling matrix. + + + Creates a scaling matrix from the specified X, Y, and Z components. + The value to scale by on the X axis. + The value to scale by on the Y axis. + The value to scale by on the Z axis. + The scaling matrix. + + + Creates a scaling matrix that is offset by a given center point. + The value to scale by on the X axis. + The value to scale by on the Y axis. + The value to scale by on the Z axis. + The center point. + The scaling matrix. + + + Creates a matrix that flattens geometry into a specified plane as if casting a shadow from a specified light source. + The direction from which the light that will cast the shadow is coming. + The plane onto which the new matrix should flatten geometry so as to cast a shadow. + A new matrix that can be used to flatten geometry onto the specified plane from the specified direction. + + + Creates a translation matrix from the specified 3-dimensional vector. + The amount to translate in each axis. + The translation matrix. + + + Creates a translation matrix from the specified X, Y, and Z components. + The amount to translate on the X axis. + The amount to translate on the Y axis. + The amount to translate on the Z axis. + The translation matrix. + + + Creates a world matrix with the specified parameters. + The position of the object. + The forward direction of the object. + The upward direction of the object. Its value is usually [0, 1, 0]. + The world matrix. + + + Attempts to extract the scale, translation, and rotation components from the given scale, rotation, or translation matrix. The return value indicates whether the operation succeeded. + The source matrix. + When this method returns, contains the scaling component of the transformation matrix if the operation succeeded. + When this method returns, contains the rotation component of the transformation matrix if the operation succeeded. + When the method returns, contains the translation component of the transformation matrix if the operation succeeded. + true if matrix was decomposed successfully; otherwise, false. + + + Returns a value that indicates whether this instance and another 4x4 matrix are equal. + The other matrix. + true if the two matrices are equal; otherwise, false. + + + Returns a value that indicates whether this instance and a specified object are equal. + The object to compare with the current instance. + true if the current instance and obj are equal; otherwise, false```. If <code data-dev-comment-type="paramref">obj</code> isnull, the method returnsfalse`. + + + Calculates the determinant of the current 4x4 matrix. + The determinant. + + + Returns the hash code for this instance. + The hash code. + + + Gets the multiplicative identity matrix. + Gets the multiplicative identity matrix. + + + Inverts the specified matrix. The return value indicates whether the operation succeeded. + The matrix to invert. + When this method returns, contains the inverted matrix if the operation succeeded. + true if matrix was converted successfully; otherwise, false. + + + Indicates whether the current matrix is the identity matrix. + true if the current matrix is the identity matrix; otherwise, false. + + + Performs a linear interpolation from one matrix to a second matrix based on a value that specifies the weighting of the second matrix. + The first matrix. + The second matrix. + The relative weighting of matrix2. + The interpolated matrix. + + + The first element of the first row. + + + + The second element of the first row. + + + + The third element of the first row. + + + + The fourth element of the first row. + + + + The first element of the second row. + + + + The second element of the second row. + + + + The third element of the second row. + + + + The fourth element of the second row. + + + + The first element of the third row. + + + + The second element of the third row. + + + + The third element of the third row. + + + + The fourth element of the third row. + + + + The first element of the fourth row. + + + + The second element of the fourth row. + + + + The third element of the fourth row. + + + + The fourth element of the fourth row. + + + + Returns the matrix that results from multiplying two matrices together. + The first matrix. + The second matrix. + The product matrix. + + + Returns the matrix that results from scaling all the elements of a specified matrix by a scalar factor. + The matrix to scale. + The scaling value to use. + The scaled matrix. + + + Negates the specified matrix by multiplying all its values by -1. + The matrix to negate. + The negated matrix. + + + Adds each element in one matrix with its corresponding element in a second matrix. + The first matrix. + The second matrix. + The matrix that contains the summed values. + + + Returns a value that indicates whether the specified matrices are equal. + The first matrix to compare. + The second matrix to care + true if value1 and value2 are equal; otherwise, false. + + + Returns a value that indicates whether the specified matrices are not equal. + The first matrix to compare. + The second matrix to compare. + true if value1 and value2 are not equal; otherwise, false. + + + Returns the matrix that results from scaling all the elements of a specified matrix by a scalar factor. + The matrix to scale. + The scaling value to use. + The scaled matrix. + + + Returns the matrix that results from multiplying two matrices together. + The first matrix. + The second matrix. + The product matrix. + + + Subtracts each element in a second matrix from its corresponding element in a first matrix. + The first matrix. + The second matrix. + The matrix containing the values that result from subtracting each element in value2 from its corresponding element in value1. + + + Negates the specified matrix by multiplying all its values by -1. + The matrix to negate. + The negated matrix. + + + Subtracts each element in a second matrix from its corresponding element in a first matrix. + The first matrix. + The second matrix. + The matrix containing the values that result from subtracting each element in value2 from its corresponding element in value1. + + + Returns a string that represents this matrix. + The string representation of this matrix. + + + Transforms the specified matrix by applying the specified Quaternion rotation. + The matrix to transform. + The rotation t apply. + The transformed matrix. + + + Gets or sets the translation component of this matrix. + The translation component of the current instance. + + + Transposes the rows and columns of a matrix. + The matrix to transpose. + The transposed matrix. + + + Represents a three-dimensional plane. + + + Creates a object from a specified four-dimensional vector. + A vector whose first three elements describe the normal vector, and whose defines the distance along that normal from the origin. + + + Creates a object from a specified normal and the distance along the normal from the origin. + The plane's normal vector. + The plane's distance from the origin along its normal vector. + + + Creates a object from the X, Y, and Z components of its normal, and its distance from the origin on that normal. + The X component of the normal. + The Y component of the normal. + The Z component of the normal. + The distance of the plane along its normal from the origin. + + + Creates a object that contains three specified points. + The first point defining the plane. + The second point defining the plane. + The third point defining the plane. + The plane containing the three points. + + + The distance of the plane along its normal from the origin. + + + + Calculates the dot product of a plane and a 4-dimensional vector. + The plane. + The four-dimensional vector. + The dot product. + + + Returns the dot product of a specified three-dimensional vector and the normal vector of this plane plus the distance () value of the plane. + The plane. + The 3-dimensional vector. + The dot product. + + + Returns the dot product of a specified three-dimensional vector and the vector of this plane. + The plane. + The three-dimensional vector. + The dot product. + + + Returns a value that indicates whether this instance and a specified object are equal. + The object to compare with the current instance. + true if the current instance and obj are equal; otherwise, false```. If <code data-dev-comment-type="paramref">obj</code> isnull, the method returnsfalse`. + + + Returns a value that indicates whether this instance and another plane object are equal. + The other plane. + true if the two planes are equal; otherwise, false. + + + Returns the hash code for this instance. + The hash code. + + + The normal vector of the plane. + + + + Creates a new object whose normal vector is the source plane's normal vector normalized. + The source plane. + The normalized plane. + + + Returns a value that indicates whether two planes are equal. + The first plane to compare. + The second plane to compare. + true if value1 and value2 are equal; otherwise, false. + + + Returns a value that indicates whether two planes are not equal. + The first plane to compare. + The second plane to compare. + true if value1 and value2 are not equal; otherwise, false. + + + Returns the string representation of this plane object. + A string that represents this object. + + + Transforms a normalized plane by a 4x4 matrix. + The normalized plane to transform. + The transformation matrix to apply to plane. + The transformed plane. + + + Transforms a normalized plane by a Quaternion rotation. + The normalized plane to transform. + The Quaternion rotation to apply to the plane. + A new plane that results from applying the Quaternion rotation. + + + Represents a vector that is used to encode three-dimensional physical rotations. + + + Creates a quaternion from the specified vector and rotation parts. + The vector part of the quaternion. + The rotation part of the quaternion. + + + Constructs a quaternion from the specified components. + The value to assign to the X component of the quaternion. + The value to assign to the Y component of the quaternion. + The value to assign to the Z component of the quaternion. + The value to assign to the W component of the quaternion. + + + Adds each element in one quaternion with its corresponding element in a second quaternion. + The first quaternion. + The second quaternion. + The quaternion that contains the summed values of value1 and value2. + + + Concatenates two quaternions. + The first quaternion rotation in the series. + The second quaternion rotation in the series. + A new quaternion representing the concatenation of the value1 rotation followed by the value2 rotation. + + + Returns the conjugate of a specified quaternion. + The quaternion. + A new quaternion that is the conjugate of value. + + + Creates a quaternion from a vector and an angle to rotate about the vector. + The vector to rotate around. + The angle, in radians, to rotate around the vector. + The newly created quaternion. + + + Creates a quaternion from the specified rotation matrix. + The rotation matrix. + The newly created quaternion. + + + Creates a new quaternion from the given yaw, pitch, and roll. + The yaw angle, in radians, around the Y axis. + The pitch angle, in radians, around the X axis. + The roll angle, in radians, around the Z axis. + The resulting quaternion. + + + Divides one quaternion by a second quaternion. + The dividend. + The divisor. + The quaternion that results from dividing value1 by value2. + + + Calculates the dot product of two quaternions. + The first quaternion. + The second quaternion. + The dot product. + + + Returns a value that indicates whether this instance and another quaternion are equal. + The other quaternion. + true if the two quaternions are equal; otherwise, false. + + + Returns a value that indicates whether this instance and a specified object are equal. + The object to compare with the current instance. + true if the current instance and obj are equal; otherwise, false```. If <code data-dev-comment-type="paramref">obj</code> isnull, the method returnsfalse`. + + + Returns the hash code for this instance. + The hash code. + + + Gets a quaternion that represents no rotation. + A quaternion whose values are (0, 0, 0, 1). + + + Returns the inverse of a quaternion. + The quaternion. + The inverted quaternion. + + + Gets a value that indicates whether the current instance is the identity quaternion. + true if the current instance is the identity quaternion; otherwise, false. + + + Calculates the length of the quaternion. + The computed length of the quaternion. + + + Calculates the squared length of the quaternion. + The length squared of the quaternion. + + + Performs a linear interpolation between two quaternions based on a value that specifies the weighting of the second quaternion. + The first quaternion. + The second quaternion. + The relative weight of quaternion2 in the interpolation. + The interpolated quaternion. + + + Returns the quaternion that results from multiplying two quaternions together. + The first quaternion. + The second quaternion. + The product quaternion. + + + Returns the quaternion that results from scaling all the components of a specified quaternion by a scalar factor. + The source quaternion. + The scalar value. + The scaled quaternion. + + + Reverses the sign of each component of the quaternion. + The quaternion to negate. + The negated quaternion. + + + Divides each component of a specified by its length. + The quaternion to normalize. + The normalized quaternion. + + + Adds each element in one quaternion with its corresponding element in a second quaternion. + The first quaternion. + The second quaternion. + The quaternion that contains the summed values of value1 and value2. + + + Divides one quaternion by a second quaternion. + The dividend. + The divisor. + The quaternion that results from dividing value1 by value2. + + + Returns a value that indicates whether two quaternions are equal. + The first quaternion to compare. + The second quaternion to compare. + true if the two quaternions are equal; otherwise, false. + + + Returns a value that indicates whether two quaternions are not equal. + The first quaternion to compare. + The second quaternion to compare. + true if value1 and value2 are not equal; otherwise, false. + + + Returns the quaternion that results from scaling all the components of a specified quaternion by a scalar factor. + The source quaternion. + The scalar value. + The scaled quaternion. + + + Returns the quaternion that results from multiplying two quaternions together. + The first quaternion. + The second quaternion. + The product quaternion. + + + Subtracts each element in a second quaternion from its corresponding element in a first quaternion. + The first quaternion. + The second quaternion. + The quaternion containing the values that result from subtracting each element in value2 from its corresponding element in value1. + + + Reverses the sign of each component of the quaternion. + The quaternion to negate. + The negated quaternion. + + + Interpolates between two quaternions, using spherical linear interpolation. + The first quaternion. + The second quaternion. + The relative weight of the second quaternion in the interpolation. + The interpolated quaternion. + + + Subtracts each element in a second quaternion from its corresponding element in a first quaternion. + The first quaternion. + The second quaternion. + The quaternion containing the values that result from subtracting each element in value2 from its corresponding element in value1. + + + Returns a string that represents this quaternion. + The string representation of this quaternion. + + + The rotation component of the quaternion. + + + + The X value of the vector component of the quaternion. + + + + The Y value of the vector component of the quaternion. + + + + The Z value of the vector component of the quaternion. + + + + Represents a single vector of a specified numeric type that is suitable for low-level optimization of parallel algorithms. + The vector type. T can be any primitive numeric type. + + + Creates a vector whose components are of a specified type. + The numeric type that defines the type of the components in the vector. + + + Creates a vector from a specified array. + A numeric array. + values is null. + + + Creates a vector from a specified array starting at a specified index position. + A numeric array. + The starting index position from which to create the vector. + values is null. + index is less than zero. -or- The length of values minus index is less than . + + + Copies the vector instance to a specified destination array. + The array to receive a copy of the vector values. + destination is null. + The number of elements in the current vector is greater than the number of elements available in the destination array. + + + Copies the vector instance to a specified destination array starting at a specified index position. + The array to receive a copy of the vector values. + The starting index in destination at which to begin the copy operation. + destination is null. + The number of elements in the current instance is greater than the number of elements available from startIndex to the end of the destination array. + index is less than zero or greater than the last index in destination. + + + Returns the number of elements stored in the vector. + The number of elements stored in the vector. + Access to the property getter via reflection is not supported. + + + Returns a value that indicates whether this instance is equal to a specified vector. + The vector to compare with this instance. + true if the current instance and other are equal; otherwise, false. + + + Returns a value that indicates whether this instance is equal to a specified object. + The object to compare with this instance. + true if the current instance and obj are equal; otherwise, false. The method returns false if obj is null, or if obj is a vector of a different type than the current instance. + + + Returns the hash code for this instance. + The hash code. + + + Gets the element at a specified index. + The index of the element to return. + The element at index index. + index is less than zero. -or- index is greater than or equal to . + + + Returns a vector containing all ones. + A vector containing all ones. + + + Adds two vectors together. + The first vector to add. + The second vector to add. + The summed vector. + + + Returns a new vector by performing a bitwise And operation on each of the elements in two vectors. + The first vector. + The second vector. + The vector that results from the bitwise And of left and right. + + + Returns a new vector by performing a bitwise Or operation on each of the elements in two vectors. + The first vector. + The second vector. + The vector that results from the bitwise Or of the elements in left and right. + + + Divides the first vector by the second. + The first vector. + The second vector. + The vector that results from dividing left by right. + + + Returns a value that indicates whether each pair of elements in two specified vectors are equal. + The first vector to compare. + The second vector to compare. + true if left and right are equal; otherwise, false. + + + Returns a new vector by performing a bitwise XOr operation on each of the elements in two vectors. + The first vector. + The second vector. + The vector that results from the bitwise XOr of the elements in left and right. + + + Reinterprets the bits of the specified vector into a vector of type . + The vector to reinterpret. + The reinterpreted vector. + + + Reinterprets the bits of the specified vector into a vector of type . + The vector to reinterpret. + The reinterpreted vector. + + + Reinterprets the bits of the specified vector into a vector of type . + The vector to reinterpret. + The reinterpreted vector. + + + Reinterprets the bits of the specified vector into a vector of type . + The vector to reinterpret. + The reinterpreted vector. + + + Reinterprets the bits of the specified vector into a vector of type . + The vector to reinterpret. + The reinterpreted vector. + + + Reinterprets the bits of the specified vector into a vector of type . + The vector to reinterpret. + The reinterpreted vector. + + + Reinterprets the bits of the specified vector into a vector of type . + The vector to reinterpret. + The reinterpreted vector. + + + Reinterprets the bits of the specified vector into a vector of type . + The vector to reinterpret. + The reinterpreted vector. + + + Reinterprets the bits of the specified vector into a vector of type . + The vector to reinterpret. + The reinterpreted vector. + + + Reinterprets the bits of the specified vector into a vector of type . + The vector to reinterpret. + The reinterpreted vector. + + + Returns a value that indicates whether any single pair of elements in the specified vectors is equal. + The first vector to compare. + The second vector to compare. + true if any element pairs in left and right are equal. false if no element pairs are equal. + + + Multiplies two vectors together. + The first vector. + The second vector. + The product vector. + + + Multiplies a vector by a specified scalar value. + The source vector. + A scalar value. + The scaled vector. + + + Multiplies a vector by the given scalar. + The scalar value. + The source vector. + The scaled vector. + + + Returns a new vector whose elements are obtained by taking the one's complement of a specified vector's elements. + The source vector. + The one's complement vector. + + + Subtracts the second vector from the first. + The first vector. + The second vector. + The vector that results from subtracting right from left. + + + Negates a given vector. + The vector to negate. + The negated vector. + + + Returns the string representation of this vector using the specified format string to format individual elements and the specified format provider to define culture-specific formatting. + A or that defines the format of individual elements. + A format provider that supplies culture-specific formatting information. + The string representation of the current instance. + + + Returns the string representation of this vector using default formatting. + The string representation of this vector. + + + Returns the string representation of this vector using the specified format string to format individual elements. + A or that defines the format of individual elements. + The string representation of the current instance. + + + Returns a vector containing all zeroes. + A vector containing all zeroes. + + + Provides a collection of static convenience methods for creating, manipulating, combining, and converting generic vectors. + + + Returns a new vector whose elements are the absolute values of the given vector's elements. + The source vector. + The vector type. T can be any primitive numeric type. + The absolute value vector. + + + Returns a new vector whose values are the sum of each pair of elements from two given vectors. + The first vector. + The second vector. + The vector type. T can be any primitive numeric type. + The summed vector. + + + Returns a new vector by performing a bitwise And Not operation on each pair of corresponding elements in two vectors. + The first vector. + The second vector. + The vector type. T can be any primitive numeric type. + The resulting vector. + + + Reinterprets the bits of a specified vector into those of a vector of unsigned bytes. + The source vector. + The vector type. T can be any primitive numeric type. + The reinterpreted vector. + + + Reinterprets the bits of a specified vector into those of a double-precision floating-point vector. + The source vector. + The vector type. T can be any primitive numeric type. + The reinterpreted vector. + + + Reinterprets the bits of a specified vector into those of a vector of 16-bit integers. + The source vector. + The vector type. T can be any primitive numeric type. + The reinterpreted vector. + + + Reinterprets the bits of a specified vector into those of a vector of integers. + The source vector. + The vector type. T can be any primitive numeric type. + The reinterpreted vector. + + + Reinterprets the bits of a specified vector into those of a vector of long integers. + The source vector. + The vector type. T can be any primitive numeric type. + The reinterpreted vector. + + + Reinterprets the bits of a specified vector into those of a vector of signed bytes. + The source vector. + The vector type. T can be any primitive numeric type. + The reinterpreted vector. + + + Reinterprets the bits of a specified vector into those of a single-precision floating-point vector. + The source vector. + The vector type. T can be any primitive numeric type. + The reinterpreted vector. + + + Reinterprets the bits of a specified vector into those of a vector of unsigned 16-bit integers. + The source vector. + The vector type. T can be any primitive numeric type. + The reinterpreted vector. + + + Reinterprets the bits of a specified vector into those of a vector of unsigned integers. + The source vector. + The vector type. T can be any primitive numeric type. + The reinterpreted vector. + + + Reinterprets the bits of a specified vector into those of a vector of unsigned long integers. + The source vector. + The vector type. T can be any primitive numeric type. + The reinterpreted vector. + + + Returns a new vector by performing a bitwise And operation on each pair of elements in two vectors. + The first vector. + The second vector. + The vector type. T can be any primitive numeric type. + The resulting vector. + + + Returns a new vector by performing a bitwise Or operation on each pair of elements in two vectors. + The first vector. + The second vector. + The vector type. T can be any primitive numeric type. + The resulting vector. + + + Creates a new single-precision vector with elements selected between two specified single-precision source vectors based on an integral mask vector. + The integral mask vector used to drive selection. + The first source vector. + The second source vector. + The new vector with elements selected based on the mask. + + + Creates a new double-precision vector with elements selected between two specified double-precision source vectors based on an integral mask vector. + The integral mask vector used to drive selection. + The first source vector. + The second source vector. + The new vector with elements selected based on the mask. + + + Creates a new vector of a specified type with elements selected between two specified source vectors of the same type based on an integral mask vector. + The integral mask vector used to drive selection. + The first source vector. + The second source vector. + The vector type. T can be any primitive numeric type. + The new vector with elements selected based on the mask. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Returns a new vector whose values are the result of dividing the first vector's elements by the corresponding elements in the second vector. + The first vector. + The second vector. + The vector type. T can be any primitive numeric type. + The divided vector. + + + Returns the dot product of two vectors. + The first vector. + The second vector. + The vector type. T can be any primitive numeric type. + The dot product. + + + Returns a new integral vector whose elements signal whether the elements in two specified double-precision vectors are equal. + The first vector to compare. + The second vector to compare. + The resulting integral vector. + + + Returns a new integral vector whose elements signal whether the elements in two specified integral vectors are equal. + The first vector to compare. + The second vector to compare. + The resulting integral vector. + + + Returns a new vector whose elements signal whether the elements in two specified long integer vectors are equal. + The first vector to compare. + The second vector to compare. + The resulting long integer vector. + + + Returns a new integral vector whose elements signal whether the elements in two specified single-precision vectors are equal. + The first vector to compare. + The second vector to compare. + The resulting integral vector. + + + Returns a new vector of a specified type whose elements signal whether the elements in two specified vectors of the same type are equal. + The first vector to compare. + The second vector to compare. + The vector type. T can be any primitive numeric type. + The resulting vector. + + + Returns a value that indicates whether each pair of elements in the given vectors is equal. + The first vector to compare. + The second vector to compare. + The vector type. T can be any primitive numeric type. + true if all elements in left and right are equal; otherwise, false. + + + Returns a value that indicates whether any single pair of elements in the given vectors is equal. + The first vector to compare. + The second vector to compare. + The vector type. T can be any primitive numeric type. + true if any element pair in left and right is equal; otherwise, false. + + + Returns a new integral vector whose elements signal whether the elements in one double-precision floating-point vector are greater than their corresponding elements in a second double-precision floating-point vector. + The first vector to compare. + The second vector to compare. + The resulting integral vector. + + + Returns a new integral vector whose elements signal whether the elements in one integral vector are greater than their corresponding elements in a second integral vector. + The first vector to compare. + The second vector to compare. + The resulting integral vector. + + + Returns a new long integer vector whose elements signal whether the elements in one long integer vector are greater than their corresponding elements in a second long integer vector. + The first vector to compare. + The second vector to compare. + The resulting long integer vector. + + + Returns a new integral vector whose elements signal whether the elements in one single-precision floating-point vector are greater than their corresponding elements in a second single-precision floating-point vector. + The first vector to compare. + The second vector to compare. + The resulting integral vector. + + + Returns a new vector whose elements signal whether the elements in one vector of a specified type are greater than their corresponding elements in the second vector of the same time. + The first vector to compare. + The second vector to compare. + The vector type. T can be any primitive numeric type. + The resulting vector. + + + Returns a value that indicates whether all elements in the first vector are greater than the corresponding elements in the second vector. + The first vector to compare. + The second vector to compare. + The vector type. T can be any primitive numeric type. + true if all elements in left are greater than the corresponding elements in right; otherwise, false. + + + Returns a value that indicates whether any element in the first vector is greater than the corresponding element in the second vector. + The first vector to compare. + The second vector to compare. + The vector type. T can be any primitive numeric type. + true if any element in left is greater than the corresponding element in right; otherwise, false. + + + Returns a new integral vector whose elements signal whether the elements in one vector are greater than or equal to their corresponding elements in the single-precision floating-point second vector. + The first vector to compare. + The second vector to compare. + The resulting integral vector. + + + Returns a new long integer vector whose elements signal whether the elements in one long integer vector are greater than or equal to their corresponding elements in the second long integer vector. + The first vector to compare. + The second vector to compare. + The resulting long integer vector. + + + Returns a new integral vector whose elements signal whether the elements in one integral vector are greater than or equal to their corresponding elements in the second integral vector. + The first vector to compare. + The second vector to compare. + The resulting integral vector. + + + Returns a new integral vector whose elements signal whether the elements in one vector are greater than or equal to their corresponding elements in the second double-precision floating-point vector. + The first vector to compare. + The second vector to compare. + The resulting integral vector. + + + Returns a new vector whose elements signal whether the elements in one vector of a specified type are greater than or equal to their corresponding elements in the second vector of the same type. + The first vector to compare. + The second vector to compare. + The vector type. T can be any primitive numeric type. + The resulting vector. + + + Returns a value that indicates whether all elements in the first vector are greater than or equal to all the corresponding elements in the second vector. + The first vector to compare. + The second vector to compare. + The vector type. T can be any primitive numeric type. + true if all elements in left are greater than or equal to the corresponding elements in right; otherwise, false. + + + Returns a value that indicates whether any element in the first vector is greater than or equal to the corresponding element in the second vector. + The first vector to compare. + The second vector to compare. + The vector type. T can be any primitive numeric type. + true if any element in left is greater than or equal to the corresponding element in right; otherwise, false. + + + Gets a value that indicates whether vector operations are subject to hardware acceleration through JIT intrinsic support. + true if vector operations are subject to hardware acceleration; otherwise, false. + + + Returns a new integral vector whose elements signal whether the elements in one double-precision floating-point vector are less than their corresponding elements in a second double-precision floating-point vector. + The first vector to compare. + The second vector to compare. + The resulting integral vector. + + + Returns a new integral vector whose elements signal whether the elements in one integral vector are less than their corresponding elements in a second integral vector. + The first vector to compare. + The second vector to compare. + The resulting integral vector + + + Returns a new long integer vector whose elements signal whether the elements in one long integer vector are less than their corresponding elements in a second long integer vector. + The first vector to compare. + The second vector to compare. + The resulting long integer vector. + + + Returns a new integral vector whose elements signal whether the elements in one single-precision vector are less than their corresponding elements in a second single-precision vector. + The first vector to compare. + The second vector to compare. + The resulting integral vector. + + + Returns a new vector of a specified type whose elements signal whether the elements in one vector are less than their corresponding elements in the second vector. + The first vector to compare. + The second vector to compare. + The vector type. T can be any primitive numeric type. + The resulting vector. + + + Returns a value that indicates whether all of the elements in the first vector are less than their corresponding elements in the second vector. + The first vector to compare. + The second vector to compare. + The vector type. T can be any primitive numeric type. + true if all of the elements in left are less than the corresponding elements in right; otherwise, false. + + + Returns a value that indicates whether any element in the first vector is less than the corresponding element in the second vector. + The first vector to compare. + The second vector to compare. + The vector type. T can be any primitive numeric type. + true if any element in left is less than the corresponding element in right; otherwise, false. + + + Returns a new integral vector whose elements signal whether the elements in one double-precision floating-point vector are less than or equal to their corresponding elements in a second double-precision floating-point vector. + The first vector to compare. + The second vector to compare. + The resulting integral vector. + + + Returns a new integral vector whose elements signal whether the elements in one integral vector are less than or equal to their corresponding elements in a second integral vector. + The first vector to compare. + The second vector to compare. + The resulting integral vector. + + + Returns a new long integer vector whose elements signal whether the elements in one long integer vector are less or equal to their corresponding elements in a second long integer vector. + The first vector to compare. + The second vector to compare. + The resulting long integer vector. + + + Returns a new integral vector whose elements signal whether the elements in one single-precision floating-point vector are less than or equal to their corresponding elements in a second single-precision floating-point vector. + The first vector to compare. + The second vector to compare. + The resulting integral vector. + + + Returns a new vector whose elements signal whether the elements in one vector are less than or equal to their corresponding elements in the second vector. + The first vector to compare. + The second vector to compare. + The vector type. T can be any primitive numeric type. + The resulting vector. + + + Returns a value that indicates whether all elements in the first vector are less than or equal to their corresponding elements in the second vector. + The first vector to compare. + The second vector to compare. + The vector type. T can be any primitive numeric type. + true if all of the elements in left are less than or equal to the corresponding elements in right; otherwise, false. + + + Returns a value that indicates whether any element in the first vector is less than or equal to the corresponding element in the second vector. + The first vector to compare. + The second vector to compare. + The vector type. T can be any primitive numeric type. + true if any element in left is less than or equal to the corresponding element in right; otherwise, false. + + + Returns a new vector whose elements are the maximum of each pair of elements in the two given vectors. + The first vector to compare. + The second vector to compare. + The vector type. T can be any primitive numeric type. + The maximum vector. + + + Returns a new vector whose elements are the minimum of each pair of elements in the two given vectors. + The first vector to compare. + The second vector to compare. + The vector type. T can be any primitive numeric type. + The minimum vector. + + + Returns a new vector whose values are a scalar value multiplied by each of the values of a specified vector. + The scalar value. + The vector. + The vector type. T can be any primitive numeric type. + The scaled vector. + + + Returns a new vector whose values are the product of each pair of elements in two specified vectors. + The first vector. + The second vector. + The vector type. T can be any primitive numeric type. + The product vector. + + + Returns a new vector whose values are the values of a specified vector each multiplied by a scalar value. + The vector. + The scalar value. + The vector type. T can be any primitive numeric type. + The scaled vector. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Returns a new vector whose elements are the negation of the corresponding element in the specified vector. + The source vector. + The vector type. T can be any primitive numeric type. + The negated vector. + + + Returns a new vector whose elements are obtained by taking the one's complement of a specified vector's elements. + The source vector. + The vector type. T can be any primitive numeric type. + The resulting vector. + + + Returns a new vector whose elements are the square roots of a specified vector's elements. + The source vector. + The vector type. T can be any primitive numeric type. + The square root vector. + + + Returns a new vector whose values are the difference between the elements in the second vector and their corresponding elements in the first vector. + The first vector. + The second vector. + The vector type. T can be any primitive numeric type. + The difference vector. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Returns a new vector by performing a bitwise exclusive Or (XOr) operation on each pair of elements in two vectors. + The first vector. + The second vector. + The vector type. T can be any primitive numeric type. + The resulting vector. + + + Represents a vector with two single-precision floating-point values. + + + Creates a new object whose two elements have the same value. + The value to assign to both elements. + + + Creates a vector whose elements have the specified values. + The value to assign to the field. + The value to assign to the field. + + + Returns a vector whose elements are the absolute values of each of the specified vector's elements. + A vector. + The absolute value vector. + + + Adds two vectors together. + The first vector to add. + The second vector to add. + The summed vector. + + + Restricts a vector between a minimum and a maximum value. + The vector to restrict. + The minimum value. + The maximum value. + The restricted vector. + + + Copies the elements of the vector to a specified array. + The destination array. + array is null. + The number of elements in the current instance is greater than in the array. + array is multidimensional. + + + Copies the elements of the vector to a specified array starting at a specified index position. + The destination array. + The index at which to copy the first element of the vector. + array is null. + The number of elements in the current instance is greater than in the array. + index is less than zero. -or- index is greater than or equal to the array length. + array is multidimensional. + + + Computes the Euclidean distance between the two given points. + The first point. + The second point. + The distance. + + + Returns the Euclidean distance squared between two specified points. + The first point. + The second point. + The distance squared. + + + Divides the first vector by the second. + The first vector. + The second vector. + The vector resulting from the division. + + + Divides the specified vector by a specified scalar value. + The vector. + The scalar value. + The vector that results from the division. + + + Returns the dot product of two vectors. + The first vector. + The second vector. + The dot product. + + + Returns a value that indicates whether this instance and a specified object are equal. + The object to compare with the current instance. + true if the current instance and obj are equal; otherwise, false```. If <code data-dev-comment-type="paramref">obj</code> isnull, the method returnsfalse`. + + + Returns a value that indicates whether this instance and another vector are equal. + The other vector. + true if the two vectors are equal; otherwise, false. + + + Returns the hash code for this instance. + The hash code. + + + Returns the length of the vector. + The vector's length. + + + Returns the length of the vector squared. + The vector's length squared. + + + Performs a linear interpolation between two vectors based on the given weighting. + The first vector. + The second vector. + A value between 0 and 1 that indicates the weight of value2. + The interpolated vector. + + + Returns a vector whose elements are the maximum of each of the pairs of elements in two specified vectors. + The first vector. + The second vector. + The maximized vector. + + + Returns a vector whose elements are the minimum of each of the pairs of elements in two specified vectors. + The first vector. + The second vector. + The minimized vector. + + + Multiplies two vectors together. + The first vector. + The second vector. + The product vector. + + + Multiplies a vector by a specified scalar. + The vector to multiply. + The scalar value. + The scaled vector. + + + Multiplies a scalar value by a specified vector. + The scaled value. + The vector. + The scaled vector. + + + Negates a specified vector. + The vector to negate. + The negated vector. + + + Returns a vector with the same direction as the specified vector, but with a length of one. + The vector to normalize. + The normalized vector. + + + Gets a vector whose 2 elements are equal to one. + A vector whose two elements are equal to one (that is, it returns the vector (1,1). + + + Adds two vectors together. + The first vector to add. + The second vector to add. + The summed vector. + + + Divides the first vector by the second. + The first vector. + The second vector. + The vector that results from dividing left by right. + + + Divides the specified vector by a specified scalar value. + The vector. + The scalar value. + The result of the division. + + + Returns a value that indicates whether each pair of elements in two specified vectors is equal. + The first vector to compare. + The second vector to compare. + true if left and right are equal; otherwise, false. + + + Returns a value that indicates whether two specified vectors are not equal. + The first vector to compare. + The second vector to compare. + true if left and right are not equal; otherwise, false. + + + Multiplies two vectors together. + The first vector. + The second vector. + The product vector. + + + Multiples the specified vector by the specified scalar value. + The vector. + The scalar value. + The scaled vector. + + + Multiples the scalar value by the specified vector. + The vector. + The scalar value. + The scaled vector. + + + Subtracts the second vector from the first. + The first vector. + The second vector. + The vector that results from subtracting right from left. + + + Negates the specified vector. + The vector to negate. + The negated vector. + + + Returns the reflection of a vector off a surface that has the specified normal. + The source vector. + The normal of the surface being reflected off. + The reflected vector. + + + Returns a vector whose elements are the square root of each of a specified vector's elements. + A vector. + The square root vector. + + + Subtracts the second vector from the first. + The first vector. + The second vector. + The difference vector. + + + Returns the string representation of the current instance using default formatting. + The string representation of the current instance. + + + Returns the string representation of the current instance using the specified format string to format individual elements. + A or that defines the format of individual elements. + The string representation of the current instance. + + + Returns the string representation of the current instance using the specified format string to format individual elements and the specified format provider to define culture-specific formatting. + A or that defines the format of individual elements. + A format provider that supplies culture-specific formatting information. + The string representation of the current instance. + + + Transforms a vector by a specified 3x2 matrix. + The vector to transform. + The transformation matrix. + The transformed vector. + + + Transforms a vector by a specified 4x4 matrix. + The vector to transform. + The transformation matrix. + The transformed vector. + + + Transforms a vector by the specified Quaternion rotation value. + The vector to rotate. + The rotation to apply. + The transformed vector. + + + Transforms a vector normal by the given 3x2 matrix. + The source vector. + The matrix. + The transformed vector. + + + Transforms a vector normal by the given 4x4 matrix. + The source vector. + The matrix. + The transformed vector. + + + Gets the vector (1,0). + The vector (1,0). + + + Gets the vector (0,1). + The vector (0,1). + + + The X component of the vector. + + + + The Y component of the vector. + + + + Returns a vector whose 2 elements are equal to zero. + A vector whose two elements are equal to zero (that is, it returns the vector (0,0). + + + Represents a vector with three single-precision floating-point values. + + + Creates a new object whose three elements have the same value. + The value to assign to all three elements. + + + Creates a new object from the specified object and the specified value. + The vector with two elements. + The additional value to assign to the field. + + + Creates a vector whose elements have the specified values. + The value to assign to the field. + The value to assign to the field. + The value to assign to the field. + + + Returns a vector whose elements are the absolute values of each of the specified vector's elements. + A vector. + The absolute value vector. + + + Adds two vectors together. + The first vector to add. + The second vector to add. + The summed vector. + + + Restricts a vector between a minimum and a maximum value. + The vector to restrict. + The minimum value. + The maximum value. + The restricted vector. + + + Copies the elements of the vector to a specified array. + The destination array. + array is null. + The number of elements in the current instance is greater than in the array. + array is multidimensional. + + + Copies the elements of the vector to a specified array starting at a specified index position. + The destination array. + The index at which to copy the first element of the vector. + array is null. + The number of elements in the current instance is greater than in the array. + index is less than zero. -or- index is greater than or equal to the array length. + array is multidimensional. + + + Computes the cross product of two vectors. + The first vector. + The second vector. + The cross product. + + + Computes the Euclidean distance between the two given points. + The first point. + The second point. + The distance. + + + Returns the Euclidean distance squared between two specified points. + The first point. + The second point. + The distance squared. + + + Divides the specified vector by a specified scalar value. + The vector. + The scalar value. + The vector that results from the division. + + + Divides the first vector by the second. + The first vector. + The second vector. + The vector resulting from the division. + + + Returns the dot product of two vectors. + The first vector. + The second vector. + The dot product. + + + Returns a value that indicates whether this instance and another vector are equal. + The other vector. + true if the two vectors are equal; otherwise, false. + + + Returns a value that indicates whether this instance and a specified object are equal. + The object to compare with the current instance. + true if the current instance and obj are equal; otherwise, false```. If <code data-dev-comment-type="paramref">obj</code> isnull, the method returnsfalse`. + + + Returns the hash code for this instance. + The hash code. + + + Returns the length of this vector object. + The vector's length. + + + Returns the length of the vector squared. + The vector's length squared. + + + Performs a linear interpolation between two vectors based on the given weighting. + The first vector. + The second vector. + A value between 0 and 1 that indicates the weight of value2. + The interpolated vector. + + + Returns a vector whose elements are the maximum of each of the pairs of elements in two specified vectors. + The first vector. + The second vector. + The maximized vector. + + + Returns a vector whose elements are the minimum of each of the pairs of elements in two specified vectors. + The first vector. + The second vector. + The minimized vector. + + + Multiplies a scalar value by a specified vector. + The scaled value. + The vector. + The scaled vector. + + + Multiplies two vectors together. + The first vector. + The second vector. + The product vector. + + + Multiplies a vector by a specified scalar. + The vector to multiply. + The scalar value. + The scaled vector. + + + Negates a specified vector. + The vector to negate. + The negated vector. + + + Returns a vector with the same direction as the specified vector, but with a length of one. + The vector to normalize. + The normalized vector. + + + Gets a vector whose 3 elements are equal to one. + A vector whose three elements are equal to one (that is, it returns the vector (1,1,1). + + + Adds two vectors together. + The first vector to add. + The second vector to add. + The summed vector. + + + Divides the first vector by the second. + The first vector. + The second vector. + The vector that results from dividing left by right. + + + Divides the specified vector by a specified scalar value. + The vector. + The scalar value. + The result of the division. + + + Returns a value that indicates whether each pair of elements in two specified vectors is equal. + The first vector to compare. + The second vector to compare. + true if left and right are equal; otherwise, false. + + + Returns a value that indicates whether two specified vectors are not equal. + The first vector to compare. + The second vector to compare. + true if left and right are not equal; otherwise, false. + + + Multiplies two vectors together. + The first vector. + The second vector. + The product vector. + + + Multiples the specified vector by the specified scalar value. + The vector. + The scalar value. + The scaled vector. + + + Multiples the scalar value by the specified vector. + The vector. + The scalar value. + The scaled vector. + + + Subtracts the second vector from the first. + The first vector. + The second vector. + The vector that results from subtracting right from left. + + + Negates the specified vector. + The vector to negate. + The negated vector. + + + Returns the reflection of a vector off a surface that has the specified normal. + The source vector. + The normal of the surface being reflected off. + The reflected vector. + + + Returns a vector whose elements are the square root of each of a specified vector's elements. + A vector. + The square root vector. + + + Subtracts the second vector from the first. + The first vector. + The second vector. + The difference vector. + + + Returns the string representation of the current instance using default formatting. + The string representation of the current instance. + + + Returns the string representation of the current instance using the specified format string to format individual elements. + A or that defines the format of individual elements. + The string representation of the current instance. + + + Returns the string representation of the current instance using the specified format string to format individual elements and the specified format provider to define culture-specific formatting. + A or that defines the format of individual elements. + A format provider that supplies culture-specific formatting information. + The string representation of the current instance. + + + Transforms a vector by a specified 4x4 matrix. + The vector to transform. + The transformation matrix. + The transformed vector. + + + Transforms a vector by the specified Quaternion rotation value. + The vector to rotate. + The rotation to apply. + The transformed vector. + + + Transforms a vector normal by the given 4x4 matrix. + The source vector. + The matrix. + The transformed vector. + + + Gets the vector (1,0,0). + The vector (1,0,0). + + + Gets the vector (0,1,0). + The vector (0,1,0).. + + + Gets the vector (0,0,1). + The vector (0,0,1). + + + The X component of the vector. + + + + The Y component of the vector. + + + + The Z component of the vector. + + + + Gets a vector whose 3 elements are equal to zero. + A vector whose three elements are equal to zero (that is, it returns the vector (0,0,0). + + + Represents a vector with four single-precision floating-point values. + + + Creates a new object whose four elements have the same value. + The value to assign to all four elements. + + + Constructs a new object from the specified object and a W component. + The vector to use for the X, Y, and Z components. + The W component. + + + Creates a new object from the specified object and a Z and a W component. + The vector to use for the X and Y components. + The Z component. + The W component. + + + Creates a vector whose elements have the specified values. + The value to assign to the field. + The value to assign to the field. + The value to assign to the field. + The value to assign to the field. + + + Returns a vector whose elements are the absolute values of each of the specified vector's elements. + A vector. + The absolute value vector. + + + Adds two vectors together. + The first vector to add. + The second vector to add. + The summed vector. + + + Restricts a vector between a minimum and a maximum value. + The vector to restrict. + The minimum value. + The maximum value. + The restricted vector. + + + Copies the elements of the vector to a specified array. + The destination array. + array is null. + The number of elements in the current instance is greater than in the array. + array is multidimensional. + + + Copies the elements of the vector to a specified array starting at a specified index position. + The destination array. + The index at which to copy the first element of the vector. + array is null. + The number of elements in the current instance is greater than in the array. + index is less than zero. -or- index is greater than or equal to the array length. + array is multidimensional. + + + Computes the Euclidean distance between the two given points. + The first point. + The second point. + The distance. + + + Returns the Euclidean distance squared between two specified points. + The first point. + The second point. + The distance squared. + + + Divides the first vector by the second. + The first vector. + The second vector. + The vector resulting from the division. + + + Divides the specified vector by a specified scalar value. + The vector. + The scalar value. + The vector that results from the division. + + + Returns the dot product of two vectors. + The first vector. + The second vector. + The dot product. + + + Returns a value that indicates whether this instance and another vector are equal. + The other vector. + true if the two vectors are equal; otherwise, false. + + + Returns a value that indicates whether this instance and a specified object are equal. + The object to compare with the current instance. + true if the current instance and obj are equal; otherwise, false```. If <code data-dev-comment-type="paramref">obj</code> isnull, the method returnsfalse`. + + + Returns the hash code for this instance. + The hash code. + + + Returns the length of this vector object. + The vector's length. + + + Returns the length of the vector squared. + The vector's length squared. + + + Performs a linear interpolation between two vectors based on the given weighting. + The first vector. + The second vector. + A value between 0 and 1 that indicates the weight of value2. + The interpolated vector. + + + Returns a vector whose elements are the maximum of each of the pairs of elements in two specified vectors. + The first vector. + The second vector. + The maximized vector. + + + Returns a vector whose elements are the minimum of each of the pairs of elements in two specified vectors. + The first vector. + The second vector. + The minimized vector. + + + Multiplies two vectors together. + The first vector. + The second vector. + The product vector. + + + Multiplies a vector by a specified scalar. + The vector to multiply. + The scalar value. + The scaled vector. + + + Multiplies a scalar value by a specified vector. + The scaled value. + The vector. + The scaled vector. + + + Negates a specified vector. + The vector to negate. + The negated vector. + + + Returns a vector with the same direction as the specified vector, but with a length of one. + The vector to normalize. + The normalized vector. + + + Gets a vector whose 4 elements are equal to one. + Returns . + + + Adds two vectors together. + The first vector to add. + The second vector to add. + The summed vector. + + + Divides the first vector by the second. + The first vector. + The second vector. + The vector that results from dividing left by right. + + + Divides the specified vector by a specified scalar value. + The vector. + The scalar value. + The result of the division. + + + Returns a value that indicates whether each pair of elements in two specified vectors is equal. + The first vector to compare. + The second vector to compare. + true if left and right are equal; otherwise, false. + + + Returns a value that indicates whether two specified vectors are not equal. + The first vector to compare. + The second vector to compare. + true if left and right are not equal; otherwise, false. + + + Multiplies two vectors together. + The first vector. + The second vector. + The product vector. + + + Multiples the specified vector by the specified scalar value. + The vector. + The scalar value. + The scaled vector. + + + Multiples the scalar value by the specified vector. + The vector. + The scalar value. + The scaled vector. + + + Subtracts the second vector from the first. + The first vector. + The second vector. + The vector that results from subtracting right from left. + + + Negates the specified vector. + The vector to negate. + The negated vector. + + + Returns a vector whose elements are the square root of each of a specified vector's elements. + A vector. + The square root vector. + + + Subtracts the second vector from the first. + The first vector. + The second vector. + The difference vector. + + + Returns the string representation of the current instance using default formatting. + The string representation of the current instance. + + + Returns the string representation of the current instance using the specified format string to format individual elements. + A or that defines the format of individual elements. + The string representation of the current instance. + + + Returns the string representation of the current instance using the specified format string to format individual elements and the specified format provider to define culture-specific formatting. + A or that defines the format of individual elements. + A format provider that supplies culture-specific formatting information. + The string representation of the current instance. + + + Transforms a four-dimensional vector by the specified Quaternion rotation value. + The vector to rotate. + The rotation to apply. + The transformed vector. + + + Transforms a four-dimensional vector by a specified 4x4 matrix. + The vector to transform. + The transformation matrix. + The transformed vector. + + + Transforms a three-dimensional vector by the specified Quaternion rotation value. + The vector to rotate. + The rotation to apply. + The transformed vector. + + + Transforms a two-dimensional vector by a specified 4x4 matrix. + The vector to transform. + The transformation matrix. + The transformed vector. + + + Transforms a two-dimensional vector by the specified Quaternion rotation value. + The vector to rotate. + The rotation to apply. + The transformed vector. + + + Transforms a three-dimensional vector by a specified 4x4 matrix. + The vector to transform. + The transformation matrix. + The transformed vector. + + + Gets the vector (0,0,0,1). + The vector (0,0,0,1). + + + Gets the vector (1,0,0,0). + The vector (1,0,0,0). + + + Gets the vector (0,1,0,0). + The vector (0,1,0,0).. + + + Gets a vector whose 4 elements are equal to zero. + The vector (0,0,1,0). + + + The W component of the vector. + + + + The X component of the vector. + + + + The Y component of the vector. + + + + The Z component of the vector. + + + + Gets a vector whose 4 elements are equal to zero. + A vector whose four elements are equal to zero (that is, it returns the vector (0,0,0,0). + + + \ No newline at end of file diff --git a/Assets/ARDK/Plugins/Niantic.Protobufs/System.Numerics.Vectors.4.4.0/netstandard2.0/Niantic.System.Numerics.Vectors.xml.meta b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Numerics.Vectors.4.4.0/netstandard2.0/Niantic.System.Numerics.Vectors.xml.meta new file mode 100644 index 0000000..2d25451 --- /dev/null +++ b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Numerics.Vectors.4.4.0/netstandard2.0/Niantic.System.Numerics.Vectors.xml.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 528abe9035e6f499b88bfe3d1c406767 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/Niantic.Protobufs/System.Runtime.CompilerServices.Unsafe.4.5.2.meta b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Runtime.CompilerServices.Unsafe.4.5.2.meta new file mode 100644 index 0000000..955363d --- /dev/null +++ b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Runtime.CompilerServices.Unsafe.4.5.2.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2c7ec84cc298c47d694ceae2cc30dabb +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/Niantic.Protobufs/System.Runtime.CompilerServices.Unsafe.4.5.2/netstandard2.0.meta b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Runtime.CompilerServices.Unsafe.4.5.2/netstandard2.0.meta new file mode 100644 index 0000000..949e03e --- /dev/null +++ b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Runtime.CompilerServices.Unsafe.4.5.2/netstandard2.0.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e8fc44ad5830746fbb329c223eb69f35 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/Niantic.Protobufs/System.Runtime.CompilerServices.Unsafe.4.5.2/netstandard2.0/Niantic.System.Runtime.CompilerServices.Unsafe.dll b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Runtime.CompilerServices.Unsafe.4.5.2/netstandard2.0/Niantic.System.Runtime.CompilerServices.Unsafe.dll new file mode 100644 index 0000000..d917796 Binary files /dev/null and b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Runtime.CompilerServices.Unsafe.4.5.2/netstandard2.0/Niantic.System.Runtime.CompilerServices.Unsafe.dll differ diff --git a/Assets/ARDK/Plugins/Niantic.Protobufs/System.Runtime.CompilerServices.Unsafe.4.5.2/netstandard2.0/Niantic.System.Runtime.CompilerServices.Unsafe.dll.meta b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Runtime.CompilerServices.Unsafe.4.5.2/netstandard2.0/Niantic.System.Runtime.CompilerServices.Unsafe.dll.meta new file mode 100644 index 0000000..6993f73 --- /dev/null +++ b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Runtime.CompilerServices.Unsafe.4.5.2/netstandard2.0/Niantic.System.Runtime.CompilerServices.Unsafe.dll.meta @@ -0,0 +1,86 @@ +fileFormatVersion: 2 +guid: 6ebeefaf59f0549c2a793f17d28c9f32 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 1 + validateReferences: 1 + platformData: + - first: + : Any + second: + enabled: 0 + settings: + Exclude Android: 0 + Exclude Editor: 0 + Exclude Linux64: 0 + Exclude OSXUniversal: 0 + Exclude Win: 0 + Exclude Win64: 0 + Exclude iOS: 0 + - first: + Android: Android + second: + enabled: 1 + settings: + CPU: ARMv7 + - first: + Any: + second: + enabled: 1 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Standalone: Linux64 + second: + enabled: 1 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 1 + settings: + CPU: None + - first: + Standalone: Win + second: + enabled: 1 + settings: + CPU: x86 + - first: + Standalone: Win64 + second: + enabled: 1 + settings: + CPU: x86_64 + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + CPU: AnyCPU + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/Niantic.Protobufs/System.Runtime.CompilerServices.Unsafe.4.5.2/netstandard2.0/Niantic.System.Runtime.CompilerServices.Unsafe.xml b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Runtime.CompilerServices.Unsafe.4.5.2/netstandard2.0/Niantic.System.Runtime.CompilerServices.Unsafe.xml new file mode 100644 index 0000000..6a7cfcf --- /dev/null +++ b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Runtime.CompilerServices.Unsafe.4.5.2/netstandard2.0/Niantic.System.Runtime.CompilerServices.Unsafe.xml @@ -0,0 +1,200 @@ + + + System.Runtime.CompilerServices.Unsafe + + + + Contains generic, low-level functionality for manipulating pointers. + + + Adds an element offset to the given reference. + The reference to add the offset to. + The offset to add. + The type of reference. + A new reference that reflects the addition of offset to pointer. + + + Adds an element offset to the given reference. + The reference to add the offset to. + The offset to add. + The type of reference. + A new reference that reflects the addition of offset to pointer. + + + Adds a byte offset to the given reference. + The reference to add the offset to. + The offset to add. + The type of reference. + A new reference that reflects the addition of byte offset to pointer. + + + Determines whether the specified references point to the same location. + The first reference to compare. + The second reference to compare. + The type of reference. + true if left and right point to the same location; otherwise, false. + + + Casts the given object to the specified type. + The object to cast. + The type which the object will be cast to. + The original object, casted to the given type. + + + Reinterprets the given reference as a reference to a value of type TTo. + The reference to reinterpret. + The type of reference to reinterpret.. + The desired type of the reference. + A reference to a value of type TTo. + + + Returns a pointer to the given by-ref parameter. + The object whose pointer is obtained. + The type of object. + A pointer to the given value. + + + Reinterprets the given location as a reference to a value of type T. + The location of the value to reference. + The type of the interpreted location. + A reference to a value of type T. + + + Determines the byte offset from origin to target from the given references. + The reference to origin. + The reference to target. + The type of reference. + Byte offset from origin to target i.e. target - origin. + + + Copies a value of type T to the given location. + The location to copy to. + A reference to the value to copy. + The type of value to copy. + + + Copies a value of type T to the given location. + The location to copy to. + A pointer to the value to copy. + The type of value to copy. + + + Copies bytes from the source address to the destination address. + The destination address to copy to. + The source address to copy from. + The number of bytes to copy. + + + Copies bytes from the source address to the destination address. + The destination address to copy to. + The source address to copy from. + The number of bytes to copy. + + + Copies bytes from the source address to the destination address +without assuming architecture dependent alignment of the addresses. + The destination address to copy to. + The source address to copy from. + The number of bytes to copy. + + + Copies bytes from the source address to the destination address +without assuming architecture dependent alignment of the addresses. + The destination address to copy to. + The source address to copy from. + The number of bytes to copy. + + + Initializes a block of memory at the given location with a given initial value. + The address of the start of the memory block to initialize. + The value to initialize the block to. + The number of bytes to initialize. + + + Initializes a block of memory at the given location with a given initial value. + The address of the start of the memory block to initialize. + The value to initialize the block to. + The number of bytes to initialize. + + + Initializes a block of memory at the given location with a given initial value +without assuming architecture dependent alignment of the address. + The address of the start of the memory block to initialize. + The value to initialize the block to. + The number of bytes to initialize. + + + Initializes a block of memory at the given location with a given initial value +without assuming architecture dependent alignment of the address. + The address of the start of the memory block to initialize. + The value to initialize the block to. + The number of bytes to initialize. + + + Reads a value of type T from the given location. + The location to read from. + The type to read. + An object of type T read from the given location. + + + Reads a value of type T from the given location +without assuming architecture dependent alignment of the addresses. + The location to read from. + The type to read. + An object of type T read from the given location. + + + Reads a value of type T from the given location +without assuming architecture dependent alignment of the addresses. + The location to read from. + The type to read. + An object of type T read from the given location. + + + Returns the size of an object of the given type parameter. + The type of object whose size is retrieved. + The size of an object of type T. + + + Subtracts an element offset from the given reference. + The reference to subtract the offset from. + The offset to subtract. + The type of reference. + A new reference that reflects the subraction of offset from pointer. + + + Subtracts an element offset from the given reference. + The reference to subtract the offset from. + The offset to subtract. + The type of reference. + A new reference that reflects the subraction of offset from pointer. + + + Subtracts a byte offset from the given reference. + The reference to subtract the offset from. + + The type of reference. + A new reference that reflects the subraction of byte offset from pointer. + + + Writes a value of type T to the given location. + The location to write to. + The value to write. + The type of value to write. + + + Writes a value of type T to the given location +without assuming architecture dependent alignment of the addresses. + The location to write to. + The value to write. + The type of value to write. + + + Writes a value of type T to the given location +without assuming architecture dependent alignment of the addresses. + The location to write to. + The value to write. + The type of value to write. + + + \ No newline at end of file diff --git a/Assets/ARDK/Plugins/Niantic.Protobufs/System.Runtime.CompilerServices.Unsafe.4.5.2/netstandard2.0/Niantic.System.Runtime.CompilerServices.Unsafe.xml.meta b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Runtime.CompilerServices.Unsafe.4.5.2/netstandard2.0/Niantic.System.Runtime.CompilerServices.Unsafe.xml.meta new file mode 100644 index 0000000..6f0b7b5 --- /dev/null +++ b/Assets/ARDK/Plugins/Niantic.Protobufs/System.Runtime.CompilerServices.Unsafe.4.5.2/netstandard2.0/Niantic.System.Runtime.CompilerServices.Unsafe.xml.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1a2a7e62d3e81454ca304f899f4bed92 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports.meta b/Assets/ARDK/Plugins/unity_exports.meta new file mode 100644 index 0000000..ce91f74 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e440cd228cf84fd8920c6dee295afb87 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform.meta new file mode 100644 index 0000000..1827b12 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e4633876f304c49a6955eb1cf44ee1e5 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins.meta new file mode 100644 index 0000000..a428d0b --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e23c58d6df6314586af0f13db7c7274d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/Android.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/Android.meta new file mode 100644 index 0000000..fba6d21 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/Android.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7389922b75c1947638fe6434b978c0e2 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/Android/arm64-v8a.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/Android/arm64-v8a.meta new file mode 100644 index 0000000..7a8f6c5 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/Android/arm64-v8a.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0cc67578bc1f143568f956e3fb426aa3 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/Android/arm64-v8a/libardk_client_platform.so b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/Android/arm64-v8a/libardk_client_platform.so new file mode 100644 index 0000000..09d8129 Binary files /dev/null and b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/Android/arm64-v8a/libardk_client_platform.so differ diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/Android/arm64-v8a/libardk_client_platform.so.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/Android/arm64-v8a/libardk_client_platform.so.meta new file mode 100644 index 0000000..ca34d0f --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/Android/arm64-v8a/libardk_client_platform.so.meta @@ -0,0 +1,107 @@ +PluginImporter: + executionOrder: {} + externalObjects: {} + iconMap: {} + isOverridable: 0 + isPreloaded: 0 + platformData: + - first: + ? '' + : Any + second: + enabled: 0 + settings: + Exclude Android: 0 + Exclude Editor: 1 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude OSXIntel: 1 + Exclude OSXIntel64: 1 + Exclude OSXUniversal: 1 + Exclude Win: 1 + Exclude Win64: 1 + - first: + Android: Android + second: + enabled: 1 + settings: + CPU: ARM64 + - first: + Editor: Editor + second: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Linux + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: x86_64 + - first: + Standalone: LinuxUniversal + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + ? '' + : OSXIntel + second: + enabled: 0 + settings: {} + - first: + ? '' + : OSXIntel64 + second: + enabled: 0 + settings: {} + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + iPhone: iOS + second: + enabled: 0 + settings: + CompileFlags: null + FrameworkDependencies: null + serializedVersion: 2 +fileFormatVersion: 2 +guid: cb711462fbd964337a6c868d43056c15 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/Android/arm64-v8a/libtensorflowlite.so b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/Android/arm64-v8a/libtensorflowlite.so new file mode 100644 index 0000000..dbc6a63 Binary files /dev/null and b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/Android/arm64-v8a/libtensorflowlite.so differ diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/Android/arm64-v8a/libtensorflowlite.so.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/Android/arm64-v8a/libtensorflowlite.so.meta new file mode 100644 index 0000000..9e8d93b --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/Android/arm64-v8a/libtensorflowlite.so.meta @@ -0,0 +1,107 @@ +PluginImporter: + executionOrder: {} + externalObjects: {} + iconMap: {} + isOverridable: 0 + isPreloaded: 0 + platformData: + - first: + ? '' + : Any + second: + enabled: 0 + settings: + Exclude Android: 0 + Exclude Editor: 1 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude OSXIntel: 1 + Exclude OSXIntel64: 1 + Exclude OSXUniversal: 1 + Exclude Win: 1 + Exclude Win64: 1 + - first: + Android: Android + second: + enabled: 1 + settings: + CPU: ARM64 + - first: + Editor: Editor + second: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Linux + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: x86_64 + - first: + Standalone: LinuxUniversal + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + ? '' + : OSXIntel + second: + enabled: 0 + settings: {} + - first: + ? '' + : OSXIntel64 + second: + enabled: 0 + settings: {} + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + iPhone: iOS + second: + enabled: 0 + settings: + CompileFlags: null + FrameworkDependencies: null + serializedVersion: 2 +fileFormatVersion: 2 +guid: 0a36ebcec9aeb499891ffafa048696a7 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/Android/armeabi-v7a.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/Android/armeabi-v7a.meta new file mode 100644 index 0000000..509c66d --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/Android/armeabi-v7a.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 31de753d5fa1b44c19980750f952ad7a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/Android/armeabi-v7a/libardk_client_platform.so b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/Android/armeabi-v7a/libardk_client_platform.so new file mode 100644 index 0000000..2a17a5a Binary files /dev/null and b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/Android/armeabi-v7a/libardk_client_platform.so differ diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/Android/armeabi-v7a/libardk_client_platform.so.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/Android/armeabi-v7a/libardk_client_platform.so.meta new file mode 100644 index 0000000..5874391 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/Android/armeabi-v7a/libardk_client_platform.so.meta @@ -0,0 +1,107 @@ +PluginImporter: + executionOrder: {} + externalObjects: {} + iconMap: {} + isOverridable: 0 + isPreloaded: 0 + platformData: + - first: + ? '' + : Any + second: + enabled: 0 + settings: + Exclude Android: 0 + Exclude Editor: 1 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude OSXIntel: 1 + Exclude OSXIntel64: 1 + Exclude OSXUniversal: 1 + Exclude Win: 1 + Exclude Win64: 1 + - first: + Android: Android + second: + enabled: 1 + settings: + CPU: ARMv7 + - first: + Editor: Editor + second: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Linux + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: x86_64 + - first: + Standalone: LinuxUniversal + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + ? '' + : OSXIntel + second: + enabled: 0 + settings: {} + - first: + ? '' + : OSXIntel64 + second: + enabled: 0 + settings: {} + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + iPhone: iOS + second: + enabled: 0 + settings: + CompileFlags: null + FrameworkDependencies: null + serializedVersion: 2 +fileFormatVersion: 2 +guid: cb0290e1eb2734e1f93bd15046e67005 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/Android/armeabi-v7a/libtensorflowlite.so b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/Android/armeabi-v7a/libtensorflowlite.so new file mode 100644 index 0000000..ed59a1b Binary files /dev/null and b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/Android/armeabi-v7a/libtensorflowlite.so differ diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/Android/armeabi-v7a/libtensorflowlite.so.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/Android/armeabi-v7a/libtensorflowlite.so.meta new file mode 100644 index 0000000..a22ec96 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/Android/armeabi-v7a/libtensorflowlite.so.meta @@ -0,0 +1,107 @@ +PluginImporter: + executionOrder: {} + externalObjects: {} + iconMap: {} + isOverridable: 0 + isPreloaded: 0 + platformData: + - first: + ? '' + : Any + second: + enabled: 0 + settings: + Exclude Android: 0 + Exclude Editor: 1 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude OSXIntel: 1 + Exclude OSXIntel64: 1 + Exclude OSXUniversal: 1 + Exclude Win: 1 + Exclude Win64: 1 + - first: + Android: Android + second: + enabled: 1 + settings: + CPU: ARMv7 + - first: + Editor: Editor + second: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Linux + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: x86_64 + - first: + Standalone: LinuxUniversal + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + ? '' + : OSXIntel + second: + enabled: 0 + settings: {} + - first: + ? '' + : OSXIntel64 + second: + enabled: 0 + settings: {} + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + iPhone: iOS + second: + enabled: 0 + settings: + CompileFlags: null + FrameworkDependencies: null + serializedVersion: 2 +fileFormatVersion: 2 +guid: ea65a4fb838e94d799fc97c8740e6ef3 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS.meta new file mode 100644 index 0000000..e1e3374 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e198eb1c5c77d41749f40312b847fa52 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64.meta new file mode 100644 index 0000000..b5ceecc --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: afa7c2dba45a5429aae7b879233fc9f5 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/ardk_client_platform.bundle.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/ardk_client_platform.bundle.meta new file mode 100644 index 0000000..39a9637 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/ardk_client_platform.bundle.meta @@ -0,0 +1,107 @@ +PluginImporter: + executionOrder: {} + externalObjects: {} + iconMap: {} + isOverridable: 0 + isPreloaded: 0 + platformData: + - first: + ? '' + : Any + second: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 0 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude OSXIntel: 0 + Exclude OSXIntel64: 0 + Exclude OSXUniversal: 0 + Exclude Win: 1 + Exclude Win64: 1 + - first: + Android: Android + second: + enabled: 0 + settings: + CPU: ARM64 + - first: + Editor: Editor + second: + enabled: 1 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: OSX + - first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Linux + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: x86_64 + - first: + Standalone: LinuxUniversal + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 1 + settings: + CPU: AnyCPU + - first: + ? '' + : OSXIntel + second: + enabled: 1 + settings: {} + - first: + ? '' + : OSXIntel64 + second: + enabled: 1 + settings: {} + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + iPhone: iOS + second: + enabled: 0 + settings: + CompileFlags: null + FrameworkDependencies: null + serializedVersion: 2 +fileFormatVersion: 2 +guid: 1e366481cf1047eb8b362bf69876e409 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/ardk_client_platform.bundle/Contents.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/ardk_client_platform.bundle/Contents.meta new file mode 100644 index 0000000..cc88fef --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/ardk_client_platform.bundle/Contents.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b62ceb084101c4cbca2202b670f18791 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/ardk_client_platform.bundle/Contents/Info.plist b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/ardk_client_platform.bundle/Contents/Info.plist new file mode 100644 index 0000000..2facb5b --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/ardk_client_platform.bundle/Contents/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ardk_client_platform + CFBundleGetInfoString + + CFBundleIconFile + + CFBundleIdentifier + + CFBundleInfoDictionaryVersion + 6.0 + CFBundleLongVersionString + + CFBundleName + + CFBundlePackageType + APPL + CFBundleShortVersionString + + CFBundleSignature + ???? + CFBundleVersion + + CSResourcesFileMapped + + NSHumanReadableCopyright + + + diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/ardk_client_platform.bundle/Contents/Info.plist.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/ardk_client_platform.bundle/Contents/Info.plist.meta new file mode 100644 index 0000000..dd90b07 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/ardk_client_platform.bundle/Contents/Info.plist.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: b21d8d4121d9d46b8004ccc605579577 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/ardk_client_platform.bundle/Contents/MacOS.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/ardk_client_platform.bundle/Contents/MacOS.meta new file mode 100644 index 0000000..0487df4 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/ardk_client_platform.bundle/Contents/MacOS.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 363856b2d5feb4349b267912e9884ae3 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/ardk_client_platform.bundle/Contents/MacOS/ardk_client_platform b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/ardk_client_platform.bundle/Contents/MacOS/ardk_client_platform new file mode 100644 index 0000000..b3413f9 Binary files /dev/null and b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/ardk_client_platform.bundle/Contents/MacOS/ardk_client_platform differ diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/ardk_client_platform.bundle/Contents/MacOS/ardk_client_platform.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/ardk_client_platform.bundle/Contents/MacOS/ardk_client_platform.meta new file mode 100644 index 0000000..cea4572 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/ardk_client_platform.bundle/Contents/MacOS/ardk_client_platform.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: d9fd1072b672c0067bf5287f8a4f9423 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework.meta new file mode 100644 index 0000000..dd5111e --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework.meta @@ -0,0 +1,107 @@ +PluginImporter: + executionOrder: {} + externalObjects: {} + iconMap: {} + isOverridable: 0 + isPreloaded: 0 + platformData: + - first: + ? '' + : Any + second: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 0 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude OSXIntel: 0 + Exclude OSXIntel64: 0 + Exclude OSXUniversal: 0 + Exclude Win: 1 + Exclude Win64: 1 + - first: + Android: Android + second: + enabled: 0 + settings: + CPU: ARM64 + - first: + Editor: Editor + second: + enabled: 1 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: OSX + - first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Linux + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: x86_64 + - first: + Standalone: LinuxUniversal + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 1 + settings: + CPU: AnyCPU + - first: + ? '' + : OSXIntel + second: + enabled: 1 + settings: {} + - first: + ? '' + : OSXIntel64 + second: + enabled: 1 + settings: {} + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + iPhone: iOS + second: + enabled: 0 + settings: + CompileFlags: null + FrameworkDependencies: null + serializedVersion: 2 +fileFormatVersion: 2 +guid: 288aee9facdf648c982645bff5845100 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Resources.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Resources.meta new file mode 100644 index 0000000..f927bf9 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Resources.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 78b80a61d97234f2db7c215c56fbd302 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Resources/Info.plist b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Resources/Info.plist new file mode 100644 index 0000000..5615bca --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Resources/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + infinitam + CFBundleIconFile + + CFBundleIdentifier + com.nianticlabs.infinitam + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + FMWK + CFBundleSignature + ???? + CFBundleVersion + 1652834257 + CFBundleShortVersionString + 2.0.0 + CSResourcesFileMapped + + MinimumOSVersion + 9.0 + + diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Resources/Info.plist.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Resources/Info.plist.meta new file mode 100644 index 0000000..be9acd3 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Resources/Info.plist.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 3ea957cdb61dc74018dbf9290513f37a diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Resources/default.metallib b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Resources/default.metallib new file mode 100644 index 0000000..6e1616f Binary files /dev/null and b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Resources/default.metallib differ diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Resources/default.metallib.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Resources/default.metallib.meta new file mode 100644 index 0000000..9a603ff --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Resources/default.metallib.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: e21dbe05b246964f23a8e6c5f60455dd diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions.meta new file mode 100644 index 0000000..3a6f2d5 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fc12884d7347c4b44b68ae15addde75b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/0.24.0.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/0.24.0.meta new file mode 100644 index 0000000..a67cd37 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/0.24.0.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 47d8c0e70a617402fbec0d6b27d61e87 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/0.24.0/Resources.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/0.24.0/Resources.meta new file mode 100644 index 0000000..e31a4d4 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/0.24.0/Resources.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2665a390b121f49d18ddaca209306195 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/0.24.0/Resources/Info.plist b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/0.24.0/Resources/Info.plist new file mode 100644 index 0000000..5615bca --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/0.24.0/Resources/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + infinitam + CFBundleIconFile + + CFBundleIdentifier + com.nianticlabs.infinitam + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + FMWK + CFBundleSignature + ???? + CFBundleVersion + 1652834257 + CFBundleShortVersionString + 2.0.0 + CSResourcesFileMapped + + MinimumOSVersion + 9.0 + + diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/0.24.0/Resources/Info.plist.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/0.24.0/Resources/Info.plist.meta new file mode 100644 index 0000000..9faaead --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/0.24.0/Resources/Info.plist.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: e554254c5e81f5ddbb02b317e1c0fcff diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/0.24.0/Resources/default.metallib b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/0.24.0/Resources/default.metallib new file mode 100644 index 0000000..6e1616f Binary files /dev/null and b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/0.24.0/Resources/default.metallib differ diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/0.24.0/Resources/default.metallib.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/0.24.0/Resources/default.metallib.meta new file mode 100644 index 0000000..c4cfe03 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/0.24.0/Resources/default.metallib.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: f2578f4a6390636cf26d30f5d1625d60 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/0.24.0/infinitam b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/0.24.0/infinitam new file mode 100644 index 0000000..b27b43a Binary files /dev/null and b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/0.24.0/infinitam differ diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/0.24.0/infinitam.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/0.24.0/infinitam.meta new file mode 100644 index 0000000..014056d --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/0.24.0/infinitam.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 9be7b13cdb8c1956e7f5bb8698505e86 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/Current.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/Current.meta new file mode 100644 index 0000000..3ecfa8e --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/Current.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e87ed4e40499243ddac18344b7ff7fe0 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/Current/Resources.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/Current/Resources.meta new file mode 100644 index 0000000..7d56391 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/Current/Resources.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3177525a3ad99450298f07e38c243fc0 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/Current/Resources/Info.plist b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/Current/Resources/Info.plist new file mode 100644 index 0000000..5615bca --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/Current/Resources/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + infinitam + CFBundleIconFile + + CFBundleIdentifier + com.nianticlabs.infinitam + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + FMWK + CFBundleSignature + ???? + CFBundleVersion + 1652834257 + CFBundleShortVersionString + 2.0.0 + CSResourcesFileMapped + + MinimumOSVersion + 9.0 + + diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/Current/Resources/Info.plist.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/Current/Resources/Info.plist.meta new file mode 100644 index 0000000..613e668 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/Current/Resources/Info.plist.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 714ae75cea884cfffdcac525bd6aece7 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/Current/Resources/default.metallib b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/Current/Resources/default.metallib new file mode 100644 index 0000000..6e1616f Binary files /dev/null and b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/Current/Resources/default.metallib differ diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/Current/Resources/default.metallib.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/Current/Resources/default.metallib.meta new file mode 100644 index 0000000..0b3cc9c --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/Current/Resources/default.metallib.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: d6c675803488ee4b742421b723d2c310 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/Current/infinitam b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/Current/infinitam new file mode 100644 index 0000000..b27b43a Binary files /dev/null and b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/Current/infinitam differ diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/Current/infinitam.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/Current/infinitam.meta new file mode 100644 index 0000000..ae82f94 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/Versions/Current/infinitam.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 5f42e51bd7cf4f10dbd951504390ef0c diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/infinitam b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/infinitam new file mode 100644 index 0000000..b27b43a Binary files /dev/null and b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/infinitam differ diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/infinitam.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/infinitam.meta new file mode 100644 index 0000000..e9539da --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/MacOS/x86_64/infinitam.framework/infinitam.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: fe939e1b02a36dac0487913927ba8d34 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS.meta new file mode 100644 index 0000000..4ad6d70 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 78f819d07a78c47809bdf431f7ab9a2b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS/ardk_client_platform.framework.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS/ardk_client_platform.framework.meta new file mode 100644 index 0000000..bbb6861 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS/ardk_client_platform.framework.meta @@ -0,0 +1,109 @@ +PluginImporter: + executionOrder: {} + externalObjects: {} + iconMap: {} + isOverridable: 0 + isPreloaded: 0 + platformData: + - first: + ? '' + : Any + second: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 1 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude OSXIntel: 1 + Exclude OSXIntel64: 1 + Exclude OSXUniversal: 1 + Exclude Win: 1 + Exclude Win64: 1 + Exclude iOS: 0 + - first: + Android: Android + second: + enabled: 0 + settings: + CPU: ARM64 + - first: + Editor: Editor + second: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Linux + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: x86_64 + - first: + Standalone: LinuxUniversal + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + ? '' + : OSXIntel + second: + enabled: 0 + settings: {} + - first: + ? '' + : OSXIntel64 + second: + enabled: 0 + settings: {} + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: 'true' + CompileFlags: null + FrameworkDependencies: Security;Foundation;UIKit;Metal + serializedVersion: 2 +fileFormatVersion: 2 +guid: e290ee1fc6ec9ef6c8e2cedeb4d13fe9 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS/ardk_client_platform.framework/Info.plist b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS/ardk_client_platform.framework/Info.plist new file mode 100644 index 0000000..badc2ee --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS/ardk_client_platform.framework/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ardk_client_platform + CFBundleIconFile + + CFBundleIdentifier + com.niantic.ardk-client-platform + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + FMWK + CFBundleSignature + ???? + CFBundleVersion + 1652833660 + CFBundleShortVersionString + 2.0.0 + CSResourcesFileMapped + + MinimumOSVersion + 9.0 + + diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS/ardk_client_platform.framework/Info.plist.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS/ardk_client_platform.framework/Info.plist.meta new file mode 100644 index 0000000..adf690c --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS/ardk_client_platform.framework/Info.plist.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: fa61d101dea9ca81b3927d7c3879c736 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS/ardk_client_platform.framework/ardk_client_platform b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS/ardk_client_platform.framework/ardk_client_platform new file mode 100644 index 0000000..f579119 Binary files /dev/null and b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS/ardk_client_platform.framework/ardk_client_platform differ diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS/ardk_client_platform.framework/ardk_client_platform.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS/ardk_client_platform.framework/ardk_client_platform.meta new file mode 100644 index 0000000..82df048 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS/ardk_client_platform.framework/ardk_client_platform.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 51198332ae0333766cc4152d052abffc diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS/infinitam.framework.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS/infinitam.framework.meta new file mode 100644 index 0000000..5b81fbe --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS/infinitam.framework.meta @@ -0,0 +1,109 @@ +PluginImporter: + executionOrder: {} + externalObjects: {} + iconMap: {} + isOverridable: 0 + isPreloaded: 0 + platformData: + - first: + ? '' + : Any + second: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 1 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude OSXIntel: 1 + Exclude OSXIntel64: 1 + Exclude OSXUniversal: 1 + Exclude Win: 1 + Exclude Win64: 1 + Exclude iOS: 0 + - first: + Android: Android + second: + enabled: 0 + settings: + CPU: ARM64 + - first: + Editor: Editor + second: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Linux + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: x86_64 + - first: + Standalone: LinuxUniversal + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + ? '' + : OSXIntel + second: + enabled: 0 + settings: {} + - first: + ? '' + : OSXIntel64 + second: + enabled: 0 + settings: {} + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: 'true' + CompileFlags: null + FrameworkDependencies: null + serializedVersion: 2 +fileFormatVersion: 2 +guid: 2d0636e877ada411cb06119b5cfb7969 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS/infinitam.framework/Info.plist b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS/infinitam.framework/Info.plist new file mode 100644 index 0000000..5a8c8d3 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS/infinitam.framework/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + infinitam + CFBundleIconFile + + CFBundleIdentifier + com.nianticlabs.infinitam + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + FMWK + CFBundleSignature + ???? + CFBundleVersion + 1652833660 + CFBundleShortVersionString + 2.0.0 + CSResourcesFileMapped + + MinimumOSVersion + 9.0 + + diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS/infinitam.framework/Info.plist.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS/infinitam.framework/Info.plist.meta new file mode 100644 index 0000000..af2d113 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS/infinitam.framework/Info.plist.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 9ed8e13ff3c118bda438b5e20e761d54 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS/infinitam.framework/default.metallib b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS/infinitam.framework/default.metallib new file mode 100644 index 0000000..dc519ad Binary files /dev/null and b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS/infinitam.framework/default.metallib differ diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS/infinitam.framework/default.metallib.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS/infinitam.framework/default.metallib.meta new file mode 100644 index 0000000..35b1799 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS/infinitam.framework/default.metallib.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: fdf1ca670f826257fb4720fe1a1ebab6 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS/infinitam.framework/infinitam b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS/infinitam.framework/infinitam new file mode 100644 index 0000000..db58acb Binary files /dev/null and b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS/infinitam.framework/infinitam differ diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS/infinitam.framework/infinitam.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS/infinitam.framework/infinitam.meta new file mode 100644 index 0000000..80bb0ee --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/Plugins/iOS/infinitam.framework/infinitam.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: a2ecbbf5305ec10ed44f1fcdf404c021 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/exports.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/exports.meta new file mode 100644 index 0000000..cb29b77 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/exports.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f39225088f4af4521aec49ec4d978a50 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/exports/arcore.aar b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/exports/arcore.aar new file mode 100644 index 0000000..8f4b4d7 Binary files /dev/null and b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/exports/arcore.aar differ diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/exports/arcore.aar.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/exports/arcore.aar.meta new file mode 100644 index 0000000..064ce38 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/exports/arcore.aar.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 10e0e87b0ed6f92842c21de3ddbe7189 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/exports/nar-dependencies.aar b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/exports/nar-dependencies.aar new file mode 100644 index 0000000..7e28141 Binary files /dev/null and b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/exports/nar-dependencies.aar differ diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/exports/nar-dependencies.aar.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/exports/nar-dependencies.aar.meta new file mode 100644 index 0000000..7e44d90 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/exports/nar-dependencies.aar.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: e2f4d77966c49dad485b50523fa780a0 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs.meta new file mode 100644 index 0000000..2a0c33f --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9c8354f3c67104d4d84133e073466b0f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application.meta new file mode 100644 index 0000000..4b9e285 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0f3f7935278ac477e90e0ff05b954b9e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers.meta new file mode 100644 index 0000000..5c93ddc --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3e88f5241ace24be69aec47fadf22d88 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/ByteBuffer.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/ByteBuffer.cs new file mode 100644 index 0000000..5e212dd --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/ByteBuffer.cs @@ -0,0 +1,891 @@ +/* + * Copyright 2014 Google Inc. All rights reserved. + * + * 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. + */ + +// There are 3 #defines that have an impact on performance / features of this ByteBuffer implementation +// +// UNSAFE_BYTEBUFFER +// This will use unsafe code to manipulate the underlying byte array. This +// can yield a reasonable performance increase. +// +// BYTEBUFFER_NO_BOUNDS_CHECK +// This will disable the bounds check asserts to the byte array. This can +// yield a small performance gain in normal code.. +// +// ENABLE_SPAN_T +// This will enable reading and writing blocks of memory with a Span instead if just +// T[]. You can also enable writing directly to shared memory or other types of memory +// by providing a custom implementation of ByteBufferAllocator. +// ENABLE_SPAN_T also requires UNSAFE_BYTEBUFFER to be defined +// +// Using UNSAFE_BYTEBUFFER and BYTEBUFFER_NO_BOUNDS_CHECK together can yield a +// performance gain of ~15% for some operations, however doing so is potentially +// dangerous. Do so at your own risk! +// + +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Text; + +#if ENABLE_SPAN_T +using System.Buffers.Binary; +#endif + +#if ENABLE_SPAN_T && !UNSAFE_BYTEBUFFER +#error ENABLE_SPAN_T requires UNSAFE_BYTEBUFFER to also be defined +#endif + +namespace FlatBuffers +{ + public abstract class ByteBufferAllocator + { +#if ENABLE_SPAN_T + public abstract Span Span { get; } + public abstract ReadOnlySpan ReadOnlySpan { get; } + public abstract Memory Memory { get; } + public abstract ReadOnlyMemory ReadOnlyMemory { get; } + +#else + public byte[] Buffer + { + get; + protected set; + } +#endif + + public int Length + { + get; + protected set; + } + + public abstract void GrowFront(int newSize); + } + + public sealed class ByteArrayAllocator : ByteBufferAllocator + { + private byte[] _buffer; + + public ByteArrayAllocator(byte[] buffer) + { + _buffer = buffer; + InitBuffer(); + } + + public override void GrowFront(int newSize) + { + if ((Length & 0xC0000000) != 0) + throw new Exception( + "ByteBuffer: cannot grow buffer beyond 2 gigabytes."); + + if (newSize < Length) + throw new Exception("ByteBuffer: cannot truncate buffer."); + + byte[] newBuffer = new byte[newSize]; + System.Buffer.BlockCopy(_buffer, 0, newBuffer, newSize - Length, Length); + _buffer = newBuffer; + InitBuffer(); + } + +#if ENABLE_SPAN_T + public override Span Span => _buffer; + public override ReadOnlySpan ReadOnlySpan => _buffer; + public override Memory Memory => _buffer; + public override ReadOnlyMemory ReadOnlyMemory => _buffer; +#endif + + private void InitBuffer() + { + Length = _buffer.Length; +#if !ENABLE_SPAN_T + Buffer = _buffer; +#endif + } + } + + /// + /// Class to mimic Java's ByteBuffer which is used heavily in Flatbuffers. + /// + public class ByteBuffer + { + private ByteBufferAllocator _buffer; + private int _pos; // Must track start of the buffer. + + public ByteBuffer(ByteBufferAllocator allocator, int position) + { + _buffer = allocator; + _pos = position; + } + + public ByteBuffer(int size) : this(new byte[size]) { } + + public ByteBuffer(byte[] buffer) : this(buffer, 0) { } + + public ByteBuffer(byte[] buffer, int pos) + { + _buffer = new ByteArrayAllocator(buffer); + _pos = pos; + } + + public int Position + { + get { return _pos; } + set { _pos = value; } + } + + public int Length { get { return _buffer.Length; } } + + public void Reset() + { + _pos = 0; + } + + // Create a new ByteBuffer on the same underlying data. + // The new ByteBuffer's position will be same as this buffer's. + public ByteBuffer Duplicate() + { + return new ByteBuffer(_buffer, Position); + } + + // Increases the size of the ByteBuffer, and copies the old data towards + // the end of the new buffer. + public void GrowFront(int newSize) + { + _buffer.GrowFront(newSize); + } + + public byte[] ToArray(int pos, int len) + { + return ToArray(pos, len); + } + + /// + /// A lookup of type sizes. Used instead of Marshal.SizeOf() which has additional + /// overhead, but also is compatible with generic functions for simplified code. + /// + private static Dictionary genericSizes = new Dictionary() + { + { typeof(bool), sizeof(bool) }, + { typeof(float), sizeof(float) }, + { typeof(double), sizeof(double) }, + { typeof(sbyte), sizeof(sbyte) }, + { typeof(byte), sizeof(byte) }, + { typeof(short), sizeof(short) }, + { typeof(ushort), sizeof(ushort) }, + { typeof(int), sizeof(int) }, + { typeof(uint), sizeof(uint) }, + { typeof(ulong), sizeof(ulong) }, + { typeof(long), sizeof(long) }, + }; + + /// + /// Get the wire-size (in bytes) of a type supported by flatbuffers. + /// + /// The type to get the wire size of + /// + public static int SizeOf() + { + return genericSizes[typeof(T)]; + } + + /// + /// Checks if the Type provided is supported as scalar value + /// + /// The Type to check + /// True if the type is a scalar type that is supported, falsed otherwise + public static bool IsSupportedType() + { + return genericSizes.ContainsKey(typeof(T)); + } + + /// + /// Get the wire-size (in bytes) of an typed array + /// + /// The type of the array + /// The array to get the size of + /// The number of bytes the array takes on wire + public static int ArraySize(T[] x) + { + return SizeOf() * x.Length; + } + +#if ENABLE_SPAN_T + public static int ArraySize(Span x) + { + return SizeOf() * x.Length; + } +#endif + + // Get a portion of the buffer casted into an array of type T, given + // the buffer position and length. +#if ENABLE_SPAN_T + public T[] ToArray(int pos, int len) + where T : struct + { + AssertOffsetAndLength(pos, len); + return MemoryMarshal.Cast(_buffer.ReadOnlySpan.Slice(pos)).Slice(0, len).ToArray(); + } +#else + public T[] ToArray(int pos, int len) + where T : struct + { + AssertOffsetAndLength(pos, len); + T[] arr = new T[len]; + Buffer.BlockCopy(_buffer.Buffer, pos, arr, 0, ArraySize(arr)); + return arr; + } +#endif + + public byte[] ToSizedArray() + { + return ToArray(Position, Length - Position); + } + + public byte[] ToFullArray() + { + return ToArray(0, Length); + } + +#if ENABLE_SPAN_T + public ReadOnlyMemory ToReadOnlyMemory(int pos, int len) + { + return _buffer.ReadOnlyMemory.Slice(pos, len); + } + + public Memory ToMemory(int pos, int len) + { + return _buffer.Memory.Slice(pos, len); + } + + public Span ToSpan(int pos, int len) + { + return _buffer.Span.Slice(pos, len); + } +#else + public ArraySegment ToArraySegment(int pos, int len) + { + return new ArraySegment(_buffer.Buffer, pos, len); + } + + public MemoryStream ToMemoryStream(int pos, int len) + { + return new MemoryStream(_buffer.Buffer, pos, len); + } +#endif + +#if !UNSAFE_BYTEBUFFER + // Pre-allocated helper arrays for convertion. + private float[] floathelper = new[] { 0.0f }; + private int[] inthelper = new[] { 0 }; + private double[] doublehelper = new[] { 0.0 }; + private ulong[] ulonghelper = new[] { 0UL }; +#endif // !UNSAFE_BYTEBUFFER + + // Helper functions for the unsafe version. + static public ushort ReverseBytes(ushort input) + { + return (ushort)(((input & 0x00FFU) << 8) | + ((input & 0xFF00U) >> 8)); + } + static public uint ReverseBytes(uint input) + { + return ((input & 0x000000FFU) << 24) | + ((input & 0x0000FF00U) << 8) | + ((input & 0x00FF0000U) >> 8) | + ((input & 0xFF000000U) >> 24); + } + static public ulong ReverseBytes(ulong input) + { + return (((input & 0x00000000000000FFUL) << 56) | + ((input & 0x000000000000FF00UL) << 40) | + ((input & 0x0000000000FF0000UL) << 24) | + ((input & 0x00000000FF000000UL) << 8) | + ((input & 0x000000FF00000000UL) >> 8) | + ((input & 0x0000FF0000000000UL) >> 24) | + ((input & 0x00FF000000000000UL) >> 40) | + ((input & 0xFF00000000000000UL) >> 56)); + } + +#if !UNSAFE_BYTEBUFFER + // Helper functions for the safe (but slower) version. + protected void WriteLittleEndian(int offset, int count, ulong data) + { + if (BitConverter.IsLittleEndian) + { + for (int i = 0; i < count; i++) + { + _buffer.Buffer[offset + i] = (byte)(data >> i * 8); + } + } + else + { + for (int i = 0; i < count; i++) + { + _buffer.Buffer[offset + count - 1 - i] = (byte)(data >> i * 8); + } + } + } + + protected ulong ReadLittleEndian(int offset, int count) + { + AssertOffsetAndLength(offset, count); + ulong r = 0; + if (BitConverter.IsLittleEndian) + { + for (int i = 0; i < count; i++) + { + r |= (ulong)_buffer.Buffer[offset + i] << i * 8; + } + } + else + { + for (int i = 0; i < count; i++) + { + r |= (ulong)_buffer.Buffer[offset + count - 1 - i] << i * 8; + } + } + return r; + } +#endif // !UNSAFE_BYTEBUFFER + + private void AssertOffsetAndLength(int offset, int length) + { +#if !BYTEBUFFER_NO_BOUNDS_CHECK + if (offset < 0 || + offset > _buffer.Length - length) + throw new ArgumentOutOfRangeException(); +#endif + } + +#if ENABLE_SPAN_T + + public void PutSbyte(int offset, sbyte value) + { + AssertOffsetAndLength(offset, sizeof(sbyte)); + _buffer.Span[offset] = (byte)value; + } + + public void PutByte(int offset, byte value) + { + AssertOffsetAndLength(offset, sizeof(byte)); + _buffer.Span[offset] = value; + } + + public void PutByte(int offset, byte value, int count) + { + AssertOffsetAndLength(offset, sizeof(byte) * count); + Span span = _buffer.Span.Slice(offset, count); + for (var i = 0; i < span.Length; ++i) + span[i] = value; + } +#else + public void PutSbyte(int offset, sbyte value) + { + AssertOffsetAndLength(offset, sizeof(sbyte)); + _buffer.Buffer[offset] = (byte)value; + } + + public void PutByte(int offset, byte value) + { + AssertOffsetAndLength(offset, sizeof(byte)); + _buffer.Buffer[offset] = value; + } + + public void PutByte(int offset, byte value, int count) + { + AssertOffsetAndLength(offset, sizeof(byte) * count); + for (var i = 0; i < count; ++i) + _buffer.Buffer[offset + i] = value; + } +#endif + + // this method exists in order to conform with Java ByteBuffer standards + public void Put(int offset, byte value) + { + PutByte(offset, value); + } + +#if ENABLE_SPAN_T + public unsafe void PutStringUTF8(int offset, string value) + { + AssertOffsetAndLength(offset, value.Length); + fixed (char* s = value) + { + fixed (byte* buffer = &MemoryMarshal.GetReference(_buffer.Span)) + { + Encoding.UTF8.GetBytes(s, value.Length, buffer + offset, Length - offset); + } + } + } +#else + public void PutStringUTF8(int offset, string value) + { + AssertOffsetAndLength(offset, value.Length); + Encoding.UTF8.GetBytes(value, 0, value.Length, + _buffer.Buffer, offset); + } +#endif + +#if UNSAFE_BYTEBUFFER + // Unsafe but more efficient versions of Put*. + public void PutShort(int offset, short value) + { + PutUshort(offset, (ushort)value); + } + + public unsafe void PutUshort(int offset, ushort value) + { + AssertOffsetAndLength(offset, sizeof(ushort)); +#if ENABLE_SPAN_T + Span span = _buffer.Span.Slice(offset); + BinaryPrimitives.WriteUInt16LittleEndian(span, value); +#else + fixed (byte* ptr = _buffer.Buffer) + { + *(ushort*)(ptr + offset) = BitConverter.IsLittleEndian + ? value + : ReverseBytes(value); + } +#endif + } + + public void PutInt(int offset, int value) + { + PutUint(offset, (uint)value); + } + + public unsafe void PutUint(int offset, uint value) + { + AssertOffsetAndLength(offset, sizeof(uint)); +#if ENABLE_SPAN_T + Span span = _buffer.Span.Slice(offset); + BinaryPrimitives.WriteUInt32LittleEndian(span, value); +#else + fixed (byte* ptr = _buffer.Buffer) + { + *(uint*)(ptr + offset) = BitConverter.IsLittleEndian + ? value + : ReverseBytes(value); + } +#endif + } + + public unsafe void PutLong(int offset, long value) + { + PutUlong(offset, (ulong)value); + } + + public unsafe void PutUlong(int offset, ulong value) + { + AssertOffsetAndLength(offset, sizeof(ulong)); +#if ENABLE_SPAN_T + Span span = _buffer.Span.Slice(offset); + BinaryPrimitives.WriteUInt64LittleEndian(span, value); +#else + fixed (byte* ptr = _buffer.Buffer) + { + *(ulong*)(ptr + offset) = BitConverter.IsLittleEndian + ? value + : ReverseBytes(value); + } +#endif + } + + public unsafe void PutFloat(int offset, float value) + { + AssertOffsetAndLength(offset, sizeof(float)); +#if ENABLE_SPAN_T + fixed (byte* ptr = &MemoryMarshal.GetReference(_buffer.Span)) +#else + fixed (byte* ptr = _buffer.Buffer) +#endif + { + if (BitConverter.IsLittleEndian) + { + *(float*)(ptr + offset) = value; + } + else + { + *(uint*)(ptr + offset) = ReverseBytes(*(uint*)(&value)); + } + } + } + + public unsafe void PutDouble(int offset, double value) + { + AssertOffsetAndLength(offset, sizeof(double)); +#if ENABLE_SPAN_T + fixed (byte* ptr = &MemoryMarshal.GetReference(_buffer.Span)) +#else + fixed (byte* ptr = _buffer.Buffer) +#endif + { + if (BitConverter.IsLittleEndian) + { + *(double*)(ptr + offset) = value; + } + else + { + *(ulong*)(ptr + offset) = ReverseBytes(*(ulong*)(&value)); + } + } + } +#else // !UNSAFE_BYTEBUFFER + // Slower versions of Put* for when unsafe code is not allowed. + public void PutShort(int offset, short value) + { + AssertOffsetAndLength(offset, sizeof(short)); + WriteLittleEndian(offset, sizeof(short), (ulong)value); + } + + public void PutUshort(int offset, ushort value) + { + AssertOffsetAndLength(offset, sizeof(ushort)); + WriteLittleEndian(offset, sizeof(ushort), (ulong)value); + } + + public void PutInt(int offset, int value) + { + AssertOffsetAndLength(offset, sizeof(int)); + WriteLittleEndian(offset, sizeof(int), (ulong)value); + } + + public void PutUint(int offset, uint value) + { + AssertOffsetAndLength(offset, sizeof(uint)); + WriteLittleEndian(offset, sizeof(uint), (ulong)value); + } + + public void PutLong(int offset, long value) + { + AssertOffsetAndLength(offset, sizeof(long)); + WriteLittleEndian(offset, sizeof(long), (ulong)value); + } + + public void PutUlong(int offset, ulong value) + { + AssertOffsetAndLength(offset, sizeof(ulong)); + WriteLittleEndian(offset, sizeof(ulong), value); + } + + public void PutFloat(int offset, float value) + { + AssertOffsetAndLength(offset, sizeof(float)); + floathelper[0] = value; + Buffer.BlockCopy(floathelper, 0, inthelper, 0, sizeof(float)); + WriteLittleEndian(offset, sizeof(float), (ulong)inthelper[0]); + } + + public void PutDouble(int offset, double value) + { + AssertOffsetAndLength(offset, sizeof(double)); + doublehelper[0] = value; + Buffer.BlockCopy(doublehelper, 0, ulonghelper, 0, sizeof(double)); + WriteLittleEndian(offset, sizeof(double), ulonghelper[0]); + } + +#endif // UNSAFE_BYTEBUFFER + +#if ENABLE_SPAN_T + public sbyte GetSbyte(int index) + { + AssertOffsetAndLength(index, sizeof(sbyte)); + return (sbyte)_buffer.ReadOnlySpan[index]; + } + + public byte Get(int index) + { + AssertOffsetAndLength(index, sizeof(byte)); + return _buffer.ReadOnlySpan[index]; + } +#else + public sbyte GetSbyte(int index) + { + AssertOffsetAndLength(index, sizeof(sbyte)); + return (sbyte)_buffer.Buffer[index]; + } + + public byte Get(int index) + { + AssertOffsetAndLength(index, sizeof(byte)); + return _buffer.Buffer[index]; + } +#endif + +#if ENABLE_SPAN_T + public unsafe string GetStringUTF8(int startPos, int len) + { + fixed (byte* buffer = &MemoryMarshal.GetReference(_buffer.ReadOnlySpan.Slice(startPos))) + { + return Encoding.UTF8.GetString(buffer, len); + } + } +#else + public string GetStringUTF8(int startPos, int len) + { + return Encoding.UTF8.GetString(_buffer.Buffer, startPos, len); + } +#endif + +#if UNSAFE_BYTEBUFFER + // Unsafe but more efficient versions of Get*. + public short GetShort(int offset) + { + return (short)GetUshort(offset); + } + + public unsafe ushort GetUshort(int offset) + { + AssertOffsetAndLength(offset, sizeof(ushort)); +#if ENABLE_SPAN_T + ReadOnlySpan span = _buffer.ReadOnlySpan.Slice(offset); + return BinaryPrimitives.ReadUInt16LittleEndian(span); +#else + fixed (byte* ptr = _buffer.Buffer) + { + return BitConverter.IsLittleEndian + ? *(ushort*)(ptr + offset) + : ReverseBytes(*(ushort*)(ptr + offset)); + } +#endif + } + + public int GetInt(int offset) + { + return (int)GetUint(offset); + } + + public unsafe uint GetUint(int offset) + { + AssertOffsetAndLength(offset, sizeof(uint)); +#if ENABLE_SPAN_T + ReadOnlySpan span = _buffer.ReadOnlySpan.Slice(offset); + return BinaryPrimitives.ReadUInt32LittleEndian(span); +#else + fixed (byte* ptr = _buffer.Buffer) + { + return BitConverter.IsLittleEndian + ? *(uint*)(ptr + offset) + : ReverseBytes(*(uint*)(ptr + offset)); + } +#endif + } + + public long GetLong(int offset) + { + return (long)GetUlong(offset); + } + + public unsafe ulong GetUlong(int offset) + { + AssertOffsetAndLength(offset, sizeof(ulong)); +#if ENABLE_SPAN_T + ReadOnlySpan span = _buffer.ReadOnlySpan.Slice(offset); + return BinaryPrimitives.ReadUInt64LittleEndian(span); +#else + fixed (byte* ptr = _buffer.Buffer) + { + return BitConverter.IsLittleEndian + ? *(ulong*)(ptr + offset) + : ReverseBytes(*(ulong*)(ptr + offset)); + } +#endif + } + + public unsafe float GetFloat(int offset) + { + AssertOffsetAndLength(offset, sizeof(float)); +#if ENABLE_SPAN_T + fixed (byte* ptr = &MemoryMarshal.GetReference(_buffer.ReadOnlySpan)) +#else + fixed (byte* ptr = _buffer.Buffer) +#endif + { + if (BitConverter.IsLittleEndian) + { + return *(float*)(ptr + offset); + } + else + { + uint uvalue = ReverseBytes(*(uint*)(ptr + offset)); + return *(float*)(&uvalue); + } + } + } + + public unsafe double GetDouble(int offset) + { + AssertOffsetAndLength(offset, sizeof(double)); +#if ENABLE_SPAN_T + fixed (byte* ptr = &MemoryMarshal.GetReference(_buffer.ReadOnlySpan)) +#else + fixed (byte* ptr = _buffer.Buffer) +#endif + { + if (BitConverter.IsLittleEndian) + { + return *(double*)(ptr + offset); + } + else + { + ulong uvalue = ReverseBytes(*(ulong*)(ptr + offset)); + return *(double*)(&uvalue); + } + } + } +#else // !UNSAFE_BYTEBUFFER + // Slower versions of Get* for when unsafe code is not allowed. + public short GetShort(int index) + { + return (short)ReadLittleEndian(index, sizeof(short)); + } + + public ushort GetUshort(int index) + { + return (ushort)ReadLittleEndian(index, sizeof(ushort)); + } + + public int GetInt(int index) + { + return (int)ReadLittleEndian(index, sizeof(int)); + } + + public uint GetUint(int index) + { + return (uint)ReadLittleEndian(index, sizeof(uint)); + } + + public long GetLong(int index) + { + return (long)ReadLittleEndian(index, sizeof(long)); + } + + public ulong GetUlong(int index) + { + return ReadLittleEndian(index, sizeof(ulong)); + } + + public float GetFloat(int index) + { + int i = (int)ReadLittleEndian(index, sizeof(float)); + inthelper[0] = i; + Buffer.BlockCopy(inthelper, 0, floathelper, 0, sizeof(float)); + return floathelper[0]; + } + + public double GetDouble(int index) + { + ulong i = ReadLittleEndian(index, sizeof(double)); + // There's Int64BitsToDouble but it uses unsafe code internally. + ulonghelper[0] = i; + Buffer.BlockCopy(ulonghelper, 0, doublehelper, 0, sizeof(double)); + return doublehelper[0]; + } +#endif // UNSAFE_BYTEBUFFER + + /// + /// Copies an array of type T into this buffer, ending at the given + /// offset into this buffer. The starting offset is calculated based on the length + /// of the array and is the value returned. + /// + /// The type of the input data (must be a struct) + /// The offset into this buffer where the copy will end + /// The array to copy data from + /// The 'start' location of this buffer now, after the copy completed + public int Put(int offset, T[] x) + where T : struct + { + if (x == null) + { + throw new ArgumentNullException("Cannot put a null array"); + } + + if (x.Length == 0) + { + throw new ArgumentException("Cannot put an empty array"); + } + + if (!IsSupportedType()) + { + throw new ArgumentException("Cannot put an array of type " + + typeof(T) + " into this buffer"); + } + + if (BitConverter.IsLittleEndian) + { + int numBytes = ByteBuffer.ArraySize(x); + offset -= numBytes; + AssertOffsetAndLength(offset, numBytes); + // if we are LE, just do a block copy +#if ENABLE_SPAN_T + MemoryMarshal.Cast(x).CopyTo(_buffer.Span.Slice(offset, numBytes)); +#else + Buffer.BlockCopy(x, 0, _buffer.Buffer, offset, numBytes); +#endif + } + else + { + throw new NotImplementedException("Big Endian Support not implemented yet " + + "for putting typed arrays"); + // if we are BE, we have to swap each element by itself + //for(int i = x.Length - 1; i >= 0; i--) + //{ + // todo: low priority, but need to genericize the Put() functions + //} + } + return offset; + } + +#if ENABLE_SPAN_T + public int Put(int offset, Span x) + where T : struct + { + if (x.Length == 0) + { + throw new ArgumentException("Cannot put an empty array"); + } + + if (!IsSupportedType()) + { + throw new ArgumentException("Cannot put an array of type " + + typeof(T) + " into this buffer"); + } + + if (BitConverter.IsLittleEndian) + { + int numBytes = ByteBuffer.ArraySize(x); + offset -= numBytes; + AssertOffsetAndLength(offset, numBytes); + // if we are LE, just do a block copy + MemoryMarshal.Cast(x).CopyTo(_buffer.Span.Slice(offset, numBytes)); + } + else + { + throw new NotImplementedException("Big Endian Support not implemented yet " + + "for putting typed arrays"); + // if we are BE, we have to swap each element by itself + //for(int i = x.Length - 1; i >= 0; i--) + //{ + // todo: low priority, but need to genericize the Put() functions + //} + } + return offset; + } +#endif + } +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/ByteBuffer.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/ByteBuffer.cs.meta new file mode 100644 index 0000000..fd81ad8 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/ByteBuffer.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: a9f2a32809f58c2a9877bbcb04dffa37 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/ByteBufferUtil.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/ByteBufferUtil.cs new file mode 100644 index 0000000..66e8266 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/ByteBufferUtil.cs @@ -0,0 +1,39 @@ +/* + * Copyright 2017 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; + +namespace FlatBuffers +{ + /// + /// Class that collects utility functions around `ByteBuffer`. + /// + public class ByteBufferUtil + { + // Extract the size prefix from a `ByteBuffer`. + public static int GetSizePrefix(ByteBuffer bb) { + return bb.GetInt(bb.Position); + } + + // Create a duplicate of a size-prefixed `ByteBuffer` that has its position + // advanced just past the size prefix. + public static ByteBuffer RemoveSizePrefix(ByteBuffer bb) { + ByteBuffer s = bb.Duplicate(); + s.Position += FlatBufferConstants.SizePrefixLength; + return s; + } + } +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/ByteBufferUtil.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/ByteBufferUtil.cs.meta new file mode 100644 index 0000000..230ff8e --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/ByteBufferUtil.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 03db12f626433e1baac6b2a9d33d8fa9 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/FlatBufferBuilder.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/FlatBufferBuilder.cs new file mode 100644 index 0000000..27c16b3 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/FlatBufferBuilder.cs @@ -0,0 +1,842 @@ +/* + * Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +using System; +using System.Collections.Generic; +using System.Text; + +/// @file +/// @addtogroup flatbuffers_csharp_api +/// @{ + +namespace FlatBuffers +{ + /// + /// Responsible for building up and accessing a FlatBuffer formatted byte + /// array (via ByteBuffer). + /// + public class FlatBufferBuilder + { + private int _space; + private ByteBuffer _bb; + private int _minAlign = 1; + + // The vtable for the current table (if _vtableSize >= 0) + private int[] _vtable = new int[16]; + // The size of the vtable. -1 indicates no vtable + private int _vtableSize = -1; + // Starting offset of the current struct/table. + private int _objectStart; + // List of offsets of all vtables. + private int[] _vtables = new int[16]; + // Number of entries in `vtables` in use. + private int _numVtables = 0; + // For the current vector being built. + private int _vectorNumElems = 0; + + // For CreateSharedString + private Dictionary _sharedStringMap = null; + + /// + /// Create a FlatBufferBuilder with a given initial size. + /// + /// + /// The initial size to use for the internal buffer. + /// + public FlatBufferBuilder(int initialSize) + { + if (initialSize <= 0) + throw new ArgumentOutOfRangeException("initialSize", + initialSize, "Must be greater than zero"); + _space = initialSize; + _bb = new ByteBuffer(initialSize); + } + + /// + /// Create a FlatBufferBuilder backed by the pased in ByteBuffer + /// + /// The ByteBuffer to write to + public FlatBufferBuilder(ByteBuffer buffer) + { + _bb = buffer; + _space = buffer.Length; + buffer.Reset(); + } + + /// + /// Reset the FlatBufferBuilder by purging all data that it holds. + /// + public void Clear() + { + _space = _bb.Length; + _bb.Reset(); + _minAlign = 1; + while (_vtableSize > 0) _vtable[--_vtableSize] = 0; + _vtableSize = -1; + _objectStart = 0; + _numVtables = 0; + _vectorNumElems = 0; + } + + /// + /// Gets and sets a Boolean to disable the optimization when serializing + /// default values to a Table. + /// + /// In order to save space, fields that are set to their default value + /// don't get serialized into the buffer. + /// + public bool ForceDefaults { get; set; } + + /// @cond FLATBUFFERS_INTERNAL + + public int Offset { get { return _bb.Length - _space; } } + + public void Pad(int size) + { + _bb.PutByte(_space -= size, 0, size); + } + + // Doubles the size of the ByteBuffer, and copies the old data towards + // the end of the new buffer (since we build the buffer backwards). + void GrowBuffer() + { + _bb.GrowFront(_bb.Length << 1); + } + + // Prepare to write an element of `size` after `additional_bytes` + // have been written, e.g. if you write a string, you need to align + // such the int length field is aligned to SIZEOF_INT, and the string + // data follows it directly. + // If all you need to do is align, `additional_bytes` will be 0. + public void Prep(int size, int additionalBytes) + { + // Track the biggest thing we've ever aligned to. + if (size > _minAlign) + _minAlign = size; + // Find the amount of alignment needed such that `size` is properly + // aligned after `additional_bytes` + var alignSize = + ((~((int)_bb.Length - _space + additionalBytes)) + 1) & + (size - 1); + // Reallocate the buffer if needed. + while (_space < alignSize + size + additionalBytes) + { + var oldBufSize = (int)_bb.Length; + GrowBuffer(); + _space += (int)_bb.Length - oldBufSize; + + } + if (alignSize > 0) + Pad(alignSize); + } + + public void PutBool(bool x) + { + _bb.PutByte(_space -= sizeof(byte), (byte)(x ? 1 : 0)); + } + + public void PutSbyte(sbyte x) + { + _bb.PutSbyte(_space -= sizeof(sbyte), x); + } + + public void PutByte(byte x) + { + _bb.PutByte(_space -= sizeof(byte), x); + } + + public void PutShort(short x) + { + _bb.PutShort(_space -= sizeof(short), x); + } + + public void PutUshort(ushort x) + { + _bb.PutUshort(_space -= sizeof(ushort), x); + } + + public void PutInt(int x) + { + _bb.PutInt(_space -= sizeof(int), x); + } + + public void PutUint(uint x) + { + _bb.PutUint(_space -= sizeof(uint), x); + } + + public void PutLong(long x) + { + _bb.PutLong(_space -= sizeof(long), x); + } + + public void PutUlong(ulong x) + { + _bb.PutUlong(_space -= sizeof(ulong), x); + } + + public void PutFloat(float x) + { + _bb.PutFloat(_space -= sizeof(float), x); + } + + /// + /// Puts an array of type T into this builder at the + /// current offset + /// + /// The type of the input data + /// The array to copy data from + public void Put(T[] x) + where T : struct + { + _space = _bb.Put(_space, x); + } + +#if ENABLE_SPAN_T + /// + /// Puts a span of type T into this builder at the + /// current offset + /// + /// The type of the input data + /// The span to copy data from + public void Put(Span x) + where T : struct + { + _space = _bb.Put(_space, x); + } +#endif + + public void PutDouble(double x) + { + _bb.PutDouble(_space -= sizeof(double), x); + } + /// @endcond + + /// + /// Add a `bool` to the buffer (aligns the data and grows if necessary). + /// + /// The `bool` to add to the buffer. + public void AddBool(bool x) { Prep(sizeof(byte), 0); PutBool(x); } + + /// + /// Add a `sbyte` to the buffer (aligns the data and grows if necessary). + /// + /// The `sbyte` to add to the buffer. + public void AddSbyte(sbyte x) { Prep(sizeof(sbyte), 0); PutSbyte(x); } + + /// + /// Add a `byte` to the buffer (aligns the data and grows if necessary). + /// + /// The `byte` to add to the buffer. + public void AddByte(byte x) { Prep(sizeof(byte), 0); PutByte(x); } + + /// + /// Add a `short` to the buffer (aligns the data and grows if necessary). + /// + /// The `short` to add to the buffer. + public void AddShort(short x) { Prep(sizeof(short), 0); PutShort(x); } + + /// + /// Add an `ushort` to the buffer (aligns the data and grows if necessary). + /// + /// The `ushort` to add to the buffer. + public void AddUshort(ushort x) { Prep(sizeof(ushort), 0); PutUshort(x); } + + /// + /// Add an `int` to the buffer (aligns the data and grows if necessary). + /// + /// The `int` to add to the buffer. + public void AddInt(int x) { Prep(sizeof(int), 0); PutInt(x); } + + /// + /// Add an `uint` to the buffer (aligns the data and grows if necessary). + /// + /// The `uint` to add to the buffer. + public void AddUint(uint x) { Prep(sizeof(uint), 0); PutUint(x); } + + /// + /// Add a `long` to the buffer (aligns the data and grows if necessary). + /// + /// The `long` to add to the buffer. + public void AddLong(long x) { Prep(sizeof(long), 0); PutLong(x); } + + /// + /// Add an `ulong` to the buffer (aligns the data and grows if necessary). + /// + /// The `ulong` to add to the buffer. + public void AddUlong(ulong x) { Prep(sizeof(ulong), 0); PutUlong(x); } + + /// + /// Add a `float` to the buffer (aligns the data and grows if necessary). + /// + /// The `float` to add to the buffer. + public void AddFloat(float x) { Prep(sizeof(float), 0); PutFloat(x); } + + /// + /// Add an array of type T to the buffer (aligns the data and grows if necessary). + /// + /// The type of the input data + /// The array to copy data from + public void Add(T[] x) + where T : struct + { + if (x == null) + { + throw new ArgumentNullException("Cannot add a null array"); + } + + if( x.Length == 0) + { + // don't do anything if the array is empty + return; + } + + if(!ByteBuffer.IsSupportedType()) + { + throw new ArgumentException("Cannot add this Type array to the builder"); + } + + int size = ByteBuffer.SizeOf(); + // Need to prep on size (for data alignment) and then we pass the + // rest of the length (minus 1) as additional bytes + Prep(size, size * (x.Length - 1)); + Put(x); + } + +#if ENABLE_SPAN_T + /// + /// Add a span of type T to the buffer (aligns the data and grows if necessary). + /// + /// The type of the input data + /// The span to copy data from + public void Add(Span x) + where T : struct + { + if (!ByteBuffer.IsSupportedType()) + { + throw new ArgumentException("Cannot add this Type array to the builder"); + } + + int size = ByteBuffer.SizeOf(); + // Need to prep on size (for data alignment) and then we pass the + // rest of the length (minus 1) as additional bytes + Prep(size, size * (x.Length - 1)); + Put(x); + } +#endif + + /// + /// Add a `double` to the buffer (aligns the data and grows if necessary). + /// + /// The `double` to add to the buffer. + public void AddDouble(double x) { Prep(sizeof(double), 0); + PutDouble(x); } + + /// + /// Adds an offset, relative to where it will be written. + /// + /// The offset to add to the buffer. + public void AddOffset(int off) + { + Prep(sizeof(int), 0); // Ensure alignment is already done. + if (off > Offset) + throw new ArgumentException(); + + off = Offset - off + sizeof(int); + PutInt(off); + } + + /// @cond FLATBUFFERS_INTERNAL + public void StartVector(int elemSize, int count, int alignment) + { + NotNested(); + _vectorNumElems = count; + Prep(sizeof(int), elemSize * count); + Prep(alignment, elemSize * count); // Just in case alignment > int. + } + /// @endcond + + /// + /// Writes data necessary to finish a vector construction. + /// + public VectorOffset EndVector() + { + PutInt(_vectorNumElems); + return new VectorOffset(Offset); + } + + /// + /// Creates a vector of tables. + /// + /// Offsets of the tables. + public VectorOffset CreateVectorOfTables(Offset[] offsets) where T : struct + { + NotNested(); + StartVector(sizeof(int), offsets.Length, sizeof(int)); + for (int i = offsets.Length - 1; i >= 0; i--) AddOffset(offsets[i].Value); + return EndVector(); + } + + /// @cond FLATBUFFERS_INTENRAL + public void Nested(int obj) + { + // Structs are always stored inline, so need to be created right + // where they are used. You'll get this assert if you created it + // elsewhere. + if (obj != Offset) + throw new Exception( + "FlatBuffers: struct must be serialized inline."); + } + + public void NotNested() + { + // You should not be creating any other objects or strings/vectors + // while an object is being constructed + if (_vtableSize >= 0) + throw new Exception( + "FlatBuffers: object serialization must not be nested."); + } + + public void StartTable(int numfields) + { + if (numfields < 0) + throw new ArgumentOutOfRangeException("Flatbuffers: invalid numfields"); + + NotNested(); + + if (_vtable.Length < numfields) + _vtable = new int[numfields]; + + _vtableSize = numfields; + _objectStart = Offset; + } + + + // Set the current vtable at `voffset` to the current location in the + // buffer. + public void Slot(int voffset) + { + if (voffset >= _vtableSize) + throw new IndexOutOfRangeException("Flatbuffers: invalid voffset"); + + _vtable[voffset] = Offset; + } + + /// + /// Adds a Boolean to the Table at index `o` in its vtable using the value `x` and default `d` + /// + /// The index into the vtable + /// The value to put into the buffer. If the value is equal to the default + /// and is false, the value will be skipped. + /// The default value to compare the value against + public void AddBool(int o, bool x, bool d) { if (ForceDefaults || x != d) { AddBool(x); Slot(o); } } + + /// + /// Adds a SByte to the Table at index `o` in its vtable using the value `x` and default `d` + /// + /// The index into the vtable + /// The value to put into the buffer. If the value is equal to the default + /// and is false, the value will be skipped. + /// The default value to compare the value against + public void AddSbyte(int o, sbyte x, sbyte d) { if (ForceDefaults || x != d) { AddSbyte(x); Slot(o); } } + + /// + /// Adds a Byte to the Table at index `o` in its vtable using the value `x` and default `d` + /// + /// The index into the vtable + /// The value to put into the buffer. If the value is equal to the default + /// and is false, the value will be skipped. + /// The default value to compare the value against + public void AddByte(int o, byte x, byte d) { if (ForceDefaults || x != d) { AddByte(x); Slot(o); } } + + /// + /// Adds a Int16 to the Table at index `o` in its vtable using the value `x` and default `d` + /// + /// The index into the vtable + /// The value to put into the buffer. If the value is equal to the default + /// and is false, the value will be skipped. + /// The default value to compare the value against + public void AddShort(int o, short x, int d) { if (ForceDefaults || x != d) { AddShort(x); Slot(o); } } + + /// + /// Adds a UInt16 to the Table at index `o` in its vtable using the value `x` and default `d` + /// + /// The index into the vtable + /// The value to put into the buffer. If the value is equal to the default + /// and is false, the value will be skipped. + /// The default value to compare the value against + public void AddUshort(int o, ushort x, ushort d) { if (ForceDefaults || x != d) { AddUshort(x); Slot(o); } } + + /// + /// Adds an Int32 to the Table at index `o` in its vtable using the value `x` and default `d` + /// + /// The index into the vtable + /// The value to put into the buffer. If the value is equal to the default + /// and is false, the value will be skipped. + /// The default value to compare the value against + public void AddInt(int o, int x, int d) { if (ForceDefaults || x != d) { AddInt(x); Slot(o); } } + + /// + /// Adds a UInt32 to the Table at index `o` in its vtable using the value `x` and default `d` + /// + /// The index into the vtable + /// The value to put into the buffer. If the value is equal to the default + /// and is false, the value will be skipped. + /// The default value to compare the value against + public void AddUint(int o, uint x, uint d) { if (ForceDefaults || x != d) { AddUint(x); Slot(o); } } + + /// + /// Adds an Int64 to the Table at index `o` in its vtable using the value `x` and default `d` + /// + /// The index into the vtable + /// The value to put into the buffer. If the value is equal to the default + /// and is false, the value will be skipped. + /// The default value to compare the value against + public void AddLong(int o, long x, long d) { if (ForceDefaults || x != d) { AddLong(x); Slot(o); } } + + /// + /// Adds a UInt64 to the Table at index `o` in its vtable using the value `x` and default `d` + /// + /// The index into the vtable + /// The value to put into the buffer. If the value is equal to the default + /// and is false, the value will be skipped. + /// The default value to compare the value against + public void AddUlong(int o, ulong x, ulong d) { if (ForceDefaults || x != d) { AddUlong(x); Slot(o); } } + + /// + /// Adds a Single to the Table at index `o` in its vtable using the value `x` and default `d` + /// + /// The index into the vtable + /// The value to put into the buffer. If the value is equal to the default + /// and is false, the value will be skipped. + /// The default value to compare the value against + public void AddFloat(int o, float x, double d) { if (ForceDefaults || x != d) { AddFloat(x); Slot(o); } } + + /// + /// Adds a Double to the Table at index `o` in its vtable using the value `x` and default `d` + /// + /// The index into the vtable + /// The value to put into the buffer. If the value is equal to the default + /// and is false, the value will be skipped. + /// The default value to compare the value against + public void AddDouble(int o, double x, double d) { if (ForceDefaults || x != d) { AddDouble(x); Slot(o); } } + + /// + /// Adds a buffer offset to the Table at index `o` in its vtable using the value `x` and default `d` + /// + /// The index into the vtable + /// The value to put into the buffer. If the value is equal to the default + /// the value will be skipped. + /// The default value to compare the value against + public void AddOffset(int o, int x, int d) { if (x != d) { AddOffset(x); Slot(o); } } + /// @endcond + + /// + /// Encode the string `s` in the buffer using UTF-8. + /// + /// The string to encode. + /// + /// The offset in the buffer where the encoded string starts. + /// + public StringOffset CreateString(string s) + { + NotNested(); + AddByte(0); + var utf8StringLen = Encoding.UTF8.GetByteCount(s); + StartVector(1, utf8StringLen, 1); + _bb.PutStringUTF8(_space -= utf8StringLen, s); + return new StringOffset(EndVector().Value); + } + + +#if ENABLE_SPAN_T + /// + /// Creates a string in the buffer from a Span containing + /// a UTF8 string. + /// + /// the UTF8 string to add to the buffer + /// + /// The offset in the buffer where the encoded string starts. + /// + public StringOffset CreateUTF8String(Span chars) + { + NotNested(); + AddByte(0); + var utf8StringLen = chars.Length; + StartVector(1, utf8StringLen, 1); + _space = _bb.Put(_space, chars); + return new StringOffset(EndVector().Value); + } +#endif + + /// + /// Store a string in the buffer, which can contain any binary data. + /// If a string with this exact contents has already been serialized before, + /// instead simply returns the offset of the existing string. + /// + /// The string to encode. + /// + /// The offset in the buffer where the encoded string starts. + /// + public StringOffset CreateSharedString(string s) + { + if (_sharedStringMap == null) + { + _sharedStringMap = new Dictionary(); + } + + if (_sharedStringMap.ContainsKey(s)) + { + return _sharedStringMap[s]; + } + + var stringOffset = CreateString(s); + _sharedStringMap.Add(s, stringOffset); + return stringOffset; + } + + /// @cond FLATBUFFERS_INTERNAL + // Structs are stored inline, so nothing additional is being added. + // `d` is always 0. + public void AddStruct(int voffset, int x, int d) + { + if (x != d) + { + Nested(x); + Slot(voffset); + } + } + + public int EndTable() + { + if (_vtableSize < 0) + throw new InvalidOperationException( + "Flatbuffers: calling EndTable without a StartTable"); + + AddInt((int)0); + var vtableloc = Offset; + // Write out the current vtable. + int i = _vtableSize - 1; + // Trim trailing zeroes. + for (; i >= 0 && _vtable[i] == 0; i--) {} + int trimmedSize = i + 1; + for (; i >= 0 ; i--) { + // Offset relative to the start of the table. + short off = (short)(_vtable[i] != 0 + ? vtableloc - _vtable[i] + : 0); + AddShort(off); + + // clear out written entry + _vtable[i] = 0; + } + + const int standardFields = 2; // The fields below: + AddShort((short)(vtableloc - _objectStart)); + AddShort((short)((trimmedSize + standardFields) * + sizeof(short))); + + // Search for an existing vtable that matches the current one. + int existingVtable = 0; + for (i = 0; i < _numVtables; i++) { + int vt1 = _bb.Length - _vtables[i]; + int vt2 = _space; + short len = _bb.GetShort(vt1); + if (len == _bb.GetShort(vt2)) { + for (int j = sizeof(short); j < len; j += sizeof(short)) { + if (_bb.GetShort(vt1 + j) != _bb.GetShort(vt2 + j)) { + goto endLoop; + } + } + existingVtable = _vtables[i]; + break; + } + + endLoop: { } + } + + if (existingVtable != 0) { + // Found a match: + // Remove the current vtable. + _space = _bb.Length - vtableloc; + // Point table to existing vtable. + _bb.PutInt(_space, existingVtable - vtableloc); + } else { + // No match: + // Add the location of the current vtable to the list of + // vtables. + if (_numVtables == _vtables.Length) + { + // Arrays.CopyOf(vtables num_vtables * 2); + var newvtables = new int[ _numVtables * 2]; + Array.Copy(_vtables, newvtables, _vtables.Length); + + _vtables = newvtables; + }; + _vtables[_numVtables++] = Offset; + // Point table to current vtable. + _bb.PutInt(_bb.Length - vtableloc, Offset - vtableloc); + } + + _vtableSize = -1; + return vtableloc; + } + + // This checks a required field has been set in a given table that has + // just been constructed. + public void Required(int table, int field) + { + int table_start = _bb.Length - table; + int vtable_start = table_start - _bb.GetInt(table_start); + bool ok = _bb.GetShort(vtable_start + field) != 0; + // If this fails, the caller will show what field needs to be set. + if (!ok) + throw new InvalidOperationException("FlatBuffers: field " + field + + " must be set"); + } + /// @endcond + + /// + /// Finalize a buffer, pointing to the given `root_table`. + /// + /// + /// An offset to be added to the buffer. + /// + /// + /// Whether to prefix the size to the buffer. + /// + protected void Finish(int rootTable, bool sizePrefix) + { + Prep(_minAlign, sizeof(int) + (sizePrefix ? sizeof(int) : 0)); + AddOffset(rootTable); + if (sizePrefix) { + AddInt(_bb.Length - _space); + } + _bb.Position = _space; + } + + /// + /// Finalize a buffer, pointing to the given `root_table`. + /// + /// + /// An offset to be added to the buffer. + /// + public void Finish(int rootTable) + { + Finish(rootTable, false); + } + + /// + /// Finalize a buffer, pointing to the given `root_table`, with the size prefixed. + /// + /// + /// An offset to be added to the buffer. + /// + public void FinishSizePrefixed(int rootTable) + { + Finish(rootTable, true); + } + + /// + /// Get the ByteBuffer representing the FlatBuffer. + /// + /// + /// This is typically only called after you call `Finish()`. + /// The actual data starts at the ByteBuffer's current position, + /// not necessarily at `0`. + /// + /// + /// Returns the ByteBuffer for this FlatBuffer. + /// + public ByteBuffer DataBuffer { get { return _bb; } } + + /// + /// A utility function to copy and return the ByteBuffer data as a + /// `byte[]`. + /// + /// + /// A full copy of the FlatBuffer data. + /// + public byte[] SizedByteArray() + { + return _bb.ToSizedArray(); + } + + /// + /// Finalize a buffer, pointing to the given `rootTable`. + /// + /// + /// An offset to be added to the buffer. + /// + /// + /// A FlatBuffer file identifier to be added to the buffer before + /// `root_table`. + /// + /// + /// Whether to prefix the size to the buffer. + /// + protected void Finish(int rootTable, string fileIdentifier, bool sizePrefix) + { + Prep(_minAlign, sizeof(int) + (sizePrefix ? sizeof(int) : 0) + + FlatBufferConstants.FileIdentifierLength); + if (fileIdentifier.Length != + FlatBufferConstants.FileIdentifierLength) + throw new ArgumentException( + "FlatBuffers: file identifier must be length " + + FlatBufferConstants.FileIdentifierLength, + "fileIdentifier"); + for (int i = FlatBufferConstants.FileIdentifierLength - 1; i >= 0; + i--) + { + AddByte((byte)fileIdentifier[i]); + } + Finish(rootTable, sizePrefix); + } + + /// + /// Finalize a buffer, pointing to the given `rootTable`. + /// + /// + /// An offset to be added to the buffer. + /// + /// + /// A FlatBuffer file identifier to be added to the buffer before + /// `root_table`. + /// + public void Finish(int rootTable, string fileIdentifier) + { + Finish(rootTable, fileIdentifier, false); + } + + /// + /// Finalize a buffer, pointing to the given `rootTable`, with the size prefixed. + /// + /// + /// An offset to be added to the buffer. + /// + /// + /// A FlatBuffer file identifier to be added to the buffer before + /// `root_table`. + /// + public void FinishSizePrefixed(int rootTable, string fileIdentifier) + { + Finish(rootTable, fileIdentifier, true); + } + } +} + +/// @} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/FlatBufferBuilder.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/FlatBufferBuilder.cs.meta new file mode 100644 index 0000000..46a830e --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/FlatBufferBuilder.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 535e0a1b07b9d5a5486f2a31b5104a77 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/FlatBufferConstants.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/FlatBufferConstants.cs new file mode 100644 index 0000000..1d4c5dc --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/FlatBufferConstants.cs @@ -0,0 +1,37 @@ +/* + * Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace FlatBuffers +{ + public static class FlatBufferConstants + { + public const int FileIdentifierLength = 4; + public const int SizePrefixLength = 4; + /** A version identifier to force a compile error if someone + accidentally tries to build generated code with a runtime of + two mismatched version. Versions need to always match, as + the runtime and generated code are modified in sync. + Changes to the C# implementation need to be sure to change + the version here and in the code generator on every possible + incompatible change */ + public static void FLATBUFFERS_1_12_0() {} + } +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/FlatBufferConstants.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/FlatBufferConstants.cs.meta new file mode 100644 index 0000000..6ec6661 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/FlatBufferConstants.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: d1353ef2376e059b6230902e5c1ca38b diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/IFlatbufferObject.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/IFlatbufferObject.cs new file mode 100644 index 0000000..6a15aba --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/IFlatbufferObject.cs @@ -0,0 +1,28 @@ +/* + * Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace FlatBuffers +{ + /// + /// This is the base for both structs and tables. + /// + public interface IFlatbufferObject + { + void __init(int _i, ByteBuffer _bb); + + ByteBuffer ByteBuffer { get; } + } +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/IFlatbufferObject.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/IFlatbufferObject.cs.meta new file mode 100644 index 0000000..5c1cf52 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/IFlatbufferObject.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: b49ac3aef9f3fd3c4498c11cb4c023ac diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/Offset.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/Offset.cs new file mode 100644 index 0000000..2b17cec --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/Offset.cs @@ -0,0 +1,48 @@ +/* + * Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace FlatBuffers +{ + /// + /// Offset class for typesafe assignments. + /// + public struct Offset where T : struct + { + public int Value; + public Offset(int value) + { + Value = value; + } + } + + public struct StringOffset + { + public int Value; + public StringOffset(int value) + { + Value = value; + } + } + + public struct VectorOffset + { + public int Value; + public VectorOffset(int value) + { + Value = value; + } + } +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/Offset.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/Offset.cs.meta new file mode 100644 index 0000000..6fab390 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/Offset.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: bd386a52f50c8064d7593b3c4080ad9a diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/Properties.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/Properties.meta new file mode 100644 index 0000000..bd85426 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/Properties.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3641530f4ab184c7788119d50e5a743c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/Properties/AssemblyInfo.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..1edfac4 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/Properties/AssemblyInfo.cs @@ -0,0 +1,52 @@ +/* + * Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("FlatBuffers")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("FlatBuffers")] +[assembly: AssemblyCopyright("Copyright (c) 2015 Google Inc")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("91c32e64-ef20-47df-9c9f-cec9207bc6df")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/Properties/AssemblyInfo.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/Properties/AssemblyInfo.cs.meta new file mode 100644 index 0000000..eab3201 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/Properties/AssemblyInfo.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: d83b8e69f2fef0cec77c185f28b99935 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/Struct.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/Struct.cs new file mode 100644 index 0000000..4832cda --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/Struct.cs @@ -0,0 +1,34 @@ +/* + * Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace FlatBuffers +{ + /// + /// All structs in the generated code derive from this class, and add their own accessors. + /// + public struct Struct + { + public int bb_pos { get; private set; } + public ByteBuffer bb { get; private set; } + + // Re-init the internal state with an external buffer {@code ByteBuffer} and an offset within. + public Struct(int _i, ByteBuffer _bb) : this() + { + bb = _bb; + bb_pos = _i; + } + } +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/Struct.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/Struct.cs.meta new file mode 100644 index 0000000..c9b9078 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/Struct.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 06039704da9107e6984ddbcd40a889a2 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/Table.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/Table.cs new file mode 100644 index 0000000..2ed0788 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/Table.cs @@ -0,0 +1,208 @@ +/* + * Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.Text; +using System.Runtime.InteropServices; + +namespace FlatBuffers +{ + /// + /// All tables in the generated code derive from this struct, and add their own accessors. + /// + public struct Table + { + public int bb_pos { get; private set; } + public ByteBuffer bb { get; private set; } + + public ByteBuffer ByteBuffer { get { return bb; } } + + // Re-init the internal state with an external buffer {@code ByteBuffer} and an offset within. + public Table(int _i, ByteBuffer _bb) : this() + { + bb = _bb; + bb_pos = _i; + } + + // Look up a field in the vtable, return an offset into the object, or 0 if the field is not + // present. + public int __offset(int vtableOffset) + { + int vtable = bb_pos - bb.GetInt(bb_pos); + return vtableOffset < bb.GetShort(vtable) ? (int)bb.GetShort(vtable + vtableOffset) : 0; + } + + public static int __offset(int vtableOffset, int offset, ByteBuffer bb) + { + int vtable = bb.Length - offset; + return (int)bb.GetShort(vtable + vtableOffset - bb.GetInt(vtable)) + vtable; + } + + // Retrieve the relative offset stored at "offset" + public int __indirect(int offset) + { + return offset + bb.GetInt(offset); + } + + public static int __indirect(int offset, ByteBuffer bb) + { + return offset + bb.GetInt(offset); + } + + // Create a .NET String from UTF-8 data stored inside the flatbuffer. + public string __string(int offset) + { + offset += bb.GetInt(offset); + var len = bb.GetInt(offset); + var startPos = offset + sizeof(int); + return bb.GetStringUTF8(startPos, len); + } + + // Get the length of a vector whose offset is stored at "offset" in this object. + public int __vector_len(int offset) + { + offset += bb_pos; + offset += bb.GetInt(offset); + return bb.GetInt(offset); + } + + // Get the start of data of a vector whose offset is stored at "offset" in this object. + public int __vector(int offset) + { + offset += bb_pos; + return offset + bb.GetInt(offset) + sizeof(int); // data starts after the length + } + +#if ENABLE_SPAN_T + // Get the data of a vector whoses offset is stored at "offset" in this object as an + // Spant<byte>. If the vector is not present in the ByteBuffer, + // then an empty span will be returned. + public Span __vector_as_span(int offset, int elementSize) where T : struct + { + if (!BitConverter.IsLittleEndian) + { + throw new NotSupportedException("Getting typed span on a Big Endian " + + "system is not support"); + } + + var o = this.__offset(offset); + if (0 == o) + { + return new Span(); + } + + var pos = this.__vector(o); + var len = this.__vector_len(o); + return MemoryMarshal.Cast(bb.ToSpan(pos, len * elementSize)); + } +#else + // Get the data of a vector whoses offset is stored at "offset" in this object as an + // ArraySegment<byte>. If the vector is not present in the ByteBuffer, + // then a null value will be returned. + public ArraySegment? __vector_as_arraysegment(int offset) + { + var o = this.__offset(offset); + if (0 == o) + { + return null; + } + + var pos = this.__vector(o); + var len = this.__vector_len(o); + return bb.ToArraySegment(pos, len); + } +#endif + + // Get the data of a vector whoses offset is stored at "offset" in this object as an + // T[]. If the vector is not present in the ByteBuffer, then a null value will be + // returned. + public T[] __vector_as_array(int offset) + where T : struct + { + if(!BitConverter.IsLittleEndian) + { + throw new NotSupportedException("Getting typed arrays on a Big Endian " + + "system is not support"); + } + + var o = this.__offset(offset); + if (0 == o) + { + return null; + } + + var pos = this.__vector(o); + var len = this.__vector_len(o); + return bb.ToArray(pos, len); + } + + // Initialize any Table-derived type to point to the union at the given offset. + public T __union(int offset) where T : struct, IFlatbufferObject + { + T t = new T(); + t.__init(__indirect(offset), bb); + return t; + } + + public static bool __has_identifier(ByteBuffer bb, string ident) + { + if (ident.Length != FlatBufferConstants.FileIdentifierLength) + throw new ArgumentException("FlatBuffers: file identifier must be length " + FlatBufferConstants.FileIdentifierLength, "ident"); + + for (var i = 0; i < FlatBufferConstants.FileIdentifierLength; i++) + { + if (ident[i] != (char)bb.Get(bb.Position + sizeof(int) + i)) return false; + } + + return true; + } + + // Compare strings in the ByteBuffer. + public static int CompareStrings(int offset_1, int offset_2, ByteBuffer bb) + { + offset_1 += bb.GetInt(offset_1); + offset_2 += bb.GetInt(offset_2); + var len_1 = bb.GetInt(offset_1); + var len_2 = bb.GetInt(offset_2); + var startPos_1 = offset_1 + sizeof(int); + var startPos_2 = offset_2 + sizeof(int); + var len = Math.Min(len_1, len_2); + for(int i = 0; i < len; i++) { + byte b1 = bb.Get(i + startPos_1); + byte b2 = bb.Get(i + startPos_2); + if (b1 != b2) + return b1 - b2; + } + return len_1 - len_2; + } + + // Compare string from the ByteBuffer with the string object + public static int CompareStrings(int offset_1, byte[] key, ByteBuffer bb) + { + offset_1 += bb.GetInt(offset_1); + var len_1 = bb.GetInt(offset_1); + var len_2 = key.Length; + var startPos_1 = offset_1 + sizeof(int); + var len = Math.Min(len_1, len_2); + for (int i = 0; i < len; i++) { + byte b = bb.Get(i + startPos_1); + if (b != key[i]) + return b - key[i]; + } + return len_1 - len_2; + } + } +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/Table.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/Table.cs.meta new file mode 100644 index 0000000..d083688 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/FlatBuffers/Table.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: db74681fef2db2271dad5137f820b271 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/LibraryHelper.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/LibraryHelper.cs new file mode 100644 index 0000000..cff8d51 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/LibraryHelper.cs @@ -0,0 +1,26 @@ + +// Copyright 2019 Niantic, Inc. All Rights Reserved. + +namespace Grapeshot { + + public static class LibraryHelper { + #if UNITY_EDITOR + internal const string libraryName = "ardk_client_platform"; + + #elif UNITY_STANDALONE_OSX + internal const string libraryName = "ardk_client_platform"; + + #elif UNITY_IOS + internal const string libraryName = "__Internal"; + + #elif UNITY_ANDROID + internal const string libraryName = "ardk_client_platform"; + + #else + // TODO: Windows and Linux library name + support + internal const string libraryName = "TODO_DOES_NOT_EXIST"; + + #endif + } + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/LibraryHelper.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/LibraryHelper.cs.meta new file mode 100644 index 0000000..8b61230 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/LibraryHelper.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 4ef41e531682cb927ee00b5ad8f01e4f diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/cs_helpers.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/cs_helpers.meta new file mode 100644 index 0000000..3128a77 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/cs_helpers.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4c6f4eec379614388ba027f813687495 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/cs_helpers/TableUtils.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/cs_helpers/TableUtils.cs new file mode 100644 index 0000000..3bc414c --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/cs_helpers/TableUtils.cs @@ -0,0 +1,27 @@ +using System; +using System.Reflection; + +namespace FlatBuffers { + + internal static class TableFieldLookup { + public static FieldInfo fieldInfo; + public static object lockable = new object(); + } + + public static class TableUtils { + public static Table GetTable(this T table) where T : IFlatbufferObject{ + var fieldInfo = TableFieldLookup.fieldInfo; + if (fieldInfo == null) { + lock (TableFieldLookup.lockable) { + if (fieldInfo == null) { + fieldInfo = typeof(T).GetField("__p", BindingFlags.NonPublic | BindingFlags.Instance); + TableFieldLookup.fieldInfo = fieldInfo; + } + } + } + + return (Table) fieldInfo.GetValue(table); + } + } + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/cs_helpers/TableUtils.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/cs_helpers/TableUtils.cs.meta new file mode 100644 index 0000000..579769a --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/cs_helpers/TableUtils.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 23c32001bd5ef1c3e6ba40509c07b62a diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application.meta new file mode 100644 index 0000000..3798d7a --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 27b484401be3b44448df8340f4a9a9e6 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/ApplicationChunkFetcher_FunctionApplicationBridge.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/ApplicationChunkFetcher_FunctionApplicationBridge.cs new file mode 100644 index 0000000..adeeefb --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/ApplicationChunkFetcher_FunctionApplicationBridge.cs @@ -0,0 +1,36 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public sealed class ApplicationChunkFetcher_FunctionApplicationBridge : ApplicationChunkFetcher_FunctionApplicationBridgeBase { + public delegate void Delegate(ChunkFetcherParams arg); + + private Delegate _delegate; + + public ApplicationChunkFetcher_FunctionApplicationBridge(Delegate d) : base() { + _delegate = d; + } + + public override void releaseApplicationCallback() { + // This doesn't do anything except update reflection info so that the director thinks it needs + // to call this. + base.releaseApplicationCallback(); + } + + public override void invokeApplicationLogic(ChunkFetcherParams arg) { + try { + _delegate(arg); + } catch {} + } + +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/ApplicationChunkFetcher_FunctionApplicationBridge.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/ApplicationChunkFetcher_FunctionApplicationBridge.cs.meta new file mode 100644 index 0000000..14e5e50 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/ApplicationChunkFetcher_FunctionApplicationBridge.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 2da7900b726b399d695e875f4ec0ae45 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/ApplicationChunkFetcher_FunctionApplicationBridgeBase.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/ApplicationChunkFetcher_FunctionApplicationBridgeBase.cs new file mode 100644 index 0000000..fd5646e --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/ApplicationChunkFetcher_FunctionApplicationBridgeBase.cs @@ -0,0 +1,155 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public abstract class ApplicationChunkFetcher_FunctionApplicationBridgeBase : global::System.IDisposable { + /** DO NOT REMOVE THE FOLLOWING COMMENT **/ + /** THIS HAS BEEN SWIG CORRECTED: JJDKFJSIIIIDKJ **/ + private global::System.Runtime.InteropServices.GCHandle _swigDelegateHandle1; + private global::System.Runtime.InteropServices.GCHandle _swigDelegateHandle0; + private global::System.Runtime.InteropServices.HandleRef swigCPtr; + protected bool swigCMemOwn; + + internal ApplicationChunkFetcher_FunctionApplicationBridgeBase(global::System.IntPtr cPtr, bool cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr); + } + + internal static global::System.Runtime.InteropServices.HandleRef getCPtr(ApplicationChunkFetcher_FunctionApplicationBridgeBase obj) { + return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; + } + + ~ApplicationChunkFetcher_FunctionApplicationBridgeBase() { + Dispose(); + } + + public virtual void Dispose() { + lock(this) { + if (swigCPtr.Handle != global::System.IntPtr.Zero) { + if (swigCMemOwn) { + swigCMemOwn = false; + GrapeshotSessionPINVOKE.delete_ApplicationChunkFetcher_FunctionApplicationBridgeBase(swigCPtr); + } + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); + } + global::System.GC.SuppressFinalize(this); + _swigDelegateHandle0.Free(); + _swigDelegateHandle1.Free(); + } + } + + // Information used to prevent pre-mature GC of callbacks still being used from C++. + private ulong _refCount; + private System.Runtime.InteropServices.GCHandle _handle; + + /// Allocates a reference to this application callback so that it can't be released from memory + /// until all allocs have been meet with an equal number of releaseApplicationCallback. + public void allocApplicationCallback() { + lock(this) { + if (_refCount == 0) { + _handle = System.Runtime.InteropServices.GCHandle.Alloc(this); + } + + _refCount++; + } + } + + public virtual void invokeApplicationLogic(ChunkFetcherParams ApplicationChunkFetcher_arg) { throw new System.NotImplementedException(); } + + public virtual void releaseApplicationCallback() { + // When releasing the application side callback, this means that one of the native side holds + // was terminated, thus cs should remove a reference count, once that count is zero free the + // handle. + lock(this) { + if (_refCount <= 0) { + return; + } + + _refCount -= 1; + + if (_refCount <= 0) { + _handle.Free(); + } + } + } + + + public ApplicationChunkFetcher_FunctionApplicationBridgeBase() : this(GrapeshotSessionPINVOKE.new_ApplicationChunkFetcher_FunctionApplicationBridgeBase(), true) { + SwigDirectorConnect(); + } + + private void SwigDirectorConnect() { + global::System.IntPtr swigDelegate0gcHandlePtr = global::System.IntPtr.Zero; + if (SwigDerivedClassHasMethod("invokeApplicationLogic", swigMethodTypes0)) { + swigDelegate0 = new SwigDelegateApplicationChunkFetcher_FunctionApplicationBridgeBase_0(SwigDirectorinvokeApplicationLogic); + swigDelegate0dispatcher = new SwigDelegateApplicationChunkFetcher_FunctionApplicationBridgeBase_0_Dispatcher(SwigDirectorinvokeApplicationLogic_Dispatcher); + + global::System.Runtime.InteropServices.GCHandle swigDelegate0gcHandle = global::System.Runtime.InteropServices.GCHandle.Alloc(swigDelegate0, global::System.Runtime.InteropServices.GCHandleType.Normal); + _swigDelegateHandle0 = swigDelegate0gcHandle; + swigDelegate0gcHandlePtr = global::System.Runtime.InteropServices.GCHandle.ToIntPtr(swigDelegate0gcHandle); + } + global::System.IntPtr swigDelegate1gcHandlePtr = global::System.IntPtr.Zero; + if (SwigDerivedClassHasMethod("releaseApplicationCallback", swigMethodTypes1)) { + swigDelegate1 = new SwigDelegateApplicationChunkFetcher_FunctionApplicationBridgeBase_1(SwigDirectorreleaseApplicationCallback); + swigDelegate1dispatcher = new SwigDelegateApplicationChunkFetcher_FunctionApplicationBridgeBase_1_Dispatcher(SwigDirectorreleaseApplicationCallback_Dispatcher); + + global::System.Runtime.InteropServices.GCHandle swigDelegate1gcHandle = global::System.Runtime.InteropServices.GCHandle.Alloc(swigDelegate1, global::System.Runtime.InteropServices.GCHandleType.Normal); + _swigDelegateHandle1 = swigDelegate1gcHandle; + swigDelegate1gcHandlePtr = global::System.Runtime.InteropServices.GCHandle.ToIntPtr(swigDelegate1gcHandle); + } + GrapeshotSessionPINVOKE.ApplicationChunkFetcher_FunctionApplicationBridgeBase_director_connect(swigCPtr, swigDelegate0dispatcher, swigDelegate0gcHandlePtr, swigDelegate1dispatcher, swigDelegate1gcHandlePtr); + } + + private bool SwigDerivedClassHasMethod(string methodName, global::System.Type[] methodTypes) { + global::System.Reflection.MethodInfo methodInfo = this.GetType().GetMethod(methodName, global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance, null, methodTypes, null); + bool hasDerivedMethod = methodInfo.DeclaringType.IsSubclassOf(typeof(ApplicationChunkFetcher_FunctionApplicationBridgeBase)); + return hasDerivedMethod; + } + + private void SwigDirectorinvokeApplicationLogic(global::System.IntPtr ApplicationChunkFetcher_arg) { + invokeApplicationLogic(new ChunkFetcherParams(ApplicationChunkFetcher_arg, false)); + } + + [GrapeshotSessionPINVOKE.MonoPInvokeCallback(typeof(SwigDelegateApplicationChunkFetcher_FunctionApplicationBridgeBase_0_Dispatcher))] + private static void SwigDirectorinvokeApplicationLogic_Dispatcher(global::System.IntPtr swigDelegateApplicationChunkFetcher_FunctionApplicationBridgeBase_0_Handle, global::System.IntPtr ApplicationChunkFetcher_arg) { + global::System.Runtime.InteropServices.GCHandle gcHandle = global::System.Runtime.InteropServices.GCHandle.FromIntPtr(swigDelegateApplicationChunkFetcher_FunctionApplicationBridgeBase_0_Handle); + SwigDelegateApplicationChunkFetcher_FunctionApplicationBridgeBase_0 delegateSwigDelegateApplicationChunkFetcher_FunctionApplicationBridgeBase_0 = (SwigDelegateApplicationChunkFetcher_FunctionApplicationBridgeBase_0) gcHandle.Target; +delegateSwigDelegateApplicationChunkFetcher_FunctionApplicationBridgeBase_0(ApplicationChunkFetcher_arg); + } + + private void SwigDirectorreleaseApplicationCallback() { + releaseApplicationCallback(); + } + + [GrapeshotSessionPINVOKE.MonoPInvokeCallback(typeof(SwigDelegateApplicationChunkFetcher_FunctionApplicationBridgeBase_1_Dispatcher))] + private static void SwigDirectorreleaseApplicationCallback_Dispatcher(global::System.IntPtr swigDelegateApplicationChunkFetcher_FunctionApplicationBridgeBase_1_Handle) { + global::System.Runtime.InteropServices.GCHandle gcHandle = global::System.Runtime.InteropServices.GCHandle.FromIntPtr(swigDelegateApplicationChunkFetcher_FunctionApplicationBridgeBase_1_Handle); + SwigDelegateApplicationChunkFetcher_FunctionApplicationBridgeBase_1 delegateSwigDelegateApplicationChunkFetcher_FunctionApplicationBridgeBase_1 = (SwigDelegateApplicationChunkFetcher_FunctionApplicationBridgeBase_1) gcHandle.Target; +delegateSwigDelegateApplicationChunkFetcher_FunctionApplicationBridgeBase_1(); + } + + public delegate void SwigDelegateApplicationChunkFetcher_FunctionApplicationBridgeBase_0(global::System.IntPtr ApplicationChunkFetcher_arg); + public delegate void SwigDelegateApplicationChunkFetcher_FunctionApplicationBridgeBase_1(); + + private SwigDelegateApplicationChunkFetcher_FunctionApplicationBridgeBase_0 swigDelegate0; + private SwigDelegateApplicationChunkFetcher_FunctionApplicationBridgeBase_1 swigDelegate1; + + public delegate void SwigDelegateApplicationChunkFetcher_FunctionApplicationBridgeBase_0_Dispatcher(global::System.IntPtr swigDelegateApplicationChunkFetcher_FunctionApplicationBridgeBase_0_Handle, global::System.IntPtr ApplicationChunkFetcher_arg); + public delegate void SwigDelegateApplicationChunkFetcher_FunctionApplicationBridgeBase_1_Dispatcher(global::System.IntPtr swigDelegateApplicationChunkFetcher_FunctionApplicationBridgeBase_1_Handle); + + private SwigDelegateApplicationChunkFetcher_FunctionApplicationBridgeBase_0_Dispatcher swigDelegate0dispatcher; + private SwigDelegateApplicationChunkFetcher_FunctionApplicationBridgeBase_1_Dispatcher swigDelegate1dispatcher; + + private static global::System.Type[] swigMethodTypes0 = new global::System.Type[] { typeof(ChunkFetcherParams) }; + private static global::System.Type[] swigMethodTypes1 = new global::System.Type[] { }; +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/ApplicationChunkFetcher_FunctionApplicationBridgeBase.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/ApplicationChunkFetcher_FunctionApplicationBridgeBase.cs.meta new file mode 100644 index 0000000..e7f33d2 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/ApplicationChunkFetcher_FunctionApplicationBridgeBase.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: ad7dc4b1270874e36929c35345d75ea3 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/ApplicationRate.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/ApplicationRate.cs new file mode 100644 index 0000000..a0f8799 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/ApplicationRate.cs @@ -0,0 +1,233 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public abstract class ApplicationRate : Rate { + /** DO NOT REMOVE THE FOLLOWING COMMENT **/ + /** THIS HAS BEEN SWIG CORRECTED: JJDKFJSIIIIDKJ **/ + private global::System.Runtime.InteropServices.GCHandle _swigDelegateHandle3; + private global::System.Runtime.InteropServices.GCHandle _swigDelegateHandle2; + private global::System.Runtime.InteropServices.GCHandle _swigDelegateHandle1; + private global::System.Runtime.InteropServices.GCHandle _swigDelegateHandle0; + private global::System.Runtime.InteropServices.HandleRef swigCPtr; + private bool swigCMemOwnDerived; + + internal ApplicationRate(global::System.IntPtr cPtr, bool cMemoryOwn) : base(GrapeshotApplicationRatePINVOKE.ApplicationRate_SWIGSmartPtrUpcast(cPtr), true) { + swigCMemOwnDerived = cMemoryOwn; + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr); + } + + internal static global::System.Runtime.InteropServices.HandleRef getCPtr(ApplicationRate obj) { + return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; + } + + ~ApplicationRate() { + Dispose(); + } + + public override void Dispose() { + lock(this) { + if (swigCPtr.Handle != global::System.IntPtr.Zero) { + if (swigCMemOwnDerived) { + swigCMemOwnDerived = false; + GrapeshotApplicationRatePINVOKE.delete_ApplicationRate(swigCPtr); + } + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); + } + global::System.GC.SuppressFinalize(this); + base.Dispose(); + _swigDelegateHandle0.Free(); + _swigDelegateHandle1.Free(); + _swigDelegateHandle2.Free(); + _swigDelegateHandle3.Free(); + } + } + + public override RateTicket claimTicket(ror.schema.upload.UploadChunkRequest chunkRequest) { +var chunkRequest_table = FlatBuffers.TableUtils.GetTable(chunkRequest);var chunkRequest_length = chunkRequest_table.bb.Length;var chunkRequest_pos = chunkRequest_table.bb_pos;var chunkRequest_seg = chunkRequest_table.bb.ToArraySegment(chunkRequest_pos, chunkRequest_length - chunkRequest_pos);var chunkRequest_managed_array = chunkRequest_seg.Array;var chunkRequest_managed_handle = System.Runtime.InteropServices.GCHandle.Alloc(chunkRequest_managed_array, System.Runtime.InteropServices.GCHandleType.Pinned);var chunkRequest_buffer_ptr = chunkRequest_managed_handle.AddrOfPinnedObject();System.IntPtr chunkRequest_fb_ptr;unsafe { var chunkRequest_buffer_unsafe_ptr = (byte*) chunkRequest_buffer_ptr.ToPointer(); chunkRequest_fb_ptr = (System.IntPtr) (chunkRequest_buffer_unsafe_ptr + chunkRequest_pos);}var chunkRequest_intermediate = new FBIntermediateBuffer();chunkRequest_intermediate.ptr = chunkRequest_fb_ptr; + try { + global::System.IntPtr cPtr = GrapeshotApplicationRatePINVOKE.ApplicationRate_claimTicket(swigCPtr, chunkRequest_intermediate); + RateTicket ret = (cPtr == global::System.IntPtr.Zero) ? null : new RateTicket(cPtr, true); + if (GrapeshotApplicationRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotApplicationRatePINVOKE.SWIGPendingException.Retrieve(); + return ret; + } finally { +chunkRequest_managed_handle.Free(); + } + } + + public virtual void applicationClaimTicket(ror.schema.upload.UploadChunkRequest chunkRequest, RateTicketReturn rateTicketReturn) { +var chunkRequest_table = FlatBuffers.TableUtils.GetTable(chunkRequest);var chunkRequest_length = chunkRequest_table.bb.Length;var chunkRequest_pos = chunkRequest_table.bb_pos;var chunkRequest_seg = chunkRequest_table.bb.ToArraySegment(chunkRequest_pos, chunkRequest_length - chunkRequest_pos);var chunkRequest_managed_array = chunkRequest_seg.Array;var chunkRequest_managed_handle = System.Runtime.InteropServices.GCHandle.Alloc(chunkRequest_managed_array, System.Runtime.InteropServices.GCHandleType.Pinned);var chunkRequest_buffer_ptr = chunkRequest_managed_handle.AddrOfPinnedObject();System.IntPtr chunkRequest_fb_ptr;unsafe { var chunkRequest_buffer_unsafe_ptr = (byte*) chunkRequest_buffer_ptr.ToPointer(); chunkRequest_fb_ptr = (System.IntPtr) (chunkRequest_buffer_unsafe_ptr + chunkRequest_pos);}var chunkRequest_intermediate = new FBIntermediateBuffer();chunkRequest_intermediate.ptr = chunkRequest_fb_ptr; + try { + if (SwigDerivedClassHasMethod("applicationClaimTicket", swigMethodTypes2)) GrapeshotApplicationRatePINVOKE.ApplicationRate_applicationClaimTicketSwigExplicitApplicationRate(swigCPtr, chunkRequest_intermediate, RateTicketReturn.getCPtr(rateTicketReturn)); else GrapeshotApplicationRatePINVOKE.ApplicationRate_applicationClaimTicket(swigCPtr, chunkRequest_intermediate, RateTicketReturn.getCPtr(rateTicketReturn)); + if (GrapeshotApplicationRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotApplicationRatePINVOKE.SWIGPendingException.Retrieve(); + } finally { +chunkRequest_managed_handle.Free(); + } + } + + public override RateTicket tryClaimTicket(ror.schema.upload.UploadChunkRequest chunkRequest) { +var chunkRequest_table = FlatBuffers.TableUtils.GetTable(chunkRequest);var chunkRequest_length = chunkRequest_table.bb.Length;var chunkRequest_pos = chunkRequest_table.bb_pos;var chunkRequest_seg = chunkRequest_table.bb.ToArraySegment(chunkRequest_pos, chunkRequest_length - chunkRequest_pos);var chunkRequest_managed_array = chunkRequest_seg.Array;var chunkRequest_managed_handle = System.Runtime.InteropServices.GCHandle.Alloc(chunkRequest_managed_array, System.Runtime.InteropServices.GCHandleType.Pinned);var chunkRequest_buffer_ptr = chunkRequest_managed_handle.AddrOfPinnedObject();System.IntPtr chunkRequest_fb_ptr;unsafe { var chunkRequest_buffer_unsafe_ptr = (byte*) chunkRequest_buffer_ptr.ToPointer(); chunkRequest_fb_ptr = (System.IntPtr) (chunkRequest_buffer_unsafe_ptr + chunkRequest_pos);}var chunkRequest_intermediate = new FBIntermediateBuffer();chunkRequest_intermediate.ptr = chunkRequest_fb_ptr; + try { + global::System.IntPtr cPtr = GrapeshotApplicationRatePINVOKE.ApplicationRate_tryClaimTicket(swigCPtr, chunkRequest_intermediate); + RateTicket ret = (cPtr == global::System.IntPtr.Zero) ? null : new RateTicket(cPtr, true); + if (GrapeshotApplicationRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotApplicationRatePINVOKE.SWIGPendingException.Retrieve(); + return ret; + } finally { +chunkRequest_managed_handle.Free(); + } + } + + public virtual void applicationTryClaimTicket(ror.schema.upload.UploadChunkRequest chunkRequest, RateTicketReturn rateTicketReturn) { +var chunkRequest_table = FlatBuffers.TableUtils.GetTable(chunkRequest);var chunkRequest_length = chunkRequest_table.bb.Length;var chunkRequest_pos = chunkRequest_table.bb_pos;var chunkRequest_seg = chunkRequest_table.bb.ToArraySegment(chunkRequest_pos, chunkRequest_length - chunkRequest_pos);var chunkRequest_managed_array = chunkRequest_seg.Array;var chunkRequest_managed_handle = System.Runtime.InteropServices.GCHandle.Alloc(chunkRequest_managed_array, System.Runtime.InteropServices.GCHandleType.Pinned);var chunkRequest_buffer_ptr = chunkRequest_managed_handle.AddrOfPinnedObject();System.IntPtr chunkRequest_fb_ptr;unsafe { var chunkRequest_buffer_unsafe_ptr = (byte*) chunkRequest_buffer_ptr.ToPointer(); chunkRequest_fb_ptr = (System.IntPtr) (chunkRequest_buffer_unsafe_ptr + chunkRequest_pos);}var chunkRequest_intermediate = new FBIntermediateBuffer();chunkRequest_intermediate.ptr = chunkRequest_fb_ptr; + try { + if (SwigDerivedClassHasMethod("applicationTryClaimTicket", swigMethodTypes3)) GrapeshotApplicationRatePINVOKE.ApplicationRate_applicationTryClaimTicketSwigExplicitApplicationRate(swigCPtr, chunkRequest_intermediate, RateTicketReturn.getCPtr(rateTicketReturn)); else GrapeshotApplicationRatePINVOKE.ApplicationRate_applicationTryClaimTicket(swigCPtr, chunkRequest_intermediate, RateTicketReturn.getCPtr(rateTicketReturn)); + if (GrapeshotApplicationRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotApplicationRatePINVOKE.SWIGPendingException.Retrieve(); + } finally { +chunkRequest_managed_handle.Free(); + } + } + + public override bool areFreeTickets() { + bool ret = (SwigDerivedClassHasMethod("areFreeTickets", swigMethodTypes1) ? GrapeshotApplicationRatePINVOKE.ApplicationRate_areFreeTicketsSwigExplicitApplicationRate(swigCPtr) : GrapeshotApplicationRatePINVOKE.ApplicationRate_areFreeTickets(swigCPtr)); + if (GrapeshotApplicationRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotApplicationRatePINVOKE.SWIGPendingException.Retrieve(); + return ret; + } + + public override void process() { + if (SwigDerivedClassHasMethod("process", swigMethodTypes0)) GrapeshotApplicationRatePINVOKE.ApplicationRate_processSwigExplicitApplicationRate(swigCPtr); else GrapeshotApplicationRatePINVOKE.ApplicationRate_process(swigCPtr); + if (GrapeshotApplicationRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotApplicationRatePINVOKE.SWIGPendingException.Retrieve(); + } + + public ApplicationRate() : this(GrapeshotApplicationRatePINVOKE.new_ApplicationRate(), true) { + SwigDirectorConnect(); + } + + private void SwigDirectorConnect() { + global::System.IntPtr swigDelegate0gcHandlePtr = global::System.IntPtr.Zero; + if (SwigDerivedClassHasMethod("process", swigMethodTypes0)) { + swigDelegate0 = new SwigDelegateApplicationRate_0(SwigDirectorprocess); + swigDelegate0dispatcher = new SwigDelegateApplicationRate_0_Dispatcher(SwigDirectorprocess_Dispatcher); + + global::System.Runtime.InteropServices.GCHandle swigDelegate0gcHandle = global::System.Runtime.InteropServices.GCHandle.Alloc(swigDelegate0, global::System.Runtime.InteropServices.GCHandleType.Normal); + _swigDelegateHandle0 = swigDelegate0gcHandle; + swigDelegate0gcHandlePtr = global::System.Runtime.InteropServices.GCHandle.ToIntPtr(swigDelegate0gcHandle); + } + global::System.IntPtr swigDelegate1gcHandlePtr = global::System.IntPtr.Zero; + if (SwigDerivedClassHasMethod("areFreeTickets", swigMethodTypes1)) { + swigDelegate1 = new SwigDelegateApplicationRate_1(SwigDirectorareFreeTickets); + swigDelegate1dispatcher = new SwigDelegateApplicationRate_1_Dispatcher(SwigDirectorareFreeTickets_Dispatcher); + + global::System.Runtime.InteropServices.GCHandle swigDelegate1gcHandle = global::System.Runtime.InteropServices.GCHandle.Alloc(swigDelegate1, global::System.Runtime.InteropServices.GCHandleType.Normal); + _swigDelegateHandle1 = swigDelegate1gcHandle; + swigDelegate1gcHandlePtr = global::System.Runtime.InteropServices.GCHandle.ToIntPtr(swigDelegate1gcHandle); + } + global::System.IntPtr swigDelegate2gcHandlePtr = global::System.IntPtr.Zero; + if (SwigDerivedClassHasMethod("applicationClaimTicket", swigMethodTypes2)) { + swigDelegate2 = new SwigDelegateApplicationRate_2(SwigDirectorapplicationClaimTicket); + swigDelegate2dispatcher = new SwigDelegateApplicationRate_2_Dispatcher(SwigDirectorapplicationClaimTicket_Dispatcher); + + global::System.Runtime.InteropServices.GCHandle swigDelegate2gcHandle = global::System.Runtime.InteropServices.GCHandle.Alloc(swigDelegate2, global::System.Runtime.InteropServices.GCHandleType.Normal); + _swigDelegateHandle2 = swigDelegate2gcHandle; + swigDelegate2gcHandlePtr = global::System.Runtime.InteropServices.GCHandle.ToIntPtr(swigDelegate2gcHandle); + } + global::System.IntPtr swigDelegate3gcHandlePtr = global::System.IntPtr.Zero; + if (SwigDerivedClassHasMethod("applicationTryClaimTicket", swigMethodTypes3)) { + swigDelegate3 = new SwigDelegateApplicationRate_3(SwigDirectorapplicationTryClaimTicket); + swigDelegate3dispatcher = new SwigDelegateApplicationRate_3_Dispatcher(SwigDirectorapplicationTryClaimTicket_Dispatcher); + + global::System.Runtime.InteropServices.GCHandle swigDelegate3gcHandle = global::System.Runtime.InteropServices.GCHandle.Alloc(swigDelegate3, global::System.Runtime.InteropServices.GCHandleType.Normal); + _swigDelegateHandle3 = swigDelegate3gcHandle; + swigDelegate3gcHandlePtr = global::System.Runtime.InteropServices.GCHandle.ToIntPtr(swigDelegate3gcHandle); + } + GrapeshotApplicationRatePINVOKE.ApplicationRate_director_connect(swigCPtr, swigDelegate0dispatcher, swigDelegate0gcHandlePtr, swigDelegate1dispatcher, swigDelegate1gcHandlePtr, swigDelegate2dispatcher, swigDelegate2gcHandlePtr, swigDelegate3dispatcher, swigDelegate3gcHandlePtr); + } + + private bool SwigDerivedClassHasMethod(string methodName, global::System.Type[] methodTypes) { + global::System.Reflection.MethodInfo methodInfo = this.GetType().GetMethod(methodName, global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance, null, methodTypes, null); + bool hasDerivedMethod = methodInfo.DeclaringType.IsSubclassOf(typeof(ApplicationRate)); + return hasDerivedMethod; + } + + private void SwigDirectorprocess() { + process(); + } + + [GrapeshotApplicationRatePINVOKE.MonoPInvokeCallback(typeof(SwigDelegateApplicationRate_0_Dispatcher))] + private static void SwigDirectorprocess_Dispatcher(global::System.IntPtr swigDelegateApplicationRate_0_Handle) { + global::System.Runtime.InteropServices.GCHandle gcHandle = global::System.Runtime.InteropServices.GCHandle.FromIntPtr(swigDelegateApplicationRate_0_Handle); + SwigDelegateApplicationRate_0 delegateSwigDelegateApplicationRate_0 = (SwigDelegateApplicationRate_0) gcHandle.Target; +delegateSwigDelegateApplicationRate_0(); + } + + private bool SwigDirectorareFreeTickets() { + return areFreeTickets(); + } + + [GrapeshotApplicationRatePINVOKE.MonoPInvokeCallback(typeof(SwigDelegateApplicationRate_1_Dispatcher))] + private static bool SwigDirectorareFreeTickets_Dispatcher(global::System.IntPtr swigDelegateApplicationRate_1_Handle) { + global::System.Runtime.InteropServices.GCHandle gcHandle = global::System.Runtime.InteropServices.GCHandle.FromIntPtr(swigDelegateApplicationRate_1_Handle); + SwigDelegateApplicationRate_1 delegateSwigDelegateApplicationRate_1 = (SwigDelegateApplicationRate_1) gcHandle.Target; + return delegateSwigDelegateApplicationRate_1(); + } + + private void SwigDirectorapplicationClaimTicket(FBIntermediateBuffer chunkRequest, global::System.IntPtr rateTicketReturn) { +var chunkRequest_buffer = new byte[chunkRequest.size];UnityEngine.Assertions.Assert.AreNotEqual(chunkRequest.size, (ulong) 0);System.Runtime.InteropServices.Marshal.Copy(chunkRequest.ptr, chunkRequest_buffer, 0, (int) chunkRequest.size);var chunkRequest_bb = new FlatBuffers.ByteBuffer(chunkRequest_buffer);var chunkRequest_fb = new ror.schema.upload.UploadChunkRequest();chunkRequest_fb.__assign(chunkRequest_bb.GetInt(chunkRequest_bb.Position) + chunkRequest_bb.Position, chunkRequest_bb); + applicationClaimTicket(chunkRequest_fb, new RateTicketReturn(rateTicketReturn, false)); + } + + [GrapeshotApplicationRatePINVOKE.MonoPInvokeCallback(typeof(SwigDelegateApplicationRate_2_Dispatcher))] + private static void SwigDirectorapplicationClaimTicket_Dispatcher(global::System.IntPtr swigDelegateApplicationRate_2_Handle, FBIntermediateBuffer chunkRequest, global::System.IntPtr rateTicketReturn) { +var chunkRequest_buffer = new byte[chunkRequest.size];UnityEngine.Assertions.Assert.AreNotEqual(chunkRequest.size, (ulong) 0);System.Runtime.InteropServices.Marshal.Copy(chunkRequest.ptr, chunkRequest_buffer, 0, (int) chunkRequest.size);var chunkRequest_bb = new FlatBuffers.ByteBuffer(chunkRequest_buffer);var chunkRequest_fb = new ror.schema.upload.UploadChunkRequest();chunkRequest_fb.__assign(chunkRequest_bb.GetInt(chunkRequest_bb.Position) + chunkRequest_bb.Position, chunkRequest_bb); + global::System.Runtime.InteropServices.GCHandle gcHandle = global::System.Runtime.InteropServices.GCHandle.FromIntPtr(swigDelegateApplicationRate_2_Handle); + SwigDelegateApplicationRate_2 delegateSwigDelegateApplicationRate_2 = (SwigDelegateApplicationRate_2) gcHandle.Target; +delegateSwigDelegateApplicationRate_2(chunkRequest, rateTicketReturn); + } + + private void SwigDirectorapplicationTryClaimTicket(FBIntermediateBuffer chunkRequest, global::System.IntPtr rateTicketReturn) { +var chunkRequest_buffer = new byte[chunkRequest.size];UnityEngine.Assertions.Assert.AreNotEqual(chunkRequest.size, (ulong) 0);System.Runtime.InteropServices.Marshal.Copy(chunkRequest.ptr, chunkRequest_buffer, 0, (int) chunkRequest.size);var chunkRequest_bb = new FlatBuffers.ByteBuffer(chunkRequest_buffer);var chunkRequest_fb = new ror.schema.upload.UploadChunkRequest();chunkRequest_fb.__assign(chunkRequest_bb.GetInt(chunkRequest_bb.Position) + chunkRequest_bb.Position, chunkRequest_bb); + applicationTryClaimTicket(chunkRequest_fb, new RateTicketReturn(rateTicketReturn, false)); + } + + [GrapeshotApplicationRatePINVOKE.MonoPInvokeCallback(typeof(SwigDelegateApplicationRate_3_Dispatcher))] + private static void SwigDirectorapplicationTryClaimTicket_Dispatcher(global::System.IntPtr swigDelegateApplicationRate_3_Handle, FBIntermediateBuffer chunkRequest, global::System.IntPtr rateTicketReturn) { +var chunkRequest_buffer = new byte[chunkRequest.size];UnityEngine.Assertions.Assert.AreNotEqual(chunkRequest.size, (ulong) 0);System.Runtime.InteropServices.Marshal.Copy(chunkRequest.ptr, chunkRequest_buffer, 0, (int) chunkRequest.size);var chunkRequest_bb = new FlatBuffers.ByteBuffer(chunkRequest_buffer);var chunkRequest_fb = new ror.schema.upload.UploadChunkRequest();chunkRequest_fb.__assign(chunkRequest_bb.GetInt(chunkRequest_bb.Position) + chunkRequest_bb.Position, chunkRequest_bb); + global::System.Runtime.InteropServices.GCHandle gcHandle = global::System.Runtime.InteropServices.GCHandle.FromIntPtr(swigDelegateApplicationRate_3_Handle); + SwigDelegateApplicationRate_3 delegateSwigDelegateApplicationRate_3 = (SwigDelegateApplicationRate_3) gcHandle.Target; +delegateSwigDelegateApplicationRate_3(chunkRequest, rateTicketReturn); + } + + public delegate void SwigDelegateApplicationRate_0(); + public delegate bool SwigDelegateApplicationRate_1(); + public delegate void SwigDelegateApplicationRate_2(FBIntermediateBuffer chunkRequest, global::System.IntPtr rateTicketReturn); + public delegate void SwigDelegateApplicationRate_3(FBIntermediateBuffer chunkRequest, global::System.IntPtr rateTicketReturn); + + private SwigDelegateApplicationRate_0 swigDelegate0; + private SwigDelegateApplicationRate_1 swigDelegate1; + private SwigDelegateApplicationRate_2 swigDelegate2; + private SwigDelegateApplicationRate_3 swigDelegate3; + + public delegate void SwigDelegateApplicationRate_0_Dispatcher(global::System.IntPtr swigDelegateApplicationRate_0_Handle); + public delegate bool SwigDelegateApplicationRate_1_Dispatcher(global::System.IntPtr swigDelegateApplicationRate_1_Handle); + public delegate void SwigDelegateApplicationRate_2_Dispatcher(global::System.IntPtr swigDelegateApplicationRate_2_Handle, FBIntermediateBuffer chunkRequest, global::System.IntPtr rateTicketReturn); + public delegate void SwigDelegateApplicationRate_3_Dispatcher(global::System.IntPtr swigDelegateApplicationRate_3_Handle, FBIntermediateBuffer chunkRequest, global::System.IntPtr rateTicketReturn); + + private SwigDelegateApplicationRate_0_Dispatcher swigDelegate0dispatcher; + private SwigDelegateApplicationRate_1_Dispatcher swigDelegate1dispatcher; + private SwigDelegateApplicationRate_2_Dispatcher swigDelegate2dispatcher; + private SwigDelegateApplicationRate_3_Dispatcher swigDelegate3dispatcher; + + private static global::System.Type[] swigMethodTypes0 = new global::System.Type[] { }; + private static global::System.Type[] swigMethodTypes1 = new global::System.Type[] { }; + private static global::System.Type[] swigMethodTypes2 = new global::System.Type[] { typeof(ror.schema.upload.UploadChunkRequest), typeof(RateTicketReturn) }; + private static global::System.Type[] swigMethodTypes3 = new global::System.Type[] { typeof(ror.schema.upload.UploadChunkRequest), typeof(RateTicketReturn) }; +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/ApplicationRate.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/ApplicationRate.cs.meta new file mode 100644 index 0000000..151e599 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/ApplicationRate.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 03935940086d5a5ad3aebe1881eb0549 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/ChunkFetcherParams.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/ChunkFetcherParams.cs new file mode 100644 index 0000000..90adcbe --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/ChunkFetcherParams.cs @@ -0,0 +1,82 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public class ChunkFetcherParams : global::System.IDisposable { + private global::System.Runtime.InteropServices.HandleRef swigCPtr; + protected bool swigCMemOwn; + + internal ChunkFetcherParams(global::System.IntPtr cPtr, bool cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr); + } + + internal static global::System.Runtime.InteropServices.HandleRef getCPtr(ChunkFetcherParams obj) { + return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; + } + + ~ChunkFetcherParams() { + Dispose(); + } + + public virtual void Dispose() { + lock(this) { + if (swigCPtr.Handle != global::System.IntPtr.Zero) { + if (swigCMemOwn) { + swigCMemOwn = false; + GrapeshotSessionPINVOKE.delete_ChunkFetcherParams(swigCPtr); + } + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); + } + global::System.GC.SuppressFinalize(this); + } + } + + public ulong index { + get { + ulong ret = GrapeshotSessionPINVOKE.ChunkFetcherParams_index_get(swigCPtr); + return ret; + } + } + + public UploadChunkBody_Ret bodyReturn { + get { + global::System.IntPtr cPtr = GrapeshotSessionPINVOKE.ChunkFetcherParams_bodyReturn_get(swigCPtr); + UploadChunkBody_Ret ret = (cPtr == global::System.IntPtr.Zero) ? null : new UploadChunkBody_Ret(cPtr, false); + return ret; + } + } + + public UploadAuth_Ret authReturn { + get { + global::System.IntPtr cPtr = GrapeshotSessionPINVOKE.ChunkFetcherParams_authReturn_get(swigCPtr); + UploadAuth_Ret ret = (cPtr == global::System.IntPtr.Zero) ? null : new UploadAuth_Ret(cPtr, false); + return ret; + } + } + + public UploadServiceInfo_Ret serviceInfoReturn { + set { + GrapeshotSessionPINVOKE.ChunkFetcherParams_serviceInfoReturn_set(swigCPtr, UploadServiceInfo_Ret.getCPtr(value)); + } + get { + global::System.IntPtr cPtr = GrapeshotSessionPINVOKE.ChunkFetcherParams_serviceInfoReturn_get(swigCPtr); + UploadServiceInfo_Ret ret = (cPtr == global::System.IntPtr.Zero) ? null : new UploadServiceInfo_Ret(cPtr, false); + return ret; + } + } + + public ChunkFetcherParams() : this(GrapeshotSessionPINVOKE.new_ChunkFetcherParams(), true) { + } + +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/ChunkFetcherParams.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/ChunkFetcherParams.cs.meta new file mode 100644 index 0000000..e3c9202 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/ChunkFetcherParams.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: ecc39afd443b4529f8848166b50330da diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/Driver.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/Driver.cs new file mode 100644 index 0000000..fabb9f6 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/Driver.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public abstract class Driver : global::System.IDisposable { + private global::System.Runtime.InteropServices.HandleRef swigCPtr; + private bool swigCMemOwnBase; + + internal Driver(global::System.IntPtr cPtr, bool cMemoryOwn) { + swigCMemOwnBase = cMemoryOwn; + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr); + } + + internal static global::System.Runtime.InteropServices.HandleRef getCPtr(Driver obj) { + return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; + } + + ~Driver() { + Dispose(); + } + + public virtual void Dispose() { + lock(this) { + if (swigCPtr.Handle != global::System.IntPtr.Zero) { + if (swigCMemOwnBase) { + swigCMemOwnBase = false; + GrapeshotDriverPINVOKE.delete_Driver(swigCPtr); + } + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); + } + global::System.GC.SuppressFinalize(this); + } + } + + public virtual void process() { + GrapeshotDriverPINVOKE.Driver_process(swigCPtr); + if (GrapeshotDriverPINVOKE.SWIGPendingException.Pending) throw GrapeshotDriverPINVOKE.SWIGPendingException.Retrieve(); + } + + public virtual void sendChunk(System.Guid clientIdentifier, ror.schema.upload.UploadChunkRequest chunk, RequestCallback_FunctionApplicationBridgeBase callback) { +var clientIdentifier_Bytes = clientIdentifier.ToByteArray();var clientIdentifier_ByteArrayHandle = System.Runtime.InteropServices.GCHandle.Alloc(clientIdentifier_Bytes ,System.Runtime.InteropServices.GCHandleType.Pinned);var clientIdentifier_buffer_ptr = clientIdentifier_ByteArrayHandle.AddrOfPinnedObject(); +var chunk_table = FlatBuffers.TableUtils.GetTable(chunk);var chunk_length = chunk_table.bb.Length;var chunk_pos = chunk_table.bb_pos;var chunk_seg = chunk_table.bb.ToArraySegment(chunk_pos, chunk_length - chunk_pos);var chunk_managed_array = chunk_seg.Array;var chunk_managed_handle = System.Runtime.InteropServices.GCHandle.Alloc(chunk_managed_array, System.Runtime.InteropServices.GCHandleType.Pinned);var chunk_buffer_ptr = chunk_managed_handle.AddrOfPinnedObject();System.IntPtr chunk_fb_ptr;unsafe { var chunk_buffer_unsafe_ptr = (byte*) chunk_buffer_ptr.ToPointer(); chunk_fb_ptr = (System.IntPtr) (chunk_buffer_unsafe_ptr + chunk_pos);}var chunk_intermediate = new FBIntermediateBuffer();chunk_intermediate.ptr = chunk_fb_ptr; +callback.allocApplicationCallback(); + try { + GrapeshotDriverPINVOKE.Driver_sendChunk(swigCPtr, clientIdentifier_buffer_ptr, chunk_intermediate, RequestCallback_FunctionApplicationBridgeBase.getCPtr(callback)); + if (GrapeshotDriverPINVOKE.SWIGPendingException.Pending) throw GrapeshotDriverPINVOKE.SWIGPendingException.Retrieve(); + } finally { +clientIdentifier_ByteArrayHandle.Free(); +chunk_managed_handle.Free(); + } + } + +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/Driver.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/Driver.cs.meta new file mode 100644 index 0000000..a710fd7 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/Driver.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: cf74cba75c38481c40041f24a01059d5 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/FBIntermediateBuffer.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/FBIntermediateBuffer.cs new file mode 100644 index 0000000..2916256 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/FBIntermediateBuffer.cs @@ -0,0 +1,21 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)] +public struct FBIntermediateBuffer { +public System.IntPtr ptr; +public System.UInt64 size; +public byte hasSize; + +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/FBIntermediateBuffer.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/FBIntermediateBuffer.cs.meta new file mode 100644 index 0000000..ccb832c --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/FBIntermediateBuffer.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: d4b16453ee2437cbc26d57634618accd diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/FinishedCallback_FunctionApplicationBridge.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/FinishedCallback_FunctionApplicationBridge.cs new file mode 100644 index 0000000..d279eea --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/FinishedCallback_FunctionApplicationBridge.cs @@ -0,0 +1,36 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public sealed class FinishedCallback_FunctionApplicationBridge : FinishedCallback_FunctionApplicationBridgeBase { + public delegate void Delegate(bool arg); + + private Delegate _delegate; + + public FinishedCallback_FunctionApplicationBridge(Delegate d) : base() { + _delegate = d; + } + + public override void releaseApplicationCallback() { + // This doesn't do anything except update reflection info so that the director thinks it needs + // to call this. + base.releaseApplicationCallback(); + } + + public override void invokeApplicationLogic(bool arg) { + try { + _delegate(arg); + } catch {} + } + +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/FinishedCallback_FunctionApplicationBridge.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/FinishedCallback_FunctionApplicationBridge.cs.meta new file mode 100644 index 0000000..90f1846 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/FinishedCallback_FunctionApplicationBridge.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 763ecf6a14cc4b9dac1aea29095dccec diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/FinishedCallback_FunctionApplicationBridgeBase.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/FinishedCallback_FunctionApplicationBridgeBase.cs new file mode 100644 index 0000000..6b427d9 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/FinishedCallback_FunctionApplicationBridgeBase.cs @@ -0,0 +1,155 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public abstract class FinishedCallback_FunctionApplicationBridgeBase : global::System.IDisposable { + /** DO NOT REMOVE THE FOLLOWING COMMENT **/ + /** THIS HAS BEEN SWIG CORRECTED: JJDKFJSIIIIDKJ **/ + private global::System.Runtime.InteropServices.GCHandle _swigDelegateHandle1; + private global::System.Runtime.InteropServices.GCHandle _swigDelegateHandle0; + private global::System.Runtime.InteropServices.HandleRef swigCPtr; + protected bool swigCMemOwn; + + internal FinishedCallback_FunctionApplicationBridgeBase(global::System.IntPtr cPtr, bool cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr); + } + + internal static global::System.Runtime.InteropServices.HandleRef getCPtr(FinishedCallback_FunctionApplicationBridgeBase obj) { + return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; + } + + ~FinishedCallback_FunctionApplicationBridgeBase() { + Dispose(); + } + + public virtual void Dispose() { + lock(this) { + if (swigCPtr.Handle != global::System.IntPtr.Zero) { + if (swigCMemOwn) { + swigCMemOwn = false; + GrapeshotSessionPINVOKE.delete_FinishedCallback_FunctionApplicationBridgeBase(swigCPtr); + } + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); + } + global::System.GC.SuppressFinalize(this); + _swigDelegateHandle0.Free(); + _swigDelegateHandle1.Free(); + } + } + + // Information used to prevent pre-mature GC of callbacks still being used from C++. + private ulong _refCount; + private System.Runtime.InteropServices.GCHandle _handle; + + /// Allocates a reference to this application callback so that it can't be released from memory + /// until all allocs have been meet with an equal number of releaseApplicationCallback. + public void allocApplicationCallback() { + lock(this) { + if (_refCount == 0) { + _handle = System.Runtime.InteropServices.GCHandle.Alloc(this); + } + + _refCount++; + } + } + + public virtual void invokeApplicationLogic(bool FinishedCallback_arg) { throw new System.NotImplementedException(); } + + public virtual void releaseApplicationCallback() { + // When releasing the application side callback, this means that one of the native side holds + // was terminated, thus cs should remove a reference count, once that count is zero free the + // handle. + lock(this) { + if (_refCount <= 0) { + return; + } + + _refCount -= 1; + + if (_refCount <= 0) { + _handle.Free(); + } + } + } + + + public FinishedCallback_FunctionApplicationBridgeBase() : this(GrapeshotSessionPINVOKE.new_FinishedCallback_FunctionApplicationBridgeBase(), true) { + SwigDirectorConnect(); + } + + private void SwigDirectorConnect() { + global::System.IntPtr swigDelegate0gcHandlePtr = global::System.IntPtr.Zero; + if (SwigDerivedClassHasMethod("invokeApplicationLogic", swigMethodTypes0)) { + swigDelegate0 = new SwigDelegateFinishedCallback_FunctionApplicationBridgeBase_0(SwigDirectorinvokeApplicationLogic); + swigDelegate0dispatcher = new SwigDelegateFinishedCallback_FunctionApplicationBridgeBase_0_Dispatcher(SwigDirectorinvokeApplicationLogic_Dispatcher); + + global::System.Runtime.InteropServices.GCHandle swigDelegate0gcHandle = global::System.Runtime.InteropServices.GCHandle.Alloc(swigDelegate0, global::System.Runtime.InteropServices.GCHandleType.Normal); + _swigDelegateHandle0 = swigDelegate0gcHandle; + swigDelegate0gcHandlePtr = global::System.Runtime.InteropServices.GCHandle.ToIntPtr(swigDelegate0gcHandle); + } + global::System.IntPtr swigDelegate1gcHandlePtr = global::System.IntPtr.Zero; + if (SwigDerivedClassHasMethod("releaseApplicationCallback", swigMethodTypes1)) { + swigDelegate1 = new SwigDelegateFinishedCallback_FunctionApplicationBridgeBase_1(SwigDirectorreleaseApplicationCallback); + swigDelegate1dispatcher = new SwigDelegateFinishedCallback_FunctionApplicationBridgeBase_1_Dispatcher(SwigDirectorreleaseApplicationCallback_Dispatcher); + + global::System.Runtime.InteropServices.GCHandle swigDelegate1gcHandle = global::System.Runtime.InteropServices.GCHandle.Alloc(swigDelegate1, global::System.Runtime.InteropServices.GCHandleType.Normal); + _swigDelegateHandle1 = swigDelegate1gcHandle; + swigDelegate1gcHandlePtr = global::System.Runtime.InteropServices.GCHandle.ToIntPtr(swigDelegate1gcHandle); + } + GrapeshotSessionPINVOKE.FinishedCallback_FunctionApplicationBridgeBase_director_connect(swigCPtr, swigDelegate0dispatcher, swigDelegate0gcHandlePtr, swigDelegate1dispatcher, swigDelegate1gcHandlePtr); + } + + private bool SwigDerivedClassHasMethod(string methodName, global::System.Type[] methodTypes) { + global::System.Reflection.MethodInfo methodInfo = this.GetType().GetMethod(methodName, global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance, null, methodTypes, null); + bool hasDerivedMethod = methodInfo.DeclaringType.IsSubclassOf(typeof(FinishedCallback_FunctionApplicationBridgeBase)); + return hasDerivedMethod; + } + + private void SwigDirectorinvokeApplicationLogic(bool FinishedCallback_arg) { + invokeApplicationLogic(FinishedCallback_arg); + } + + [GrapeshotSessionPINVOKE.MonoPInvokeCallback(typeof(SwigDelegateFinishedCallback_FunctionApplicationBridgeBase_0_Dispatcher))] + private static void SwigDirectorinvokeApplicationLogic_Dispatcher(global::System.IntPtr swigDelegateFinishedCallback_FunctionApplicationBridgeBase_0_Handle, bool FinishedCallback_arg) { + global::System.Runtime.InteropServices.GCHandle gcHandle = global::System.Runtime.InteropServices.GCHandle.FromIntPtr(swigDelegateFinishedCallback_FunctionApplicationBridgeBase_0_Handle); + SwigDelegateFinishedCallback_FunctionApplicationBridgeBase_0 delegateSwigDelegateFinishedCallback_FunctionApplicationBridgeBase_0 = (SwigDelegateFinishedCallback_FunctionApplicationBridgeBase_0) gcHandle.Target; +delegateSwigDelegateFinishedCallback_FunctionApplicationBridgeBase_0(FinishedCallback_arg); + } + + private void SwigDirectorreleaseApplicationCallback() { + releaseApplicationCallback(); + } + + [GrapeshotSessionPINVOKE.MonoPInvokeCallback(typeof(SwigDelegateFinishedCallback_FunctionApplicationBridgeBase_1_Dispatcher))] + private static void SwigDirectorreleaseApplicationCallback_Dispatcher(global::System.IntPtr swigDelegateFinishedCallback_FunctionApplicationBridgeBase_1_Handle) { + global::System.Runtime.InteropServices.GCHandle gcHandle = global::System.Runtime.InteropServices.GCHandle.FromIntPtr(swigDelegateFinishedCallback_FunctionApplicationBridgeBase_1_Handle); + SwigDelegateFinishedCallback_FunctionApplicationBridgeBase_1 delegateSwigDelegateFinishedCallback_FunctionApplicationBridgeBase_1 = (SwigDelegateFinishedCallback_FunctionApplicationBridgeBase_1) gcHandle.Target; +delegateSwigDelegateFinishedCallback_FunctionApplicationBridgeBase_1(); + } + + public delegate void SwigDelegateFinishedCallback_FunctionApplicationBridgeBase_0(bool FinishedCallback_arg); + public delegate void SwigDelegateFinishedCallback_FunctionApplicationBridgeBase_1(); + + private SwigDelegateFinishedCallback_FunctionApplicationBridgeBase_0 swigDelegate0; + private SwigDelegateFinishedCallback_FunctionApplicationBridgeBase_1 swigDelegate1; + + public delegate void SwigDelegateFinishedCallback_FunctionApplicationBridgeBase_0_Dispatcher(global::System.IntPtr swigDelegateFinishedCallback_FunctionApplicationBridgeBase_0_Handle, bool FinishedCallback_arg); + public delegate void SwigDelegateFinishedCallback_FunctionApplicationBridgeBase_1_Dispatcher(global::System.IntPtr swigDelegateFinishedCallback_FunctionApplicationBridgeBase_1_Handle); + + private SwigDelegateFinishedCallback_FunctionApplicationBridgeBase_0_Dispatcher swigDelegate0dispatcher; + private SwigDelegateFinishedCallback_FunctionApplicationBridgeBase_1_Dispatcher swigDelegate1dispatcher; + + private static global::System.Type[] swigMethodTypes0 = new global::System.Type[] { typeof(bool) }; + private static global::System.Type[] swigMethodTypes1 = new global::System.Type[] { }; +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/FinishedCallback_FunctionApplicationBridgeBase.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/FinishedCallback_FunctionApplicationBridgeBase.cs.meta new file mode 100644 index 0000000..143a123 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/FinishedCallback_FunctionApplicationBridgeBase.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: ea4ae89cfb09d55cb0cb7c5ed7595ed5 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/FuncRateTicket.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/FuncRateTicket.cs new file mode 100644 index 0000000..202300c --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/FuncRateTicket.cs @@ -0,0 +1,55 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public class FuncRateTicket : RateTicket { + private global::System.Runtime.InteropServices.HandleRef swigCPtr; + private bool swigCMemOwnDerived; + + internal FuncRateTicket(global::System.IntPtr cPtr, bool cMemoryOwn) : base(GrapeshotFuncRateTicketPINVOKE.FuncRateTicket_SWIGSmartPtrUpcast(cPtr), true) { + swigCMemOwnDerived = cMemoryOwn; + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr); + } + + internal static global::System.Runtime.InteropServices.HandleRef getCPtr(FuncRateTicket obj) { + return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; + } + + ~FuncRateTicket() { + Dispose(); + } + + public override void Dispose() { + lock(this) { + if (swigCPtr.Handle != global::System.IntPtr.Zero) { + if (swigCMemOwnDerived) { + swigCMemOwnDerived = false; + GrapeshotFuncRateTicketPINVOKE.delete_FuncRateTicket(swigCPtr); + } + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); + } + global::System.GC.SuppressFinalize(this); + base.Dispose(); + } + } + + public static FuncRateTicket createFuncRateTicket(FuncRateTicketCallback_FunctionApplicationBridgeBase callback) { +callback.allocApplicationCallback(); + { + global::System.IntPtr cPtr = GrapeshotFuncRateTicketPINVOKE.FuncRateTicket_createFuncRateTicket(FuncRateTicketCallback_FunctionApplicationBridgeBase.getCPtr(callback)); + FuncRateTicket ret = (cPtr == global::System.IntPtr.Zero) ? null : new FuncRateTicket(cPtr, true); + return ret; + } + } + +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/FuncRateTicket.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/FuncRateTicket.cs.meta new file mode 100644 index 0000000..c8622fd --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/FuncRateTicket.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 0712d97eee39eb1a17b41d981299a316 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/FuncRateTicketCallback_FunctionApplicationBridge.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/FuncRateTicketCallback_FunctionApplicationBridge.cs new file mode 100644 index 0000000..cb1b761 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/FuncRateTicketCallback_FunctionApplicationBridge.cs @@ -0,0 +1,36 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public sealed class FuncRateTicketCallback_FunctionApplicationBridge : FuncRateTicketCallback_FunctionApplicationBridgeBase { + public delegate void Delegate(); + + private Delegate _delegate; + + public FuncRateTicketCallback_FunctionApplicationBridge(Delegate d) : base() { + _delegate = d; + } + + public override void releaseApplicationCallback() { + // This doesn't do anything except update reflection info so that the director thinks it needs + // to call this. + base.releaseApplicationCallback(); + } + + public override void invokeApplicationLogic() { + try { + _delegate(); + } catch {} + } + +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/FuncRateTicketCallback_FunctionApplicationBridge.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/FuncRateTicketCallback_FunctionApplicationBridge.cs.meta new file mode 100644 index 0000000..0c8b08d --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/FuncRateTicketCallback_FunctionApplicationBridge.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 116738d17a38adc1481968a8fde7cddf diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/FuncRateTicketCallback_FunctionApplicationBridgeBase.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/FuncRateTicketCallback_FunctionApplicationBridgeBase.cs new file mode 100644 index 0000000..a7a7826 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/FuncRateTicketCallback_FunctionApplicationBridgeBase.cs @@ -0,0 +1,155 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public abstract class FuncRateTicketCallback_FunctionApplicationBridgeBase : global::System.IDisposable { + /** DO NOT REMOVE THE FOLLOWING COMMENT **/ + /** THIS HAS BEEN SWIG CORRECTED: JJDKFJSIIIIDKJ **/ + private global::System.Runtime.InteropServices.GCHandle _swigDelegateHandle1; + private global::System.Runtime.InteropServices.GCHandle _swigDelegateHandle0; + private global::System.Runtime.InteropServices.HandleRef swigCPtr; + protected bool swigCMemOwn; + + internal FuncRateTicketCallback_FunctionApplicationBridgeBase(global::System.IntPtr cPtr, bool cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr); + } + + internal static global::System.Runtime.InteropServices.HandleRef getCPtr(FuncRateTicketCallback_FunctionApplicationBridgeBase obj) { + return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; + } + + ~FuncRateTicketCallback_FunctionApplicationBridgeBase() { + Dispose(); + } + + public virtual void Dispose() { + lock(this) { + if (swigCPtr.Handle != global::System.IntPtr.Zero) { + if (swigCMemOwn) { + swigCMemOwn = false; + GrapeshotFuncRateTicketPINVOKE.delete_FuncRateTicketCallback_FunctionApplicationBridgeBase(swigCPtr); + } + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); + } + global::System.GC.SuppressFinalize(this); + _swigDelegateHandle0.Free(); + _swigDelegateHandle1.Free(); + } + } + + // Information used to prevent pre-mature GC of callbacks still being used from C++. + private ulong _refCount; + private System.Runtime.InteropServices.GCHandle _handle; + + /// Allocates a reference to this application callback so that it can't be released from memory + /// until all allocs have been meet with an equal number of releaseApplicationCallback. + public void allocApplicationCallback() { + lock(this) { + if (_refCount == 0) { + _handle = System.Runtime.InteropServices.GCHandle.Alloc(this); + } + + _refCount++; + } + } + + public virtual void invokeApplicationLogic() { throw new System.NotImplementedException(); } + + public virtual void releaseApplicationCallback() { + // When releasing the application side callback, this means that one of the native side holds + // was terminated, thus cs should remove a reference count, once that count is zero free the + // handle. + lock(this) { + if (_refCount <= 0) { + return; + } + + _refCount -= 1; + + if (_refCount <= 0) { + _handle.Free(); + } + } + } + + + public FuncRateTicketCallback_FunctionApplicationBridgeBase() : this(GrapeshotFuncRateTicketPINVOKE.new_FuncRateTicketCallback_FunctionApplicationBridgeBase(), true) { + SwigDirectorConnect(); + } + + private void SwigDirectorConnect() { + global::System.IntPtr swigDelegate0gcHandlePtr = global::System.IntPtr.Zero; + if (SwigDerivedClassHasMethod("invokeApplicationLogic", swigMethodTypes0)) { + swigDelegate0 = new SwigDelegateFuncRateTicketCallback_FunctionApplicationBridgeBase_0(SwigDirectorinvokeApplicationLogic); + swigDelegate0dispatcher = new SwigDelegateFuncRateTicketCallback_FunctionApplicationBridgeBase_0_Dispatcher(SwigDirectorinvokeApplicationLogic_Dispatcher); + + global::System.Runtime.InteropServices.GCHandle swigDelegate0gcHandle = global::System.Runtime.InteropServices.GCHandle.Alloc(swigDelegate0, global::System.Runtime.InteropServices.GCHandleType.Normal); + _swigDelegateHandle0 = swigDelegate0gcHandle; + swigDelegate0gcHandlePtr = global::System.Runtime.InteropServices.GCHandle.ToIntPtr(swigDelegate0gcHandle); + } + global::System.IntPtr swigDelegate1gcHandlePtr = global::System.IntPtr.Zero; + if (SwigDerivedClassHasMethod("releaseApplicationCallback", swigMethodTypes1)) { + swigDelegate1 = new SwigDelegateFuncRateTicketCallback_FunctionApplicationBridgeBase_1(SwigDirectorreleaseApplicationCallback); + swigDelegate1dispatcher = new SwigDelegateFuncRateTicketCallback_FunctionApplicationBridgeBase_1_Dispatcher(SwigDirectorreleaseApplicationCallback_Dispatcher); + + global::System.Runtime.InteropServices.GCHandle swigDelegate1gcHandle = global::System.Runtime.InteropServices.GCHandle.Alloc(swigDelegate1, global::System.Runtime.InteropServices.GCHandleType.Normal); + _swigDelegateHandle1 = swigDelegate1gcHandle; + swigDelegate1gcHandlePtr = global::System.Runtime.InteropServices.GCHandle.ToIntPtr(swigDelegate1gcHandle); + } + GrapeshotFuncRateTicketPINVOKE.FuncRateTicketCallback_FunctionApplicationBridgeBase_director_connect(swigCPtr, swigDelegate0dispatcher, swigDelegate0gcHandlePtr, swigDelegate1dispatcher, swigDelegate1gcHandlePtr); + } + + private bool SwigDerivedClassHasMethod(string methodName, global::System.Type[] methodTypes) { + global::System.Reflection.MethodInfo methodInfo = this.GetType().GetMethod(methodName, global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance, null, methodTypes, null); + bool hasDerivedMethod = methodInfo.DeclaringType.IsSubclassOf(typeof(FuncRateTicketCallback_FunctionApplicationBridgeBase)); + return hasDerivedMethod; + } + + private void SwigDirectorinvokeApplicationLogic() { + invokeApplicationLogic(); + } + + [GrapeshotFuncRateTicketPINVOKE.MonoPInvokeCallback(typeof(SwigDelegateFuncRateTicketCallback_FunctionApplicationBridgeBase_0_Dispatcher))] + private static void SwigDirectorinvokeApplicationLogic_Dispatcher(global::System.IntPtr swigDelegateFuncRateTicketCallback_FunctionApplicationBridgeBase_0_Handle) { + global::System.Runtime.InteropServices.GCHandle gcHandle = global::System.Runtime.InteropServices.GCHandle.FromIntPtr(swigDelegateFuncRateTicketCallback_FunctionApplicationBridgeBase_0_Handle); + SwigDelegateFuncRateTicketCallback_FunctionApplicationBridgeBase_0 delegateSwigDelegateFuncRateTicketCallback_FunctionApplicationBridgeBase_0 = (SwigDelegateFuncRateTicketCallback_FunctionApplicationBridgeBase_0) gcHandle.Target; +delegateSwigDelegateFuncRateTicketCallback_FunctionApplicationBridgeBase_0(); + } + + private void SwigDirectorreleaseApplicationCallback() { + releaseApplicationCallback(); + } + + [GrapeshotFuncRateTicketPINVOKE.MonoPInvokeCallback(typeof(SwigDelegateFuncRateTicketCallback_FunctionApplicationBridgeBase_1_Dispatcher))] + private static void SwigDirectorreleaseApplicationCallback_Dispatcher(global::System.IntPtr swigDelegateFuncRateTicketCallback_FunctionApplicationBridgeBase_1_Handle) { + global::System.Runtime.InteropServices.GCHandle gcHandle = global::System.Runtime.InteropServices.GCHandle.FromIntPtr(swigDelegateFuncRateTicketCallback_FunctionApplicationBridgeBase_1_Handle); + SwigDelegateFuncRateTicketCallback_FunctionApplicationBridgeBase_1 delegateSwigDelegateFuncRateTicketCallback_FunctionApplicationBridgeBase_1 = (SwigDelegateFuncRateTicketCallback_FunctionApplicationBridgeBase_1) gcHandle.Target; +delegateSwigDelegateFuncRateTicketCallback_FunctionApplicationBridgeBase_1(); + } + + public delegate void SwigDelegateFuncRateTicketCallback_FunctionApplicationBridgeBase_0(); + public delegate void SwigDelegateFuncRateTicketCallback_FunctionApplicationBridgeBase_1(); + + private SwigDelegateFuncRateTicketCallback_FunctionApplicationBridgeBase_0 swigDelegate0; + private SwigDelegateFuncRateTicketCallback_FunctionApplicationBridgeBase_1 swigDelegate1; + + public delegate void SwigDelegateFuncRateTicketCallback_FunctionApplicationBridgeBase_0_Dispatcher(global::System.IntPtr swigDelegateFuncRateTicketCallback_FunctionApplicationBridgeBase_0_Handle); + public delegate void SwigDelegateFuncRateTicketCallback_FunctionApplicationBridgeBase_1_Dispatcher(global::System.IntPtr swigDelegateFuncRateTicketCallback_FunctionApplicationBridgeBase_1_Handle); + + private SwigDelegateFuncRateTicketCallback_FunctionApplicationBridgeBase_0_Dispatcher swigDelegate0dispatcher; + private SwigDelegateFuncRateTicketCallback_FunctionApplicationBridgeBase_1_Dispatcher swigDelegate1dispatcher; + + private static global::System.Type[] swigMethodTypes0 = new global::System.Type[] { }; + private static global::System.Type[] swigMethodTypes1 = new global::System.Type[] { }; +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/FuncRateTicketCallback_FunctionApplicationBridgeBase.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/FuncRateTicketCallback_FunctionApplicationBridgeBase.cs.meta new file mode 100644 index 0000000..7b7991d --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/FuncRateTicketCallback_FunctionApplicationBridgeBase.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 1137d00571ad683f65cd4d7692604365 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotApplicationRate.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotApplicationRate.cs new file mode 100644 index 0000000..50f14ca --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotApplicationRate.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public class GrapeshotApplicationRate { +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotApplicationRate.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotApplicationRate.cs.meta new file mode 100644 index 0000000..bd7b057 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotApplicationRate.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 935ebb2d9ffc103e53bacdd2623427d8 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotApplicationRatePINVOKE.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotApplicationRatePINVOKE.cs new file mode 100644 index 0000000..ccc8b8f --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotApplicationRatePINVOKE.cs @@ -0,0 +1,334 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +class GrapeshotApplicationRatePINVOKE { + + /// For Mono AOT platforms compatibility + /// This attribute can be defined in any assembly for Mono AOT to use it. + public class MonoPInvokeCallbackAttribute : global::System.Attribute { + public MonoPInvokeCallbackAttribute(global::System.Type t) { + } + } + + + protected class SWIGExceptionHelper { + public delegate void ExceptionDelegate(string message); + public delegate void ExceptionArgumentDelegate(string message, string paramName); + + static ExceptionDelegate applicationDelegate = new ExceptionDelegate(SetPendingApplicationException); + static ExceptionDelegate arithmeticDelegate = new ExceptionDelegate(SetPendingArithmeticException); + static ExceptionDelegate divideByZeroDelegate = new ExceptionDelegate(SetPendingDivideByZeroException); + static ExceptionDelegate indexOutOfRangeDelegate = new ExceptionDelegate(SetPendingIndexOutOfRangeException); + static ExceptionDelegate invalidCastDelegate = new ExceptionDelegate(SetPendingInvalidCastException); + static ExceptionDelegate invalidOperationDelegate = new ExceptionDelegate(SetPendingInvalidOperationException); + static ExceptionDelegate ioDelegate = new ExceptionDelegate(SetPendingIOException); + static ExceptionDelegate nullReferenceDelegate = new ExceptionDelegate(SetPendingNullReferenceException); + static ExceptionDelegate outOfMemoryDelegate = new ExceptionDelegate(SetPendingOutOfMemoryException); + static ExceptionDelegate overflowDelegate = new ExceptionDelegate(SetPendingOverflowException); + static ExceptionDelegate systemDelegate = new ExceptionDelegate(SetPendingSystemException); + + static ExceptionArgumentDelegate argumentDelegate = new ExceptionArgumentDelegate(SetPendingArgumentException); + static ExceptionArgumentDelegate argumentNullDelegate = new ExceptionArgumentDelegate(SetPendingArgumentNullException); + static ExceptionArgumentDelegate argumentOutOfRangeDelegate = new ExceptionArgumentDelegate(SetPendingArgumentOutOfRangeException); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="SWIGRegisterExceptionCallbacks_GrapeshotApplicationRate")] + public static extern void SWIGRegisterExceptionCallbacks_GrapeshotApplicationRate( + ExceptionDelegate applicationDelegate, + ExceptionDelegate arithmeticDelegate, + ExceptionDelegate divideByZeroDelegate, + ExceptionDelegate indexOutOfRangeDelegate, + ExceptionDelegate invalidCastDelegate, + ExceptionDelegate invalidOperationDelegate, + ExceptionDelegate ioDelegate, + ExceptionDelegate nullReferenceDelegate, + ExceptionDelegate outOfMemoryDelegate, + ExceptionDelegate overflowDelegate, + ExceptionDelegate systemExceptionDelegate); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="SWIGRegisterExceptionArgumentCallbacks_GrapeshotApplicationRate")] + public static extern void SWIGRegisterExceptionCallbacksArgument_GrapeshotApplicationRate( + ExceptionArgumentDelegate argumentDelegate, + ExceptionArgumentDelegate argumentNullDelegate, + ExceptionArgumentDelegate argumentOutOfRangeDelegate); + + + [GrapeshotApplicationRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingApplicationException(string message) { + SWIGPendingException.Set(new global::System.ApplicationException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotApplicationRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingArithmeticException(string message) { + SWIGPendingException.Set(new global::System.ArithmeticException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotApplicationRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingDivideByZeroException(string message) { + SWIGPendingException.Set(new global::System.DivideByZeroException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotApplicationRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingIndexOutOfRangeException(string message) { + SWIGPendingException.Set(new global::System.IndexOutOfRangeException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotApplicationRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingInvalidCastException(string message) { + SWIGPendingException.Set(new global::System.InvalidCastException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotApplicationRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingInvalidOperationException(string message) { + SWIGPendingException.Set(new global::System.InvalidOperationException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotApplicationRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingIOException(string message) { + SWIGPendingException.Set(new global::System.IO.IOException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotApplicationRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingNullReferenceException(string message) { + SWIGPendingException.Set(new global::System.NullReferenceException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotApplicationRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingOutOfMemoryException(string message) { + SWIGPendingException.Set(new global::System.OutOfMemoryException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotApplicationRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingOverflowException(string message) { + SWIGPendingException.Set(new global::System.OverflowException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotApplicationRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingSystemException(string message) { + SWIGPendingException.Set(new global::System.SystemException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotApplicationRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionArgumentDelegate))] + + + static void SetPendingArgumentException(string message, string paramName) { + SWIGPendingException.Set(new global::System.ArgumentException(message, paramName, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotApplicationRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionArgumentDelegate))] + + + static void SetPendingArgumentNullException(string message, string paramName) { + global::System.Exception e = SWIGPendingException.Retrieve(); + if (e != null) message = message + " Inner Exception: " + e.Message; + SWIGPendingException.Set(new global::System.ArgumentNullException(paramName, message)); + } + + + + [GrapeshotApplicationRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionArgumentDelegate))] + + + static void SetPendingArgumentOutOfRangeException(string message, string paramName) { + global::System.Exception e = SWIGPendingException.Retrieve(); + if (e != null) message = message + " Inner Exception: " + e.Message; + SWIGPendingException.Set(new global::System.ArgumentOutOfRangeException(paramName, message)); + } + + static SWIGExceptionHelper() { + SWIGRegisterExceptionCallbacks_GrapeshotApplicationRate( + applicationDelegate, + arithmeticDelegate, + divideByZeroDelegate, + indexOutOfRangeDelegate, + invalidCastDelegate, + invalidOperationDelegate, + ioDelegate, + nullReferenceDelegate, + outOfMemoryDelegate, + overflowDelegate, + systemDelegate); + + SWIGRegisterExceptionCallbacksArgument_GrapeshotApplicationRate( + argumentDelegate, + argumentNullDelegate, + argumentOutOfRangeDelegate); + } + } + + protected static SWIGExceptionHelper swigExceptionHelper = new SWIGExceptionHelper(); + + public class SWIGPendingException { + [global::System.ThreadStatic] + private static global::System.Exception pendingException = null; + private static int numExceptionsPending = 0; + + public static bool Pending { + get { + bool pending = false; + if (numExceptionsPending > 0) + if (pendingException != null) + pending = true; + return pending; + } + } + + public static void Set(global::System.Exception e) { + if (pendingException != null) + throw new global::System.ApplicationException("FATAL: An earlier pending exception from unmanaged code was missed and thus not thrown (" + pendingException.ToString() + ")", e); + pendingException = e; + lock(typeof(GrapeshotApplicationRatePINVOKE)) { + numExceptionsPending++; + } + } + + public static global::System.Exception Retrieve() { + global::System.Exception e = null; + if (numExceptionsPending > 0) { + if (pendingException != null) { + e = pendingException; + pendingException = null; + lock(typeof(GrapeshotApplicationRatePINVOKE)) { + numExceptionsPending--; + } + } + } + return e; + } + } + + + protected class SWIGStringHelper { + public delegate string SWIGStringDelegate(string message); + static SWIGStringDelegate stringDelegate = new SWIGStringDelegate(CreateString); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="SWIGRegisterStringCallback_GrapeshotApplicationRate")] + public static extern void SWIGRegisterStringCallback_GrapeshotApplicationRate(SWIGStringDelegate stringDelegate); + + + [GrapeshotApplicationRatePINVOKE.MonoPInvokeCallback(typeof(SWIGStringDelegate))] + + + static string CreateString(string cString) { + return cString; + } + + static SWIGStringHelper() { + SWIGRegisterStringCallback_GrapeshotApplicationRate(stringDelegate); + } + } + + static protected SWIGStringHelper swigStringHelper = new SWIGStringHelper(); + + + static GrapeshotApplicationRatePINVOKE() { + } + + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_RateTicketReturn_ret")] + public static extern void RateTicketReturn_ret(global::System.Runtime.InteropServices.HandleRef jarg1, global::System.Runtime.InteropServices.HandleRef jarg2); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_new_RateTicketReturn")] + public static extern global::System.IntPtr new_RateTicketReturn(); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_delete_RateTicketReturn")] + public static extern void delete_RateTicketReturn(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_ApplicationRate_claimTicket")] + public static extern global::System.IntPtr ApplicationRate_claimTicket(global::System.Runtime.InteropServices.HandleRef jarg1, FBIntermediateBuffer jarg2); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_ApplicationRate_applicationClaimTicket")] + public static extern void ApplicationRate_applicationClaimTicket(global::System.Runtime.InteropServices.HandleRef jarg1, FBIntermediateBuffer jarg2, global::System.Runtime.InteropServices.HandleRef jarg3); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_ApplicationRate_applicationClaimTicketSwigExplicitApplicationRate")] + public static extern void ApplicationRate_applicationClaimTicketSwigExplicitApplicationRate(global::System.Runtime.InteropServices.HandleRef jarg1, FBIntermediateBuffer jarg2, global::System.Runtime.InteropServices.HandleRef jarg3); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_ApplicationRate_tryClaimTicket")] + public static extern global::System.IntPtr ApplicationRate_tryClaimTicket(global::System.Runtime.InteropServices.HandleRef jarg1, FBIntermediateBuffer jarg2); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_ApplicationRate_applicationTryClaimTicket")] + public static extern void ApplicationRate_applicationTryClaimTicket(global::System.Runtime.InteropServices.HandleRef jarg1, FBIntermediateBuffer jarg2, global::System.Runtime.InteropServices.HandleRef jarg3); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_ApplicationRate_applicationTryClaimTicketSwigExplicitApplicationRate")] + public static extern void ApplicationRate_applicationTryClaimTicketSwigExplicitApplicationRate(global::System.Runtime.InteropServices.HandleRef jarg1, FBIntermediateBuffer jarg2, global::System.Runtime.InteropServices.HandleRef jarg3); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_ApplicationRate_areFreeTickets")] + public static extern bool ApplicationRate_areFreeTickets(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_ApplicationRate_areFreeTicketsSwigExplicitApplicationRate")] + public static extern bool ApplicationRate_areFreeTicketsSwigExplicitApplicationRate(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_ApplicationRate_process")] + public static extern void ApplicationRate_process(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_ApplicationRate_processSwigExplicitApplicationRate")] + public static extern void ApplicationRate_processSwigExplicitApplicationRate(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_delete_ApplicationRate")] + public static extern void delete_ApplicationRate(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_new_ApplicationRate")] + public static extern global::System.IntPtr new_ApplicationRate(); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_ApplicationRate_director_connect")] + public static extern void ApplicationRate_director_connect(global::System.Runtime.InteropServices.HandleRef jarg1, ApplicationRate.SwigDelegateApplicationRate_0_Dispatcher delegate0_dispatcher, global::System.IntPtr delegate0gcHandlePtr, ApplicationRate.SwigDelegateApplicationRate_1_Dispatcher delegate1_dispatcher, global::System.IntPtr delegate1gcHandlePtr, ApplicationRate.SwigDelegateApplicationRate_2_Dispatcher delegate2_dispatcher, global::System.IntPtr delegate2gcHandlePtr, ApplicationRate.SwigDelegateApplicationRate_3_Dispatcher delegate3_dispatcher, global::System.IntPtr delegate3gcHandlePtr); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_ApplicationRate_SWIGSmartPtrUpcast")] + public static extern global::System.IntPtr ApplicationRate_SWIGSmartPtrUpcast(global::System.IntPtr jarg1); +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotApplicationRatePINVOKE.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotApplicationRatePINVOKE.cs.meta new file mode 100644 index 0000000..0cfd805 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotApplicationRatePINVOKE.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: ceb7ae3992da51cc2fb044202eb6be55 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotBackendTopology.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotBackendTopology.cs new file mode 100644 index 0000000..84d2f64 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotBackendTopology.cs @@ -0,0 +1,27 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public class GrapeshotBackendTopology { + public static Topology createDefaultGCSTopology(System.Guid stage) { +var stage_Bytes = stage.ToByteArray();var stage_ByteArrayHandle = System.Runtime.InteropServices.GCHandle.Alloc(stage_Bytes ,System.Runtime.InteropServices.GCHandleType.Pinned);var stage_buffer_ptr = stage_ByteArrayHandle.AddrOfPinnedObject(); + try { + global::System.IntPtr cPtr = GrapeshotBackendTopologyPINVOKE.createDefaultGCSTopology(stage_buffer_ptr); + Topology ret = (cPtr == global::System.IntPtr.Zero) ? null : new Topology(cPtr, true); + return ret; + } finally { +stage_ByteArrayHandle.Free(); + } + } + +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotBackendTopology.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotBackendTopology.cs.meta new file mode 100644 index 0000000..abf9f5f --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotBackendTopology.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 570dd53374578552898048d70745a95b diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotBackendTopologyPINVOKE.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotBackendTopologyPINVOKE.cs new file mode 100644 index 0000000..6371aa9 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotBackendTopologyPINVOKE.cs @@ -0,0 +1,289 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +class GrapeshotBackendTopologyPINVOKE { + + /// For Mono AOT platforms compatibility + /// This attribute can be defined in any assembly for Mono AOT to use it. + public class MonoPInvokeCallbackAttribute : global::System.Attribute { + public MonoPInvokeCallbackAttribute(global::System.Type t) { + } + } + + + protected class SWIGExceptionHelper { + public delegate void ExceptionDelegate(string message); + public delegate void ExceptionArgumentDelegate(string message, string paramName); + + static ExceptionDelegate applicationDelegate = new ExceptionDelegate(SetPendingApplicationException); + static ExceptionDelegate arithmeticDelegate = new ExceptionDelegate(SetPendingArithmeticException); + static ExceptionDelegate divideByZeroDelegate = new ExceptionDelegate(SetPendingDivideByZeroException); + static ExceptionDelegate indexOutOfRangeDelegate = new ExceptionDelegate(SetPendingIndexOutOfRangeException); + static ExceptionDelegate invalidCastDelegate = new ExceptionDelegate(SetPendingInvalidCastException); + static ExceptionDelegate invalidOperationDelegate = new ExceptionDelegate(SetPendingInvalidOperationException); + static ExceptionDelegate ioDelegate = new ExceptionDelegate(SetPendingIOException); + static ExceptionDelegate nullReferenceDelegate = new ExceptionDelegate(SetPendingNullReferenceException); + static ExceptionDelegate outOfMemoryDelegate = new ExceptionDelegate(SetPendingOutOfMemoryException); + static ExceptionDelegate overflowDelegate = new ExceptionDelegate(SetPendingOverflowException); + static ExceptionDelegate systemDelegate = new ExceptionDelegate(SetPendingSystemException); + + static ExceptionArgumentDelegate argumentDelegate = new ExceptionArgumentDelegate(SetPendingArgumentException); + static ExceptionArgumentDelegate argumentNullDelegate = new ExceptionArgumentDelegate(SetPendingArgumentNullException); + static ExceptionArgumentDelegate argumentOutOfRangeDelegate = new ExceptionArgumentDelegate(SetPendingArgumentOutOfRangeException); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="SWIGRegisterExceptionCallbacks_GrapeshotBackendTopology")] + public static extern void SWIGRegisterExceptionCallbacks_GrapeshotBackendTopology( + ExceptionDelegate applicationDelegate, + ExceptionDelegate arithmeticDelegate, + ExceptionDelegate divideByZeroDelegate, + ExceptionDelegate indexOutOfRangeDelegate, + ExceptionDelegate invalidCastDelegate, + ExceptionDelegate invalidOperationDelegate, + ExceptionDelegate ioDelegate, + ExceptionDelegate nullReferenceDelegate, + ExceptionDelegate outOfMemoryDelegate, + ExceptionDelegate overflowDelegate, + ExceptionDelegate systemExceptionDelegate); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="SWIGRegisterExceptionArgumentCallbacks_GrapeshotBackendTopology")] + public static extern void SWIGRegisterExceptionCallbacksArgument_GrapeshotBackendTopology( + ExceptionArgumentDelegate argumentDelegate, + ExceptionArgumentDelegate argumentNullDelegate, + ExceptionArgumentDelegate argumentOutOfRangeDelegate); + + + [GrapeshotBackendTopologyPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingApplicationException(string message) { + SWIGPendingException.Set(new global::System.ApplicationException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotBackendTopologyPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingArithmeticException(string message) { + SWIGPendingException.Set(new global::System.ArithmeticException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotBackendTopologyPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingDivideByZeroException(string message) { + SWIGPendingException.Set(new global::System.DivideByZeroException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotBackendTopologyPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingIndexOutOfRangeException(string message) { + SWIGPendingException.Set(new global::System.IndexOutOfRangeException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotBackendTopologyPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingInvalidCastException(string message) { + SWIGPendingException.Set(new global::System.InvalidCastException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotBackendTopologyPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingInvalidOperationException(string message) { + SWIGPendingException.Set(new global::System.InvalidOperationException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotBackendTopologyPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingIOException(string message) { + SWIGPendingException.Set(new global::System.IO.IOException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotBackendTopologyPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingNullReferenceException(string message) { + SWIGPendingException.Set(new global::System.NullReferenceException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotBackendTopologyPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingOutOfMemoryException(string message) { + SWIGPendingException.Set(new global::System.OutOfMemoryException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotBackendTopologyPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingOverflowException(string message) { + SWIGPendingException.Set(new global::System.OverflowException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotBackendTopologyPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingSystemException(string message) { + SWIGPendingException.Set(new global::System.SystemException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotBackendTopologyPINVOKE.MonoPInvokeCallback(typeof(ExceptionArgumentDelegate))] + + + static void SetPendingArgumentException(string message, string paramName) { + SWIGPendingException.Set(new global::System.ArgumentException(message, paramName, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotBackendTopologyPINVOKE.MonoPInvokeCallback(typeof(ExceptionArgumentDelegate))] + + + static void SetPendingArgumentNullException(string message, string paramName) { + global::System.Exception e = SWIGPendingException.Retrieve(); + if (e != null) message = message + " Inner Exception: " + e.Message; + SWIGPendingException.Set(new global::System.ArgumentNullException(paramName, message)); + } + + + + [GrapeshotBackendTopologyPINVOKE.MonoPInvokeCallback(typeof(ExceptionArgumentDelegate))] + + + static void SetPendingArgumentOutOfRangeException(string message, string paramName) { + global::System.Exception e = SWIGPendingException.Retrieve(); + if (e != null) message = message + " Inner Exception: " + e.Message; + SWIGPendingException.Set(new global::System.ArgumentOutOfRangeException(paramName, message)); + } + + static SWIGExceptionHelper() { + SWIGRegisterExceptionCallbacks_GrapeshotBackendTopology( + applicationDelegate, + arithmeticDelegate, + divideByZeroDelegate, + indexOutOfRangeDelegate, + invalidCastDelegate, + invalidOperationDelegate, + ioDelegate, + nullReferenceDelegate, + outOfMemoryDelegate, + overflowDelegate, + systemDelegate); + + SWIGRegisterExceptionCallbacksArgument_GrapeshotBackendTopology( + argumentDelegate, + argumentNullDelegate, + argumentOutOfRangeDelegate); + } + } + + protected static SWIGExceptionHelper swigExceptionHelper = new SWIGExceptionHelper(); + + public class SWIGPendingException { + [global::System.ThreadStatic] + private static global::System.Exception pendingException = null; + private static int numExceptionsPending = 0; + + public static bool Pending { + get { + bool pending = false; + if (numExceptionsPending > 0) + if (pendingException != null) + pending = true; + return pending; + } + } + + public static void Set(global::System.Exception e) { + if (pendingException != null) + throw new global::System.ApplicationException("FATAL: An earlier pending exception from unmanaged code was missed and thus not thrown (" + pendingException.ToString() + ")", e); + pendingException = e; + lock(typeof(GrapeshotBackendTopologyPINVOKE)) { + numExceptionsPending++; + } + } + + public static global::System.Exception Retrieve() { + global::System.Exception e = null; + if (numExceptionsPending > 0) { + if (pendingException != null) { + e = pendingException; + pendingException = null; + lock(typeof(GrapeshotBackendTopologyPINVOKE)) { + numExceptionsPending--; + } + } + } + return e; + } + } + + + protected class SWIGStringHelper { + public delegate string SWIGStringDelegate(string message); + static SWIGStringDelegate stringDelegate = new SWIGStringDelegate(CreateString); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="SWIGRegisterStringCallback_GrapeshotBackendTopology")] + public static extern void SWIGRegisterStringCallback_GrapeshotBackendTopology(SWIGStringDelegate stringDelegate); + + + [GrapeshotBackendTopologyPINVOKE.MonoPInvokeCallback(typeof(SWIGStringDelegate))] + + + static string CreateString(string cString) { + return cString; + } + + static SWIGStringHelper() { + SWIGRegisterStringCallback_GrapeshotBackendTopology(stringDelegate); + } + } + + static protected SWIGStringHelper swigStringHelper = new SWIGStringHelper(); + + + static GrapeshotBackendTopologyPINVOKE() { + } + + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_delete_Topology")] + public static extern void delete_Topology(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_createDefaultGCSTopology")] + public static extern global::System.IntPtr createDefaultGCSTopology(System.IntPtr jarg1); +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotBackendTopologyPINVOKE.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotBackendTopologyPINVOKE.cs.meta new file mode 100644 index 0000000..50e59a5 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotBackendTopologyPINVOKE.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 172783769f1230d740bf35a2d793afda diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotDriver.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotDriver.cs new file mode 100644 index 0000000..99cfd0c --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotDriver.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public class GrapeshotDriver { +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotDriver.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotDriver.cs.meta new file mode 100644 index 0000000..1e9bc3c --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotDriver.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 971e7c7efd816ae79ec68b7fdf2db18c diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotDriverPINVOKE.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotDriverPINVOKE.cs new file mode 100644 index 0000000..d7185b6 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotDriverPINVOKE.cs @@ -0,0 +1,322 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +class GrapeshotDriverPINVOKE { + + /// For Mono AOT platforms compatibility + /// This attribute can be defined in any assembly for Mono AOT to use it. + public class MonoPInvokeCallbackAttribute : global::System.Attribute { + public MonoPInvokeCallbackAttribute(global::System.Type t) { + } + } + + + protected class SWIGExceptionHelper { + public delegate void ExceptionDelegate(string message); + public delegate void ExceptionArgumentDelegate(string message, string paramName); + + static ExceptionDelegate applicationDelegate = new ExceptionDelegate(SetPendingApplicationException); + static ExceptionDelegate arithmeticDelegate = new ExceptionDelegate(SetPendingArithmeticException); + static ExceptionDelegate divideByZeroDelegate = new ExceptionDelegate(SetPendingDivideByZeroException); + static ExceptionDelegate indexOutOfRangeDelegate = new ExceptionDelegate(SetPendingIndexOutOfRangeException); + static ExceptionDelegate invalidCastDelegate = new ExceptionDelegate(SetPendingInvalidCastException); + static ExceptionDelegate invalidOperationDelegate = new ExceptionDelegate(SetPendingInvalidOperationException); + static ExceptionDelegate ioDelegate = new ExceptionDelegate(SetPendingIOException); + static ExceptionDelegate nullReferenceDelegate = new ExceptionDelegate(SetPendingNullReferenceException); + static ExceptionDelegate outOfMemoryDelegate = new ExceptionDelegate(SetPendingOutOfMemoryException); + static ExceptionDelegate overflowDelegate = new ExceptionDelegate(SetPendingOverflowException); + static ExceptionDelegate systemDelegate = new ExceptionDelegate(SetPendingSystemException); + + static ExceptionArgumentDelegate argumentDelegate = new ExceptionArgumentDelegate(SetPendingArgumentException); + static ExceptionArgumentDelegate argumentNullDelegate = new ExceptionArgumentDelegate(SetPendingArgumentNullException); + static ExceptionArgumentDelegate argumentOutOfRangeDelegate = new ExceptionArgumentDelegate(SetPendingArgumentOutOfRangeException); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="SWIGRegisterExceptionCallbacks_GrapeshotDriver")] + public static extern void SWIGRegisterExceptionCallbacks_GrapeshotDriver( + ExceptionDelegate applicationDelegate, + ExceptionDelegate arithmeticDelegate, + ExceptionDelegate divideByZeroDelegate, + ExceptionDelegate indexOutOfRangeDelegate, + ExceptionDelegate invalidCastDelegate, + ExceptionDelegate invalidOperationDelegate, + ExceptionDelegate ioDelegate, + ExceptionDelegate nullReferenceDelegate, + ExceptionDelegate outOfMemoryDelegate, + ExceptionDelegate overflowDelegate, + ExceptionDelegate systemExceptionDelegate); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="SWIGRegisterExceptionArgumentCallbacks_GrapeshotDriver")] + public static extern void SWIGRegisterExceptionCallbacksArgument_GrapeshotDriver( + ExceptionArgumentDelegate argumentDelegate, + ExceptionArgumentDelegate argumentNullDelegate, + ExceptionArgumentDelegate argumentOutOfRangeDelegate); + + + [GrapeshotDriverPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingApplicationException(string message) { + SWIGPendingException.Set(new global::System.ApplicationException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotDriverPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingArithmeticException(string message) { + SWIGPendingException.Set(new global::System.ArithmeticException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotDriverPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingDivideByZeroException(string message) { + SWIGPendingException.Set(new global::System.DivideByZeroException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotDriverPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingIndexOutOfRangeException(string message) { + SWIGPendingException.Set(new global::System.IndexOutOfRangeException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotDriverPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingInvalidCastException(string message) { + SWIGPendingException.Set(new global::System.InvalidCastException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotDriverPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingInvalidOperationException(string message) { + SWIGPendingException.Set(new global::System.InvalidOperationException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotDriverPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingIOException(string message) { + SWIGPendingException.Set(new global::System.IO.IOException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotDriverPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingNullReferenceException(string message) { + SWIGPendingException.Set(new global::System.NullReferenceException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotDriverPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingOutOfMemoryException(string message) { + SWIGPendingException.Set(new global::System.OutOfMemoryException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotDriverPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingOverflowException(string message) { + SWIGPendingException.Set(new global::System.OverflowException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotDriverPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingSystemException(string message) { + SWIGPendingException.Set(new global::System.SystemException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotDriverPINVOKE.MonoPInvokeCallback(typeof(ExceptionArgumentDelegate))] + + + static void SetPendingArgumentException(string message, string paramName) { + SWIGPendingException.Set(new global::System.ArgumentException(message, paramName, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotDriverPINVOKE.MonoPInvokeCallback(typeof(ExceptionArgumentDelegate))] + + + static void SetPendingArgumentNullException(string message, string paramName) { + global::System.Exception e = SWIGPendingException.Retrieve(); + if (e != null) message = message + " Inner Exception: " + e.Message; + SWIGPendingException.Set(new global::System.ArgumentNullException(paramName, message)); + } + + + + [GrapeshotDriverPINVOKE.MonoPInvokeCallback(typeof(ExceptionArgumentDelegate))] + + + static void SetPendingArgumentOutOfRangeException(string message, string paramName) { + global::System.Exception e = SWIGPendingException.Retrieve(); + if (e != null) message = message + " Inner Exception: " + e.Message; + SWIGPendingException.Set(new global::System.ArgumentOutOfRangeException(paramName, message)); + } + + static SWIGExceptionHelper() { + SWIGRegisterExceptionCallbacks_GrapeshotDriver( + applicationDelegate, + arithmeticDelegate, + divideByZeroDelegate, + indexOutOfRangeDelegate, + invalidCastDelegate, + invalidOperationDelegate, + ioDelegate, + nullReferenceDelegate, + outOfMemoryDelegate, + overflowDelegate, + systemDelegate); + + SWIGRegisterExceptionCallbacksArgument_GrapeshotDriver( + argumentDelegate, + argumentNullDelegate, + argumentOutOfRangeDelegate); + } + } + + protected static SWIGExceptionHelper swigExceptionHelper = new SWIGExceptionHelper(); + + public class SWIGPendingException { + [global::System.ThreadStatic] + private static global::System.Exception pendingException = null; + private static int numExceptionsPending = 0; + + public static bool Pending { + get { + bool pending = false; + if (numExceptionsPending > 0) + if (pendingException != null) + pending = true; + return pending; + } + } + + public static void Set(global::System.Exception e) { + if (pendingException != null) + throw new global::System.ApplicationException("FATAL: An earlier pending exception from unmanaged code was missed and thus not thrown (" + pendingException.ToString() + ")", e); + pendingException = e; + lock(typeof(GrapeshotDriverPINVOKE)) { + numExceptionsPending++; + } + } + + public static global::System.Exception Retrieve() { + global::System.Exception e = null; + if (numExceptionsPending > 0) { + if (pendingException != null) { + e = pendingException; + pendingException = null; + lock(typeof(GrapeshotDriverPINVOKE)) { + numExceptionsPending--; + } + } + } + return e; + } + } + + + protected class SWIGStringHelper { + public delegate string SWIGStringDelegate(string message); + static SWIGStringDelegate stringDelegate = new SWIGStringDelegate(CreateString); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="SWIGRegisterStringCallback_GrapeshotDriver")] + public static extern void SWIGRegisterStringCallback_GrapeshotDriver(SWIGStringDelegate stringDelegate); + + + [GrapeshotDriverPINVOKE.MonoPInvokeCallback(typeof(SWIGStringDelegate))] + + + static string CreateString(string cString) { + return cString; + } + + static SWIGStringHelper() { + SWIGRegisterStringCallback_GrapeshotDriver(stringDelegate); + } + } + + static protected SWIGStringHelper swigStringHelper = new SWIGStringHelper(); + + + static GrapeshotDriverPINVOKE() { + } + + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_RequestCallback_FunctionApplicationBridgeBase_invokeApplicationLogic")] + public static extern void RequestCallback_FunctionApplicationBridgeBase_invokeApplicationLogic(global::System.Runtime.InteropServices.HandleRef jarg1, FBIntermediateBuffer jarg2); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_RequestCallback_FunctionApplicationBridgeBase_releaseApplicationCallback")] + public static extern void RequestCallback_FunctionApplicationBridgeBase_releaseApplicationCallback(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_delete_RequestCallback_FunctionApplicationBridgeBase")] + public static extern void delete_RequestCallback_FunctionApplicationBridgeBase(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_new_RequestCallback_FunctionApplicationBridgeBase")] + public static extern global::System.IntPtr new_RequestCallback_FunctionApplicationBridgeBase(); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_RequestCallback_FunctionApplicationBridgeBase_director_connect")] + public static extern void RequestCallback_FunctionApplicationBridgeBase_director_connect(global::System.Runtime.InteropServices.HandleRef jarg1, RequestCallback_FunctionApplicationBridgeBase.SwigDelegateRequestCallback_FunctionApplicationBridgeBase_0_Dispatcher delegate0_dispatcher, global::System.IntPtr delegate0gcHandlePtr, RequestCallback_FunctionApplicationBridgeBase.SwigDelegateRequestCallback_FunctionApplicationBridgeBase_1_Dispatcher delegate1_dispatcher, global::System.IntPtr delegate1gcHandlePtr); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_Driver_process")] + public static extern void Driver_process(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_Driver_sendChunk")] + public static extern void Driver_sendChunk(global::System.Runtime.InteropServices.HandleRef jarg1, System.IntPtr jarg2, FBIntermediateBuffer jarg3, global::System.Runtime.InteropServices.HandleRef jarg4); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_delete_Driver")] + public static extern void delete_Driver(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_InterprocDriver_process")] + public static extern void InterprocDriver_process(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_InterprocDriver_sendChunk")] + public static extern void InterprocDriver_sendChunk(global::System.Runtime.InteropServices.HandleRef jarg1, System.IntPtr jarg2, FBIntermediateBuffer jarg3, global::System.Runtime.InteropServices.HandleRef jarg4); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_new_InterprocDriver")] + public static extern global::System.IntPtr new_InterprocDriver(System.IntPtr jarg1, global::System.Runtime.InteropServices.HandleRef jarg2); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_delete_InterprocDriver")] + public static extern void delete_InterprocDriver(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_InterprocDriver_SWIGSmartPtrUpcast")] + public static extern global::System.IntPtr InterprocDriver_SWIGSmartPtrUpcast(global::System.IntPtr jarg1); +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotDriverPINVOKE.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotDriverPINVOKE.cs.meta new file mode 100644 index 0000000..55f9aca --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotDriverPINVOKE.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: d81a41a967bf6787fcfcc27d3f78b9e3 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotFuncRateTicket.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotFuncRateTicket.cs new file mode 100644 index 0000000..6cdea99 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotFuncRateTicket.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public class GrapeshotFuncRateTicket { +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotFuncRateTicket.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotFuncRateTicket.cs.meta new file mode 100644 index 0000000..b2ed2e2 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotFuncRateTicket.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: dc3a21c16371f51c61d131ed97f53a05 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotFuncRateTicketPINVOKE.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotFuncRateTicketPINVOKE.cs new file mode 100644 index 0000000..b7b1940 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotFuncRateTicketPINVOKE.cs @@ -0,0 +1,307 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +class GrapeshotFuncRateTicketPINVOKE { + + /// For Mono AOT platforms compatibility + /// This attribute can be defined in any assembly for Mono AOT to use it. + public class MonoPInvokeCallbackAttribute : global::System.Attribute { + public MonoPInvokeCallbackAttribute(global::System.Type t) { + } + } + + + protected class SWIGExceptionHelper { + public delegate void ExceptionDelegate(string message); + public delegate void ExceptionArgumentDelegate(string message, string paramName); + + static ExceptionDelegate applicationDelegate = new ExceptionDelegate(SetPendingApplicationException); + static ExceptionDelegate arithmeticDelegate = new ExceptionDelegate(SetPendingArithmeticException); + static ExceptionDelegate divideByZeroDelegate = new ExceptionDelegate(SetPendingDivideByZeroException); + static ExceptionDelegate indexOutOfRangeDelegate = new ExceptionDelegate(SetPendingIndexOutOfRangeException); + static ExceptionDelegate invalidCastDelegate = new ExceptionDelegate(SetPendingInvalidCastException); + static ExceptionDelegate invalidOperationDelegate = new ExceptionDelegate(SetPendingInvalidOperationException); + static ExceptionDelegate ioDelegate = new ExceptionDelegate(SetPendingIOException); + static ExceptionDelegate nullReferenceDelegate = new ExceptionDelegate(SetPendingNullReferenceException); + static ExceptionDelegate outOfMemoryDelegate = new ExceptionDelegate(SetPendingOutOfMemoryException); + static ExceptionDelegate overflowDelegate = new ExceptionDelegate(SetPendingOverflowException); + static ExceptionDelegate systemDelegate = new ExceptionDelegate(SetPendingSystemException); + + static ExceptionArgumentDelegate argumentDelegate = new ExceptionArgumentDelegate(SetPendingArgumentException); + static ExceptionArgumentDelegate argumentNullDelegate = new ExceptionArgumentDelegate(SetPendingArgumentNullException); + static ExceptionArgumentDelegate argumentOutOfRangeDelegate = new ExceptionArgumentDelegate(SetPendingArgumentOutOfRangeException); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="SWIGRegisterExceptionCallbacks_GrapeshotFuncRateTicket")] + public static extern void SWIGRegisterExceptionCallbacks_GrapeshotFuncRateTicket( + ExceptionDelegate applicationDelegate, + ExceptionDelegate arithmeticDelegate, + ExceptionDelegate divideByZeroDelegate, + ExceptionDelegate indexOutOfRangeDelegate, + ExceptionDelegate invalidCastDelegate, + ExceptionDelegate invalidOperationDelegate, + ExceptionDelegate ioDelegate, + ExceptionDelegate nullReferenceDelegate, + ExceptionDelegate outOfMemoryDelegate, + ExceptionDelegate overflowDelegate, + ExceptionDelegate systemExceptionDelegate); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="SWIGRegisterExceptionArgumentCallbacks_GrapeshotFuncRateTicket")] + public static extern void SWIGRegisterExceptionCallbacksArgument_GrapeshotFuncRateTicket( + ExceptionArgumentDelegate argumentDelegate, + ExceptionArgumentDelegate argumentNullDelegate, + ExceptionArgumentDelegate argumentOutOfRangeDelegate); + + + [GrapeshotFuncRateTicketPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingApplicationException(string message) { + SWIGPendingException.Set(new global::System.ApplicationException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotFuncRateTicketPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingArithmeticException(string message) { + SWIGPendingException.Set(new global::System.ArithmeticException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotFuncRateTicketPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingDivideByZeroException(string message) { + SWIGPendingException.Set(new global::System.DivideByZeroException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotFuncRateTicketPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingIndexOutOfRangeException(string message) { + SWIGPendingException.Set(new global::System.IndexOutOfRangeException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotFuncRateTicketPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingInvalidCastException(string message) { + SWIGPendingException.Set(new global::System.InvalidCastException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotFuncRateTicketPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingInvalidOperationException(string message) { + SWIGPendingException.Set(new global::System.InvalidOperationException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotFuncRateTicketPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingIOException(string message) { + SWIGPendingException.Set(new global::System.IO.IOException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotFuncRateTicketPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingNullReferenceException(string message) { + SWIGPendingException.Set(new global::System.NullReferenceException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotFuncRateTicketPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingOutOfMemoryException(string message) { + SWIGPendingException.Set(new global::System.OutOfMemoryException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotFuncRateTicketPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingOverflowException(string message) { + SWIGPendingException.Set(new global::System.OverflowException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotFuncRateTicketPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingSystemException(string message) { + SWIGPendingException.Set(new global::System.SystemException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotFuncRateTicketPINVOKE.MonoPInvokeCallback(typeof(ExceptionArgumentDelegate))] + + + static void SetPendingArgumentException(string message, string paramName) { + SWIGPendingException.Set(new global::System.ArgumentException(message, paramName, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotFuncRateTicketPINVOKE.MonoPInvokeCallback(typeof(ExceptionArgumentDelegate))] + + + static void SetPendingArgumentNullException(string message, string paramName) { + global::System.Exception e = SWIGPendingException.Retrieve(); + if (e != null) message = message + " Inner Exception: " + e.Message; + SWIGPendingException.Set(new global::System.ArgumentNullException(paramName, message)); + } + + + + [GrapeshotFuncRateTicketPINVOKE.MonoPInvokeCallback(typeof(ExceptionArgumentDelegate))] + + + static void SetPendingArgumentOutOfRangeException(string message, string paramName) { + global::System.Exception e = SWIGPendingException.Retrieve(); + if (e != null) message = message + " Inner Exception: " + e.Message; + SWIGPendingException.Set(new global::System.ArgumentOutOfRangeException(paramName, message)); + } + + static SWIGExceptionHelper() { + SWIGRegisterExceptionCallbacks_GrapeshotFuncRateTicket( + applicationDelegate, + arithmeticDelegate, + divideByZeroDelegate, + indexOutOfRangeDelegate, + invalidCastDelegate, + invalidOperationDelegate, + ioDelegate, + nullReferenceDelegate, + outOfMemoryDelegate, + overflowDelegate, + systemDelegate); + + SWIGRegisterExceptionCallbacksArgument_GrapeshotFuncRateTicket( + argumentDelegate, + argumentNullDelegate, + argumentOutOfRangeDelegate); + } + } + + protected static SWIGExceptionHelper swigExceptionHelper = new SWIGExceptionHelper(); + + public class SWIGPendingException { + [global::System.ThreadStatic] + private static global::System.Exception pendingException = null; + private static int numExceptionsPending = 0; + + public static bool Pending { + get { + bool pending = false; + if (numExceptionsPending > 0) + if (pendingException != null) + pending = true; + return pending; + } + } + + public static void Set(global::System.Exception e) { + if (pendingException != null) + throw new global::System.ApplicationException("FATAL: An earlier pending exception from unmanaged code was missed and thus not thrown (" + pendingException.ToString() + ")", e); + pendingException = e; + lock(typeof(GrapeshotFuncRateTicketPINVOKE)) { + numExceptionsPending++; + } + } + + public static global::System.Exception Retrieve() { + global::System.Exception e = null; + if (numExceptionsPending > 0) { + if (pendingException != null) { + e = pendingException; + pendingException = null; + lock(typeof(GrapeshotFuncRateTicketPINVOKE)) { + numExceptionsPending--; + } + } + } + return e; + } + } + + + protected class SWIGStringHelper { + public delegate string SWIGStringDelegate(string message); + static SWIGStringDelegate stringDelegate = new SWIGStringDelegate(CreateString); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="SWIGRegisterStringCallback_GrapeshotFuncRateTicket")] + public static extern void SWIGRegisterStringCallback_GrapeshotFuncRateTicket(SWIGStringDelegate stringDelegate); + + + [GrapeshotFuncRateTicketPINVOKE.MonoPInvokeCallback(typeof(SWIGStringDelegate))] + + + static string CreateString(string cString) { + return cString; + } + + static SWIGStringHelper() { + SWIGRegisterStringCallback_GrapeshotFuncRateTicket(stringDelegate); + } + } + + static protected SWIGStringHelper swigStringHelper = new SWIGStringHelper(); + + + static GrapeshotFuncRateTicketPINVOKE() { + } + + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_FuncRateTicketCallback_FunctionApplicationBridgeBase_invokeApplicationLogic")] + public static extern void FuncRateTicketCallback_FunctionApplicationBridgeBase_invokeApplicationLogic(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_FuncRateTicketCallback_FunctionApplicationBridgeBase_releaseApplicationCallback")] + public static extern void FuncRateTicketCallback_FunctionApplicationBridgeBase_releaseApplicationCallback(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_delete_FuncRateTicketCallback_FunctionApplicationBridgeBase")] + public static extern void delete_FuncRateTicketCallback_FunctionApplicationBridgeBase(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_new_FuncRateTicketCallback_FunctionApplicationBridgeBase")] + public static extern global::System.IntPtr new_FuncRateTicketCallback_FunctionApplicationBridgeBase(); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_FuncRateTicketCallback_FunctionApplicationBridgeBase_director_connect")] + public static extern void FuncRateTicketCallback_FunctionApplicationBridgeBase_director_connect(global::System.Runtime.InteropServices.HandleRef jarg1, FuncRateTicketCallback_FunctionApplicationBridgeBase.SwigDelegateFuncRateTicketCallback_FunctionApplicationBridgeBase_0_Dispatcher delegate0_dispatcher, global::System.IntPtr delegate0gcHandlePtr, FuncRateTicketCallback_FunctionApplicationBridgeBase.SwigDelegateFuncRateTicketCallback_FunctionApplicationBridgeBase_1_Dispatcher delegate1_dispatcher, global::System.IntPtr delegate1gcHandlePtr); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_FuncRateTicket_createFuncRateTicket")] + public static extern global::System.IntPtr FuncRateTicket_createFuncRateTicket(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_delete_FuncRateTicket")] + public static extern void delete_FuncRateTicket(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_FuncRateTicket_SWIGSmartPtrUpcast")] + public static extern global::System.IntPtr FuncRateTicket_SWIGSmartPtrUpcast(global::System.IntPtr jarg1); +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotFuncRateTicketPINVOKE.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotFuncRateTicketPINVOKE.cs.meta new file mode 100644 index 0000000..4ea5324 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotFuncRateTicketPINVOKE.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: c0b8880b1ec8967b20c25832c74082f8 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotMultiRate.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotMultiRate.cs new file mode 100644 index 0000000..2c6aa2a --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotMultiRate.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public class GrapeshotMultiRate { +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotMultiRate.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotMultiRate.cs.meta new file mode 100644 index 0000000..e6bd3c2 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotMultiRate.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 9a06dd595384f55a2c7d357bbd480b3b diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotMultiRatePINVOKE.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotMultiRatePINVOKE.cs new file mode 100644 index 0000000..a6e5ea9 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotMultiRatePINVOKE.cs @@ -0,0 +1,367 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +class GrapeshotMultiRatePINVOKE { + + /// For Mono AOT platforms compatibility + /// This attribute can be defined in any assembly for Mono AOT to use it. + public class MonoPInvokeCallbackAttribute : global::System.Attribute { + public MonoPInvokeCallbackAttribute(global::System.Type t) { + } + } + + + protected class SWIGExceptionHelper { + public delegate void ExceptionDelegate(string message); + public delegate void ExceptionArgumentDelegate(string message, string paramName); + + static ExceptionDelegate applicationDelegate = new ExceptionDelegate(SetPendingApplicationException); + static ExceptionDelegate arithmeticDelegate = new ExceptionDelegate(SetPendingArithmeticException); + static ExceptionDelegate divideByZeroDelegate = new ExceptionDelegate(SetPendingDivideByZeroException); + static ExceptionDelegate indexOutOfRangeDelegate = new ExceptionDelegate(SetPendingIndexOutOfRangeException); + static ExceptionDelegate invalidCastDelegate = new ExceptionDelegate(SetPendingInvalidCastException); + static ExceptionDelegate invalidOperationDelegate = new ExceptionDelegate(SetPendingInvalidOperationException); + static ExceptionDelegate ioDelegate = new ExceptionDelegate(SetPendingIOException); + static ExceptionDelegate nullReferenceDelegate = new ExceptionDelegate(SetPendingNullReferenceException); + static ExceptionDelegate outOfMemoryDelegate = new ExceptionDelegate(SetPendingOutOfMemoryException); + static ExceptionDelegate overflowDelegate = new ExceptionDelegate(SetPendingOverflowException); + static ExceptionDelegate systemDelegate = new ExceptionDelegate(SetPendingSystemException); + + static ExceptionArgumentDelegate argumentDelegate = new ExceptionArgumentDelegate(SetPendingArgumentException); + static ExceptionArgumentDelegate argumentNullDelegate = new ExceptionArgumentDelegate(SetPendingArgumentNullException); + static ExceptionArgumentDelegate argumentOutOfRangeDelegate = new ExceptionArgumentDelegate(SetPendingArgumentOutOfRangeException); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="SWIGRegisterExceptionCallbacks_GrapeshotMultiRate")] + public static extern void SWIGRegisterExceptionCallbacks_GrapeshotMultiRate( + ExceptionDelegate applicationDelegate, + ExceptionDelegate arithmeticDelegate, + ExceptionDelegate divideByZeroDelegate, + ExceptionDelegate indexOutOfRangeDelegate, + ExceptionDelegate invalidCastDelegate, + ExceptionDelegate invalidOperationDelegate, + ExceptionDelegate ioDelegate, + ExceptionDelegate nullReferenceDelegate, + ExceptionDelegate outOfMemoryDelegate, + ExceptionDelegate overflowDelegate, + ExceptionDelegate systemExceptionDelegate); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="SWIGRegisterExceptionArgumentCallbacks_GrapeshotMultiRate")] + public static extern void SWIGRegisterExceptionCallbacksArgument_GrapeshotMultiRate( + ExceptionArgumentDelegate argumentDelegate, + ExceptionArgumentDelegate argumentNullDelegate, + ExceptionArgumentDelegate argumentOutOfRangeDelegate); + + + [GrapeshotMultiRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingApplicationException(string message) { + SWIGPendingException.Set(new global::System.ApplicationException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotMultiRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingArithmeticException(string message) { + SWIGPendingException.Set(new global::System.ArithmeticException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotMultiRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingDivideByZeroException(string message) { + SWIGPendingException.Set(new global::System.DivideByZeroException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotMultiRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingIndexOutOfRangeException(string message) { + SWIGPendingException.Set(new global::System.IndexOutOfRangeException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotMultiRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingInvalidCastException(string message) { + SWIGPendingException.Set(new global::System.InvalidCastException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotMultiRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingInvalidOperationException(string message) { + SWIGPendingException.Set(new global::System.InvalidOperationException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotMultiRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingIOException(string message) { + SWIGPendingException.Set(new global::System.IO.IOException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotMultiRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingNullReferenceException(string message) { + SWIGPendingException.Set(new global::System.NullReferenceException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotMultiRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingOutOfMemoryException(string message) { + SWIGPendingException.Set(new global::System.OutOfMemoryException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotMultiRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingOverflowException(string message) { + SWIGPendingException.Set(new global::System.OverflowException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotMultiRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingSystemException(string message) { + SWIGPendingException.Set(new global::System.SystemException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotMultiRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionArgumentDelegate))] + + + static void SetPendingArgumentException(string message, string paramName) { + SWIGPendingException.Set(new global::System.ArgumentException(message, paramName, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotMultiRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionArgumentDelegate))] + + + static void SetPendingArgumentNullException(string message, string paramName) { + global::System.Exception e = SWIGPendingException.Retrieve(); + if (e != null) message = message + " Inner Exception: " + e.Message; + SWIGPendingException.Set(new global::System.ArgumentNullException(paramName, message)); + } + + + + [GrapeshotMultiRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionArgumentDelegate))] + + + static void SetPendingArgumentOutOfRangeException(string message, string paramName) { + global::System.Exception e = SWIGPendingException.Retrieve(); + if (e != null) message = message + " Inner Exception: " + e.Message; + SWIGPendingException.Set(new global::System.ArgumentOutOfRangeException(paramName, message)); + } + + static SWIGExceptionHelper() { + SWIGRegisterExceptionCallbacks_GrapeshotMultiRate( + applicationDelegate, + arithmeticDelegate, + divideByZeroDelegate, + indexOutOfRangeDelegate, + invalidCastDelegate, + invalidOperationDelegate, + ioDelegate, + nullReferenceDelegate, + outOfMemoryDelegate, + overflowDelegate, + systemDelegate); + + SWIGRegisterExceptionCallbacksArgument_GrapeshotMultiRate( + argumentDelegate, + argumentNullDelegate, + argumentOutOfRangeDelegate); + } + } + + protected static SWIGExceptionHelper swigExceptionHelper = new SWIGExceptionHelper(); + + public class SWIGPendingException { + [global::System.ThreadStatic] + private static global::System.Exception pendingException = null; + private static int numExceptionsPending = 0; + + public static bool Pending { + get { + bool pending = false; + if (numExceptionsPending > 0) + if (pendingException != null) + pending = true; + return pending; + } + } + + public static void Set(global::System.Exception e) { + if (pendingException != null) + throw new global::System.ApplicationException("FATAL: An earlier pending exception from unmanaged code was missed and thus not thrown (" + pendingException.ToString() + ")", e); + pendingException = e; + lock(typeof(GrapeshotMultiRatePINVOKE)) { + numExceptionsPending++; + } + } + + public static global::System.Exception Retrieve() { + global::System.Exception e = null; + if (numExceptionsPending > 0) { + if (pendingException != null) { + e = pendingException; + pendingException = null; + lock(typeof(GrapeshotMultiRatePINVOKE)) { + numExceptionsPending--; + } + } + } + return e; + } + } + + + protected class SWIGStringHelper { + public delegate string SWIGStringDelegate(string message); + static SWIGStringDelegate stringDelegate = new SWIGStringDelegate(CreateString); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="SWIGRegisterStringCallback_GrapeshotMultiRate")] + public static extern void SWIGRegisterStringCallback_GrapeshotMultiRate(SWIGStringDelegate stringDelegate); + + + [GrapeshotMultiRatePINVOKE.MonoPInvokeCallback(typeof(SWIGStringDelegate))] + + + static string CreateString(string cString) { + return cString; + } + + static SWIGStringHelper() { + SWIGRegisterStringCallback_GrapeshotMultiRate(stringDelegate); + } + } + + static protected SWIGStringHelper swigStringHelper = new SWIGStringHelper(); + + + static GrapeshotMultiRatePINVOKE() { + } + + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_RateVector_Clear")] + public static extern void RateVector_Clear(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_RateVector_Add")] + public static extern void RateVector_Add(global::System.Runtime.InteropServices.HandleRef jarg1, global::System.Runtime.InteropServices.HandleRef jarg2); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_RateVector_size")] + public static extern uint RateVector_size(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_RateVector_capacity")] + public static extern uint RateVector_capacity(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_RateVector_reserve")] + public static extern void RateVector_reserve(global::System.Runtime.InteropServices.HandleRef jarg1, uint jarg2); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_new_RateVector__SWIG_0")] + public static extern global::System.IntPtr new_RateVector__SWIG_0(); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_new_RateVector__SWIG_1")] + public static extern global::System.IntPtr new_RateVector__SWIG_1(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_new_RateVector__SWIG_2")] + public static extern global::System.IntPtr new_RateVector__SWIG_2(int jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_RateVector_getitemcopy")] + public static extern global::System.IntPtr RateVector_getitemcopy(global::System.Runtime.InteropServices.HandleRef jarg1, int jarg2); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_RateVector_getitem")] + public static extern global::System.IntPtr RateVector_getitem(global::System.Runtime.InteropServices.HandleRef jarg1, int jarg2); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_RateVector_setitem")] + public static extern void RateVector_setitem(global::System.Runtime.InteropServices.HandleRef jarg1, int jarg2, global::System.Runtime.InteropServices.HandleRef jarg3); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_RateVector_AddRange")] + public static extern void RateVector_AddRange(global::System.Runtime.InteropServices.HandleRef jarg1, global::System.Runtime.InteropServices.HandleRef jarg2); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_RateVector_GetRange")] + public static extern global::System.IntPtr RateVector_GetRange(global::System.Runtime.InteropServices.HandleRef jarg1, int jarg2, int jarg3); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_RateVector_Insert")] + public static extern void RateVector_Insert(global::System.Runtime.InteropServices.HandleRef jarg1, int jarg2, global::System.Runtime.InteropServices.HandleRef jarg3); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_RateVector_InsertRange")] + public static extern void RateVector_InsertRange(global::System.Runtime.InteropServices.HandleRef jarg1, int jarg2, global::System.Runtime.InteropServices.HandleRef jarg3); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_RateVector_RemoveAt")] + public static extern void RateVector_RemoveAt(global::System.Runtime.InteropServices.HandleRef jarg1, int jarg2); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_RateVector_RemoveRange")] + public static extern void RateVector_RemoveRange(global::System.Runtime.InteropServices.HandleRef jarg1, int jarg2, int jarg3); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_RateVector_Repeat")] + public static extern global::System.IntPtr RateVector_Repeat(global::System.Runtime.InteropServices.HandleRef jarg1, int jarg2); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_RateVector_Reverse__SWIG_0")] + public static extern void RateVector_Reverse__SWIG_0(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_RateVector_Reverse__SWIG_1")] + public static extern void RateVector_Reverse__SWIG_1(global::System.Runtime.InteropServices.HandleRef jarg1, int jarg2, int jarg3); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_RateVector_SetRange")] + public static extern void RateVector_SetRange(global::System.Runtime.InteropServices.HandleRef jarg1, int jarg2, global::System.Runtime.InteropServices.HandleRef jarg3); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_delete_RateVector")] + public static extern void delete_RateVector(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_MultiRate_claimTicket")] + public static extern global::System.IntPtr MultiRate_claimTicket(global::System.Runtime.InteropServices.HandleRef jarg1, FBIntermediateBuffer jarg2); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_MultiRate_tryClaimTicket")] + public static extern global::System.IntPtr MultiRate_tryClaimTicket(global::System.Runtime.InteropServices.HandleRef jarg1, FBIntermediateBuffer jarg2); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_MultiRate_areFreeTickets")] + public static extern bool MultiRate_areFreeTickets(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_MultiRate_createMultiRate")] + public static extern global::System.IntPtr MultiRate_createMultiRate(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_delete_MultiRate")] + public static extern void delete_MultiRate(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_MultiRate_SWIGSmartPtrUpcast")] + public static extern global::System.IntPtr MultiRate_SWIGSmartPtrUpcast(global::System.IntPtr jarg1); +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotMultiRatePINVOKE.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotMultiRatePINVOKE.cs.meta new file mode 100644 index 0000000..312b366 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotMultiRatePINVOKE.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: fa65a44b5198cb5d0f604afb205d8b36 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotRate.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotRate.cs new file mode 100644 index 0000000..76ad24c --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotRate.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public class GrapeshotRate { +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotRate.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotRate.cs.meta new file mode 100644 index 0000000..4d78735 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotRate.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: fa42f6e2b0a3201acd2eea25ab1390f8 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotRatePINVOKE.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotRatePINVOKE.cs new file mode 100644 index 0000000..f03aa16 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotRatePINVOKE.cs @@ -0,0 +1,349 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +class GrapeshotRatePINVOKE { + + /// For Mono AOT platforms compatibility + /// This attribute can be defined in any assembly for Mono AOT to use it. + public class MonoPInvokeCallbackAttribute : global::System.Attribute { + public MonoPInvokeCallbackAttribute(global::System.Type t) { + } + } + + + protected class SWIGExceptionHelper { + public delegate void ExceptionDelegate(string message); + public delegate void ExceptionArgumentDelegate(string message, string paramName); + + static ExceptionDelegate applicationDelegate = new ExceptionDelegate(SetPendingApplicationException); + static ExceptionDelegate arithmeticDelegate = new ExceptionDelegate(SetPendingArithmeticException); + static ExceptionDelegate divideByZeroDelegate = new ExceptionDelegate(SetPendingDivideByZeroException); + static ExceptionDelegate indexOutOfRangeDelegate = new ExceptionDelegate(SetPendingIndexOutOfRangeException); + static ExceptionDelegate invalidCastDelegate = new ExceptionDelegate(SetPendingInvalidCastException); + static ExceptionDelegate invalidOperationDelegate = new ExceptionDelegate(SetPendingInvalidOperationException); + static ExceptionDelegate ioDelegate = new ExceptionDelegate(SetPendingIOException); + static ExceptionDelegate nullReferenceDelegate = new ExceptionDelegate(SetPendingNullReferenceException); + static ExceptionDelegate outOfMemoryDelegate = new ExceptionDelegate(SetPendingOutOfMemoryException); + static ExceptionDelegate overflowDelegate = new ExceptionDelegate(SetPendingOverflowException); + static ExceptionDelegate systemDelegate = new ExceptionDelegate(SetPendingSystemException); + + static ExceptionArgumentDelegate argumentDelegate = new ExceptionArgumentDelegate(SetPendingArgumentException); + static ExceptionArgumentDelegate argumentNullDelegate = new ExceptionArgumentDelegate(SetPendingArgumentNullException); + static ExceptionArgumentDelegate argumentOutOfRangeDelegate = new ExceptionArgumentDelegate(SetPendingArgumentOutOfRangeException); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="SWIGRegisterExceptionCallbacks_GrapeshotRate")] + public static extern void SWIGRegisterExceptionCallbacks_GrapeshotRate( + ExceptionDelegate applicationDelegate, + ExceptionDelegate arithmeticDelegate, + ExceptionDelegate divideByZeroDelegate, + ExceptionDelegate indexOutOfRangeDelegate, + ExceptionDelegate invalidCastDelegate, + ExceptionDelegate invalidOperationDelegate, + ExceptionDelegate ioDelegate, + ExceptionDelegate nullReferenceDelegate, + ExceptionDelegate outOfMemoryDelegate, + ExceptionDelegate overflowDelegate, + ExceptionDelegate systemExceptionDelegate); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="SWIGRegisterExceptionArgumentCallbacks_GrapeshotRate")] + public static extern void SWIGRegisterExceptionCallbacksArgument_GrapeshotRate( + ExceptionArgumentDelegate argumentDelegate, + ExceptionArgumentDelegate argumentNullDelegate, + ExceptionArgumentDelegate argumentOutOfRangeDelegate); + + + [GrapeshotRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingApplicationException(string message) { + SWIGPendingException.Set(new global::System.ApplicationException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingArithmeticException(string message) { + SWIGPendingException.Set(new global::System.ArithmeticException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingDivideByZeroException(string message) { + SWIGPendingException.Set(new global::System.DivideByZeroException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingIndexOutOfRangeException(string message) { + SWIGPendingException.Set(new global::System.IndexOutOfRangeException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingInvalidCastException(string message) { + SWIGPendingException.Set(new global::System.InvalidCastException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingInvalidOperationException(string message) { + SWIGPendingException.Set(new global::System.InvalidOperationException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingIOException(string message) { + SWIGPendingException.Set(new global::System.IO.IOException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingNullReferenceException(string message) { + SWIGPendingException.Set(new global::System.NullReferenceException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingOutOfMemoryException(string message) { + SWIGPendingException.Set(new global::System.OutOfMemoryException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingOverflowException(string message) { + SWIGPendingException.Set(new global::System.OverflowException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingSystemException(string message) { + SWIGPendingException.Set(new global::System.SystemException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionArgumentDelegate))] + + + static void SetPendingArgumentException(string message, string paramName) { + SWIGPendingException.Set(new global::System.ArgumentException(message, paramName, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionArgumentDelegate))] + + + static void SetPendingArgumentNullException(string message, string paramName) { + global::System.Exception e = SWIGPendingException.Retrieve(); + if (e != null) message = message + " Inner Exception: " + e.Message; + SWIGPendingException.Set(new global::System.ArgumentNullException(paramName, message)); + } + + + + [GrapeshotRatePINVOKE.MonoPInvokeCallback(typeof(ExceptionArgumentDelegate))] + + + static void SetPendingArgumentOutOfRangeException(string message, string paramName) { + global::System.Exception e = SWIGPendingException.Retrieve(); + if (e != null) message = message + " Inner Exception: " + e.Message; + SWIGPendingException.Set(new global::System.ArgumentOutOfRangeException(paramName, message)); + } + + static SWIGExceptionHelper() { + SWIGRegisterExceptionCallbacks_GrapeshotRate( + applicationDelegate, + arithmeticDelegate, + divideByZeroDelegate, + indexOutOfRangeDelegate, + invalidCastDelegate, + invalidOperationDelegate, + ioDelegate, + nullReferenceDelegate, + outOfMemoryDelegate, + overflowDelegate, + systemDelegate); + + SWIGRegisterExceptionCallbacksArgument_GrapeshotRate( + argumentDelegate, + argumentNullDelegate, + argumentOutOfRangeDelegate); + } + } + + protected static SWIGExceptionHelper swigExceptionHelper = new SWIGExceptionHelper(); + + public class SWIGPendingException { + [global::System.ThreadStatic] + private static global::System.Exception pendingException = null; + private static int numExceptionsPending = 0; + + public static bool Pending { + get { + bool pending = false; + if (numExceptionsPending > 0) + if (pendingException != null) + pending = true; + return pending; + } + } + + public static void Set(global::System.Exception e) { + if (pendingException != null) + throw new global::System.ApplicationException("FATAL: An earlier pending exception from unmanaged code was missed and thus not thrown (" + pendingException.ToString() + ")", e); + pendingException = e; + lock(typeof(GrapeshotRatePINVOKE)) { + numExceptionsPending++; + } + } + + public static global::System.Exception Retrieve() { + global::System.Exception e = null; + if (numExceptionsPending > 0) { + if (pendingException != null) { + e = pendingException; + pendingException = null; + lock(typeof(GrapeshotRatePINVOKE)) { + numExceptionsPending--; + } + } + } + return e; + } + } + + + protected class SWIGStringHelper { + public delegate string SWIGStringDelegate(string message); + static SWIGStringDelegate stringDelegate = new SWIGStringDelegate(CreateString); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="SWIGRegisterStringCallback_GrapeshotRate")] + public static extern void SWIGRegisterStringCallback_GrapeshotRate(SWIGStringDelegate stringDelegate); + + + [GrapeshotRatePINVOKE.MonoPInvokeCallback(typeof(SWIGStringDelegate))] + + + static string CreateString(string cString) { + return cString; + } + + static SWIGStringHelper() { + SWIGRegisterStringCallback_GrapeshotRate(stringDelegate); + } + } + + static protected SWIGStringHelper swigStringHelper = new SWIGStringHelper(); + + + static GrapeshotRatePINVOKE() { + } + + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_new_RateTicket")] + public static extern global::System.IntPtr new_RateTicket(); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_delete_RateTicket")] + public static extern void delete_RateTicket(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_Rate_process")] + public static extern void Rate_process(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_Rate_claimTicket")] + public static extern global::System.IntPtr Rate_claimTicket(global::System.Runtime.InteropServices.HandleRef jarg1, FBIntermediateBuffer jarg2); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_Rate_tryClaimTicket")] + public static extern global::System.IntPtr Rate_tryClaimTicket(global::System.Runtime.InteropServices.HandleRef jarg1, FBIntermediateBuffer jarg2); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_Rate_areFreeTickets")] + public static extern bool Rate_areFreeTickets(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_delete_Rate")] + public static extern void delete_Rate(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_UnlimitedRate_process")] + public static extern void UnlimitedRate_process(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_UnlimitedRate_claimTicket")] + public static extern global::System.IntPtr UnlimitedRate_claimTicket(global::System.Runtime.InteropServices.HandleRef jarg1, FBIntermediateBuffer jarg2); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_UnlimitedRate_tryClaimTicket")] + public static extern global::System.IntPtr UnlimitedRate_tryClaimTicket(global::System.Runtime.InteropServices.HandleRef jarg1, FBIntermediateBuffer jarg2); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_UnlimitedRate_areFreeTickets")] + public static extern bool UnlimitedRate_areFreeTickets(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_new_UnlimitedRate")] + public static extern global::System.IntPtr new_UnlimitedRate(); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_delete_UnlimitedRate")] + public static extern void delete_UnlimitedRate(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_PendingBytesRate_process")] + public static extern void PendingBytesRate_process(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_PendingBytesRate_claimTicket")] + public static extern global::System.IntPtr PendingBytesRate_claimTicket(global::System.Runtime.InteropServices.HandleRef jarg1, FBIntermediateBuffer jarg2); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_PendingBytesRate_tryClaimTicket")] + public static extern global::System.IntPtr PendingBytesRate_tryClaimTicket(global::System.Runtime.InteropServices.HandleRef jarg1, FBIntermediateBuffer jarg2); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_PendingBytesRate_areFreeTickets")] + public static extern bool PendingBytesRate_areFreeTickets(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_new_PendingBytesRate__SWIG_0")] + public static extern global::System.IntPtr new_PendingBytesRate__SWIG_0(global::System.Runtime.InteropServices.HandleRef jarg1, long jarg2); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_new_PendingBytesRate__SWIG_1")] + public static extern global::System.IntPtr new_PendingBytesRate__SWIG_1(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_delete_PendingBytesRate")] + public static extern void delete_PendingBytesRate(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_UnlimitedRate_SWIGSmartPtrUpcast")] + public static extern global::System.IntPtr UnlimitedRate_SWIGSmartPtrUpcast(global::System.IntPtr jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_PendingBytesRate_SWIGSmartPtrUpcast")] + public static extern global::System.IntPtr PendingBytesRate_SWIGSmartPtrUpcast(global::System.IntPtr jarg1); +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotRatePINVOKE.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotRatePINVOKE.cs.meta new file mode 100644 index 0000000..0d759f2 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotRatePINVOKE.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 3d681bad830392eb2a541eaf6731cebd diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotSession.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotSession.cs new file mode 100644 index 0000000..e144b47 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotSession.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public class GrapeshotSession { +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotSession.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotSession.cs.meta new file mode 100644 index 0000000..0a12fdf --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotSession.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 0553758da489b2690d8e678561367e59 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotSessionPINVOKE.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotSessionPINVOKE.cs new file mode 100644 index 0000000..9b9535a --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotSessionPINVOKE.cs @@ -0,0 +1,367 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +class GrapeshotSessionPINVOKE { + + /// For Mono AOT platforms compatibility + /// This attribute can be defined in any assembly for Mono AOT to use it. + public class MonoPInvokeCallbackAttribute : global::System.Attribute { + public MonoPInvokeCallbackAttribute(global::System.Type t) { + } + } + + + protected class SWIGExceptionHelper { + public delegate void ExceptionDelegate(string message); + public delegate void ExceptionArgumentDelegate(string message, string paramName); + + static ExceptionDelegate applicationDelegate = new ExceptionDelegate(SetPendingApplicationException); + static ExceptionDelegate arithmeticDelegate = new ExceptionDelegate(SetPendingArithmeticException); + static ExceptionDelegate divideByZeroDelegate = new ExceptionDelegate(SetPendingDivideByZeroException); + static ExceptionDelegate indexOutOfRangeDelegate = new ExceptionDelegate(SetPendingIndexOutOfRangeException); + static ExceptionDelegate invalidCastDelegate = new ExceptionDelegate(SetPendingInvalidCastException); + static ExceptionDelegate invalidOperationDelegate = new ExceptionDelegate(SetPendingInvalidOperationException); + static ExceptionDelegate ioDelegate = new ExceptionDelegate(SetPendingIOException); + static ExceptionDelegate nullReferenceDelegate = new ExceptionDelegate(SetPendingNullReferenceException); + static ExceptionDelegate outOfMemoryDelegate = new ExceptionDelegate(SetPendingOutOfMemoryException); + static ExceptionDelegate overflowDelegate = new ExceptionDelegate(SetPendingOverflowException); + static ExceptionDelegate systemDelegate = new ExceptionDelegate(SetPendingSystemException); + + static ExceptionArgumentDelegate argumentDelegate = new ExceptionArgumentDelegate(SetPendingArgumentException); + static ExceptionArgumentDelegate argumentNullDelegate = new ExceptionArgumentDelegate(SetPendingArgumentNullException); + static ExceptionArgumentDelegate argumentOutOfRangeDelegate = new ExceptionArgumentDelegate(SetPendingArgumentOutOfRangeException); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="SWIGRegisterExceptionCallbacks_GrapeshotSession")] + public static extern void SWIGRegisterExceptionCallbacks_GrapeshotSession( + ExceptionDelegate applicationDelegate, + ExceptionDelegate arithmeticDelegate, + ExceptionDelegate divideByZeroDelegate, + ExceptionDelegate indexOutOfRangeDelegate, + ExceptionDelegate invalidCastDelegate, + ExceptionDelegate invalidOperationDelegate, + ExceptionDelegate ioDelegate, + ExceptionDelegate nullReferenceDelegate, + ExceptionDelegate outOfMemoryDelegate, + ExceptionDelegate overflowDelegate, + ExceptionDelegate systemExceptionDelegate); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="SWIGRegisterExceptionArgumentCallbacks_GrapeshotSession")] + public static extern void SWIGRegisterExceptionCallbacksArgument_GrapeshotSession( + ExceptionArgumentDelegate argumentDelegate, + ExceptionArgumentDelegate argumentNullDelegate, + ExceptionArgumentDelegate argumentOutOfRangeDelegate); + + + [GrapeshotSessionPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingApplicationException(string message) { + SWIGPendingException.Set(new global::System.ApplicationException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotSessionPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingArithmeticException(string message) { + SWIGPendingException.Set(new global::System.ArithmeticException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotSessionPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingDivideByZeroException(string message) { + SWIGPendingException.Set(new global::System.DivideByZeroException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotSessionPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingIndexOutOfRangeException(string message) { + SWIGPendingException.Set(new global::System.IndexOutOfRangeException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotSessionPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingInvalidCastException(string message) { + SWIGPendingException.Set(new global::System.InvalidCastException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotSessionPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingInvalidOperationException(string message) { + SWIGPendingException.Set(new global::System.InvalidOperationException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotSessionPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingIOException(string message) { + SWIGPendingException.Set(new global::System.IO.IOException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotSessionPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingNullReferenceException(string message) { + SWIGPendingException.Set(new global::System.NullReferenceException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotSessionPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingOutOfMemoryException(string message) { + SWIGPendingException.Set(new global::System.OutOfMemoryException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotSessionPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingOverflowException(string message) { + SWIGPendingException.Set(new global::System.OverflowException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotSessionPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingSystemException(string message) { + SWIGPendingException.Set(new global::System.SystemException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotSessionPINVOKE.MonoPInvokeCallback(typeof(ExceptionArgumentDelegate))] + + + static void SetPendingArgumentException(string message, string paramName) { + SWIGPendingException.Set(new global::System.ArgumentException(message, paramName, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotSessionPINVOKE.MonoPInvokeCallback(typeof(ExceptionArgumentDelegate))] + + + static void SetPendingArgumentNullException(string message, string paramName) { + global::System.Exception e = SWIGPendingException.Retrieve(); + if (e != null) message = message + " Inner Exception: " + e.Message; + SWIGPendingException.Set(new global::System.ArgumentNullException(paramName, message)); + } + + + + [GrapeshotSessionPINVOKE.MonoPInvokeCallback(typeof(ExceptionArgumentDelegate))] + + + static void SetPendingArgumentOutOfRangeException(string message, string paramName) { + global::System.Exception e = SWIGPendingException.Retrieve(); + if (e != null) message = message + " Inner Exception: " + e.Message; + SWIGPendingException.Set(new global::System.ArgumentOutOfRangeException(paramName, message)); + } + + static SWIGExceptionHelper() { + SWIGRegisterExceptionCallbacks_GrapeshotSession( + applicationDelegate, + arithmeticDelegate, + divideByZeroDelegate, + indexOutOfRangeDelegate, + invalidCastDelegate, + invalidOperationDelegate, + ioDelegate, + nullReferenceDelegate, + outOfMemoryDelegate, + overflowDelegate, + systemDelegate); + + SWIGRegisterExceptionCallbacksArgument_GrapeshotSession( + argumentDelegate, + argumentNullDelegate, + argumentOutOfRangeDelegate); + } + } + + protected static SWIGExceptionHelper swigExceptionHelper = new SWIGExceptionHelper(); + + public class SWIGPendingException { + [global::System.ThreadStatic] + private static global::System.Exception pendingException = null; + private static int numExceptionsPending = 0; + + public static bool Pending { + get { + bool pending = false; + if (numExceptionsPending > 0) + if (pendingException != null) + pending = true; + return pending; + } + } + + public static void Set(global::System.Exception e) { + if (pendingException != null) + throw new global::System.ApplicationException("FATAL: An earlier pending exception from unmanaged code was missed and thus not thrown (" + pendingException.ToString() + ")", e); + pendingException = e; + lock(typeof(GrapeshotSessionPINVOKE)) { + numExceptionsPending++; + } + } + + public static global::System.Exception Retrieve() { + global::System.Exception e = null; + if (numExceptionsPending > 0) { + if (pendingException != null) { + e = pendingException; + pendingException = null; + lock(typeof(GrapeshotSessionPINVOKE)) { + numExceptionsPending--; + } + } + } + return e; + } + } + + + protected class SWIGStringHelper { + public delegate string SWIGStringDelegate(string message); + static SWIGStringDelegate stringDelegate = new SWIGStringDelegate(CreateString); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="SWIGRegisterStringCallback_GrapeshotSession")] + public static extern void SWIGRegisterStringCallback_GrapeshotSession(SWIGStringDelegate stringDelegate); + + + [GrapeshotSessionPINVOKE.MonoPInvokeCallback(typeof(SWIGStringDelegate))] + + + static string CreateString(string cString) { + return cString; + } + + static SWIGStringHelper() { + SWIGRegisterStringCallback_GrapeshotSession(stringDelegate); + } + } + + static protected SWIGStringHelper swigStringHelper = new SWIGStringHelper(); + + + static GrapeshotSessionPINVOKE() { + } + + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_ChunkFetcherParams_index_get")] + public static extern ulong ChunkFetcherParams_index_get(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_ChunkFetcherParams_bodyReturn_get")] + public static extern global::System.IntPtr ChunkFetcherParams_bodyReturn_get(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_ChunkFetcherParams_authReturn_get")] + public static extern global::System.IntPtr ChunkFetcherParams_authReturn_get(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_ChunkFetcherParams_serviceInfoReturn_set")] + public static extern void ChunkFetcherParams_serviceInfoReturn_set(global::System.Runtime.InteropServices.HandleRef jarg1, global::System.Runtime.InteropServices.HandleRef jarg2); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_ChunkFetcherParams_serviceInfoReturn_get")] + public static extern global::System.IntPtr ChunkFetcherParams_serviceInfoReturn_get(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_new_ChunkFetcherParams")] + public static extern global::System.IntPtr new_ChunkFetcherParams(); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_delete_ChunkFetcherParams")] + public static extern void delete_ChunkFetcherParams(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_ApplicationChunkFetcher_FunctionApplicationBridgeBase_invokeApplicationLogic")] + public static extern void ApplicationChunkFetcher_FunctionApplicationBridgeBase_invokeApplicationLogic(global::System.Runtime.InteropServices.HandleRef jarg1, global::System.Runtime.InteropServices.HandleRef jarg2); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_ApplicationChunkFetcher_FunctionApplicationBridgeBase_releaseApplicationCallback")] + public static extern void ApplicationChunkFetcher_FunctionApplicationBridgeBase_releaseApplicationCallback(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_delete_ApplicationChunkFetcher_FunctionApplicationBridgeBase")] + public static extern void delete_ApplicationChunkFetcher_FunctionApplicationBridgeBase(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_new_ApplicationChunkFetcher_FunctionApplicationBridgeBase")] + public static extern global::System.IntPtr new_ApplicationChunkFetcher_FunctionApplicationBridgeBase(); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_ApplicationChunkFetcher_FunctionApplicationBridgeBase_director_connect")] + public static extern void ApplicationChunkFetcher_FunctionApplicationBridgeBase_director_connect(global::System.Runtime.InteropServices.HandleRef jarg1, ApplicationChunkFetcher_FunctionApplicationBridgeBase.SwigDelegateApplicationChunkFetcher_FunctionApplicationBridgeBase_0_Dispatcher delegate0_dispatcher, global::System.IntPtr delegate0gcHandlePtr, ApplicationChunkFetcher_FunctionApplicationBridgeBase.SwigDelegateApplicationChunkFetcher_FunctionApplicationBridgeBase_1_Dispatcher delegate1_dispatcher, global::System.IntPtr delegate1gcHandlePtr); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_FinishedCallback_FunctionApplicationBridgeBase_invokeApplicationLogic")] + public static extern void FinishedCallback_FunctionApplicationBridgeBase_invokeApplicationLogic(global::System.Runtime.InteropServices.HandleRef jarg1, bool jarg2); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_FinishedCallback_FunctionApplicationBridgeBase_releaseApplicationCallback")] + public static extern void FinishedCallback_FunctionApplicationBridgeBase_releaseApplicationCallback(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_delete_FinishedCallback_FunctionApplicationBridgeBase")] + public static extern void delete_FinishedCallback_FunctionApplicationBridgeBase(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_new_FinishedCallback_FunctionApplicationBridgeBase")] + public static extern global::System.IntPtr new_FinishedCallback_FunctionApplicationBridgeBase(); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_FinishedCallback_FunctionApplicationBridgeBase_director_connect")] + public static extern void FinishedCallback_FunctionApplicationBridgeBase_director_connect(global::System.Runtime.InteropServices.HandleRef jarg1, FinishedCallback_FunctionApplicationBridgeBase.SwigDelegateFinishedCallback_FunctionApplicationBridgeBase_0_Dispatcher delegate0_dispatcher, global::System.IntPtr delegate0gcHandlePtr, FinishedCallback_FunctionApplicationBridgeBase.SwigDelegateFinishedCallback_FunctionApplicationBridgeBase_1_Dispatcher delegate1_dispatcher, global::System.IntPtr delegate1gcHandlePtr); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_ResponseCallback_FunctionApplicationBridgeBase_invokeApplicationLogic")] + public static extern void ResponseCallback_FunctionApplicationBridgeBase_invokeApplicationLogic(global::System.Runtime.InteropServices.HandleRef jarg1, FBIntermediateBuffer jarg2); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_ResponseCallback_FunctionApplicationBridgeBase_releaseApplicationCallback")] + public static extern void ResponseCallback_FunctionApplicationBridgeBase_releaseApplicationCallback(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_delete_ResponseCallback_FunctionApplicationBridgeBase")] + public static extern void delete_ResponseCallback_FunctionApplicationBridgeBase(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_new_ResponseCallback_FunctionApplicationBridgeBase")] + public static extern global::System.IntPtr new_ResponseCallback_FunctionApplicationBridgeBase(); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_ResponseCallback_FunctionApplicationBridgeBase_director_connect")] + public static extern void ResponseCallback_FunctionApplicationBridgeBase_director_connect(global::System.Runtime.InteropServices.HandleRef jarg1, ResponseCallback_FunctionApplicationBridgeBase.SwigDelegateResponseCallback_FunctionApplicationBridgeBase_0_Dispatcher delegate0_dispatcher, global::System.IntPtr delegate0gcHandlePtr, ResponseCallback_FunctionApplicationBridgeBase.SwigDelegateResponseCallback_FunctionApplicationBridgeBase_1_Dispatcher delegate1_dispatcher, global::System.IntPtr delegate1gcHandlePtr); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_Session_process__SWIG_0")] + public static extern void Session_process__SWIG_0(global::System.Runtime.InteropServices.HandleRef jarg1, uint jarg2); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_Session_process__SWIG_1")] + public static extern void Session_process__SWIG_1(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_Session_isFinished")] + public static extern bool Session_isFinished(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_Session_waitTillFinished")] + public static extern void Session_waitTillFinished(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_new_Session")] + public static extern global::System.IntPtr new_Session(System.IntPtr jarg1, FBIntermediateBuffer jarg2, global::System.Runtime.InteropServices.HandleRef jarg3, global::System.Runtime.InteropServices.HandleRef jarg4, global::System.Runtime.InteropServices.HandleRef jarg5, global::System.Runtime.InteropServices.HandleRef jarg6, global::System.Runtime.InteropServices.HandleRef jarg7); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_delete_Session")] + public static extern void delete_Session(global::System.Runtime.InteropServices.HandleRef jarg1); +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotSessionPINVOKE.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotSessionPINVOKE.cs.meta new file mode 100644 index 0000000..dbc1111 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotSessionPINVOKE.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 341c103dad9e931bc290c2235b14bb05 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotUploadFlatbuffers.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotUploadFlatbuffers.cs new file mode 100644 index 0000000..457fff2 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotUploadFlatbuffers.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public class GrapeshotUploadFlatbuffers { +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotUploadFlatbuffers.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotUploadFlatbuffers.cs.meta new file mode 100644 index 0000000..321615e --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotUploadFlatbuffers.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: a460d640b1ee65f36cfba5be00d75346 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotUploadFlatbuffersPINVOKE.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotUploadFlatbuffersPINVOKE.cs new file mode 100644 index 0000000..720969b --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotUploadFlatbuffersPINVOKE.cs @@ -0,0 +1,319 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +class GrapeshotUploadFlatbuffersPINVOKE { + + /// For Mono AOT platforms compatibility + /// This attribute can be defined in any assembly for Mono AOT to use it. + public class MonoPInvokeCallbackAttribute : global::System.Attribute { + public MonoPInvokeCallbackAttribute(global::System.Type t) { + } + } + + + protected class SWIGExceptionHelper { + public delegate void ExceptionDelegate(string message); + public delegate void ExceptionArgumentDelegate(string message, string paramName); + + static ExceptionDelegate applicationDelegate = new ExceptionDelegate(SetPendingApplicationException); + static ExceptionDelegate arithmeticDelegate = new ExceptionDelegate(SetPendingArithmeticException); + static ExceptionDelegate divideByZeroDelegate = new ExceptionDelegate(SetPendingDivideByZeroException); + static ExceptionDelegate indexOutOfRangeDelegate = new ExceptionDelegate(SetPendingIndexOutOfRangeException); + static ExceptionDelegate invalidCastDelegate = new ExceptionDelegate(SetPendingInvalidCastException); + static ExceptionDelegate invalidOperationDelegate = new ExceptionDelegate(SetPendingInvalidOperationException); + static ExceptionDelegate ioDelegate = new ExceptionDelegate(SetPendingIOException); + static ExceptionDelegate nullReferenceDelegate = new ExceptionDelegate(SetPendingNullReferenceException); + static ExceptionDelegate outOfMemoryDelegate = new ExceptionDelegate(SetPendingOutOfMemoryException); + static ExceptionDelegate overflowDelegate = new ExceptionDelegate(SetPendingOverflowException); + static ExceptionDelegate systemDelegate = new ExceptionDelegate(SetPendingSystemException); + + static ExceptionArgumentDelegate argumentDelegate = new ExceptionArgumentDelegate(SetPendingArgumentException); + static ExceptionArgumentDelegate argumentNullDelegate = new ExceptionArgumentDelegate(SetPendingArgumentNullException); + static ExceptionArgumentDelegate argumentOutOfRangeDelegate = new ExceptionArgumentDelegate(SetPendingArgumentOutOfRangeException); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="SWIGRegisterExceptionCallbacks_GrapeshotUploadFlatbuffers")] + public static extern void SWIGRegisterExceptionCallbacks_GrapeshotUploadFlatbuffers( + ExceptionDelegate applicationDelegate, + ExceptionDelegate arithmeticDelegate, + ExceptionDelegate divideByZeroDelegate, + ExceptionDelegate indexOutOfRangeDelegate, + ExceptionDelegate invalidCastDelegate, + ExceptionDelegate invalidOperationDelegate, + ExceptionDelegate ioDelegate, + ExceptionDelegate nullReferenceDelegate, + ExceptionDelegate outOfMemoryDelegate, + ExceptionDelegate overflowDelegate, + ExceptionDelegate systemExceptionDelegate); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="SWIGRegisterExceptionArgumentCallbacks_GrapeshotUploadFlatbuffers")] + public static extern void SWIGRegisterExceptionCallbacksArgument_GrapeshotUploadFlatbuffers( + ExceptionArgumentDelegate argumentDelegate, + ExceptionArgumentDelegate argumentNullDelegate, + ExceptionArgumentDelegate argumentOutOfRangeDelegate); + + + [GrapeshotUploadFlatbuffersPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingApplicationException(string message) { + SWIGPendingException.Set(new global::System.ApplicationException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotUploadFlatbuffersPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingArithmeticException(string message) { + SWIGPendingException.Set(new global::System.ArithmeticException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotUploadFlatbuffersPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingDivideByZeroException(string message) { + SWIGPendingException.Set(new global::System.DivideByZeroException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotUploadFlatbuffersPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingIndexOutOfRangeException(string message) { + SWIGPendingException.Set(new global::System.IndexOutOfRangeException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotUploadFlatbuffersPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingInvalidCastException(string message) { + SWIGPendingException.Set(new global::System.InvalidCastException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotUploadFlatbuffersPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingInvalidOperationException(string message) { + SWIGPendingException.Set(new global::System.InvalidOperationException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotUploadFlatbuffersPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingIOException(string message) { + SWIGPendingException.Set(new global::System.IO.IOException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotUploadFlatbuffersPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingNullReferenceException(string message) { + SWIGPendingException.Set(new global::System.NullReferenceException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotUploadFlatbuffersPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingOutOfMemoryException(string message) { + SWIGPendingException.Set(new global::System.OutOfMemoryException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotUploadFlatbuffersPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingOverflowException(string message) { + SWIGPendingException.Set(new global::System.OverflowException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotUploadFlatbuffersPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingSystemException(string message) { + SWIGPendingException.Set(new global::System.SystemException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotUploadFlatbuffersPINVOKE.MonoPInvokeCallback(typeof(ExceptionArgumentDelegate))] + + + static void SetPendingArgumentException(string message, string paramName) { + SWIGPendingException.Set(new global::System.ArgumentException(message, paramName, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotUploadFlatbuffersPINVOKE.MonoPInvokeCallback(typeof(ExceptionArgumentDelegate))] + + + static void SetPendingArgumentNullException(string message, string paramName) { + global::System.Exception e = SWIGPendingException.Retrieve(); + if (e != null) message = message + " Inner Exception: " + e.Message; + SWIGPendingException.Set(new global::System.ArgumentNullException(paramName, message)); + } + + + + [GrapeshotUploadFlatbuffersPINVOKE.MonoPInvokeCallback(typeof(ExceptionArgumentDelegate))] + + + static void SetPendingArgumentOutOfRangeException(string message, string paramName) { + global::System.Exception e = SWIGPendingException.Retrieve(); + if (e != null) message = message + " Inner Exception: " + e.Message; + SWIGPendingException.Set(new global::System.ArgumentOutOfRangeException(paramName, message)); + } + + static SWIGExceptionHelper() { + SWIGRegisterExceptionCallbacks_GrapeshotUploadFlatbuffers( + applicationDelegate, + arithmeticDelegate, + divideByZeroDelegate, + indexOutOfRangeDelegate, + invalidCastDelegate, + invalidOperationDelegate, + ioDelegate, + nullReferenceDelegate, + outOfMemoryDelegate, + overflowDelegate, + systemDelegate); + + SWIGRegisterExceptionCallbacksArgument_GrapeshotUploadFlatbuffers( + argumentDelegate, + argumentNullDelegate, + argumentOutOfRangeDelegate); + } + } + + protected static SWIGExceptionHelper swigExceptionHelper = new SWIGExceptionHelper(); + + public class SWIGPendingException { + [global::System.ThreadStatic] + private static global::System.Exception pendingException = null; + private static int numExceptionsPending = 0; + + public static bool Pending { + get { + bool pending = false; + if (numExceptionsPending > 0) + if (pendingException != null) + pending = true; + return pending; + } + } + + public static void Set(global::System.Exception e) { + if (pendingException != null) + throw new global::System.ApplicationException("FATAL: An earlier pending exception from unmanaged code was missed and thus not thrown (" + pendingException.ToString() + ")", e); + pendingException = e; + lock(typeof(GrapeshotUploadFlatbuffersPINVOKE)) { + numExceptionsPending++; + } + } + + public static global::System.Exception Retrieve() { + global::System.Exception e = null; + if (numExceptionsPending > 0) { + if (pendingException != null) { + e = pendingException; + pendingException = null; + lock(typeof(GrapeshotUploadFlatbuffersPINVOKE)) { + numExceptionsPending--; + } + } + } + return e; + } + } + + + protected class SWIGStringHelper { + public delegate string SWIGStringDelegate(string message); + static SWIGStringDelegate stringDelegate = new SWIGStringDelegate(CreateString); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="SWIGRegisterStringCallback_GrapeshotUploadFlatbuffers")] + public static extern void SWIGRegisterStringCallback_GrapeshotUploadFlatbuffers(SWIGStringDelegate stringDelegate); + + + [GrapeshotUploadFlatbuffersPINVOKE.MonoPInvokeCallback(typeof(SWIGStringDelegate))] + + + static string CreateString(string cString) { + return cString; + } + + static SWIGStringHelper() { + SWIGRegisterStringCallback_GrapeshotUploadFlatbuffers(stringDelegate); + } + } + + static protected SWIGStringHelper swigStringHelper = new SWIGStringHelper(); + + + static GrapeshotUploadFlatbuffersPINVOKE() { + } + + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_UploadChunkRequest_Ret_ret")] + public static extern void UploadChunkRequest_Ret_ret(global::System.Runtime.InteropServices.HandleRef jarg1, FBIntermediateBuffer jarg2); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_new_UploadChunkRequest_Ret")] + public static extern global::System.IntPtr new_UploadChunkRequest_Ret(); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_delete_UploadChunkRequest_Ret")] + public static extern void delete_UploadChunkRequest_Ret(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_UploadChunkBody_Ret_ret")] + public static extern void UploadChunkBody_Ret_ret(global::System.Runtime.InteropServices.HandleRef jarg1, FBIntermediateBuffer jarg2); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_new_UploadChunkBody_Ret")] + public static extern global::System.IntPtr new_UploadChunkBody_Ret(); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_delete_UploadChunkBody_Ret")] + public static extern void delete_UploadChunkBody_Ret(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_UploadAuth_Ret_ret")] + public static extern void UploadAuth_Ret_ret(global::System.Runtime.InteropServices.HandleRef jarg1, FBIntermediateBuffer jarg2); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_new_UploadAuth_Ret")] + public static extern global::System.IntPtr new_UploadAuth_Ret(); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_delete_UploadAuth_Ret")] + public static extern void delete_UploadAuth_Ret(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_UploadServiceInfo_Ret_ret")] + public static extern void UploadServiceInfo_Ret_ret(global::System.Runtime.InteropServices.HandleRef jarg1, FBIntermediateBuffer jarg2); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_new_UploadServiceInfo_Ret")] + public static extern global::System.IntPtr new_UploadServiceInfo_Ret(); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_delete_UploadServiceInfo_Ret")] + public static extern void delete_UploadServiceInfo_Ret(global::System.Runtime.InteropServices.HandleRef jarg1); +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotUploadFlatbuffersPINVOKE.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotUploadFlatbuffersPINVOKE.cs.meta new file mode 100644 index 0000000..8ab84aa --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotUploadFlatbuffersPINVOKE.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 77bb351148990b5f8ce6f22d9445b654 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotUploadSessionDBAccessor.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotUploadSessionDBAccessor.cs new file mode 100644 index 0000000..c2f586e --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotUploadSessionDBAccessor.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public class GrapeshotUploadSessionDBAccessor { +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotUploadSessionDBAccessor.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotUploadSessionDBAccessor.cs.meta new file mode 100644 index 0000000..9521954 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotUploadSessionDBAccessor.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 9250cfe5833e76a4e464a8bacf286f2b diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotUploadSessionDBAccessorPINVOKE.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotUploadSessionDBAccessorPINVOKE.cs new file mode 100644 index 0000000..c117857 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotUploadSessionDBAccessorPINVOKE.cs @@ -0,0 +1,295 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +class GrapeshotUploadSessionDBAccessorPINVOKE { + + /// For Mono AOT platforms compatibility + /// This attribute can be defined in any assembly for Mono AOT to use it. + public class MonoPInvokeCallbackAttribute : global::System.Attribute { + public MonoPInvokeCallbackAttribute(global::System.Type t) { + } + } + + + protected class SWIGExceptionHelper { + public delegate void ExceptionDelegate(string message); + public delegate void ExceptionArgumentDelegate(string message, string paramName); + + static ExceptionDelegate applicationDelegate = new ExceptionDelegate(SetPendingApplicationException); + static ExceptionDelegate arithmeticDelegate = new ExceptionDelegate(SetPendingArithmeticException); + static ExceptionDelegate divideByZeroDelegate = new ExceptionDelegate(SetPendingDivideByZeroException); + static ExceptionDelegate indexOutOfRangeDelegate = new ExceptionDelegate(SetPendingIndexOutOfRangeException); + static ExceptionDelegate invalidCastDelegate = new ExceptionDelegate(SetPendingInvalidCastException); + static ExceptionDelegate invalidOperationDelegate = new ExceptionDelegate(SetPendingInvalidOperationException); + static ExceptionDelegate ioDelegate = new ExceptionDelegate(SetPendingIOException); + static ExceptionDelegate nullReferenceDelegate = new ExceptionDelegate(SetPendingNullReferenceException); + static ExceptionDelegate outOfMemoryDelegate = new ExceptionDelegate(SetPendingOutOfMemoryException); + static ExceptionDelegate overflowDelegate = new ExceptionDelegate(SetPendingOverflowException); + static ExceptionDelegate systemDelegate = new ExceptionDelegate(SetPendingSystemException); + + static ExceptionArgumentDelegate argumentDelegate = new ExceptionArgumentDelegate(SetPendingArgumentException); + static ExceptionArgumentDelegate argumentNullDelegate = new ExceptionArgumentDelegate(SetPendingArgumentNullException); + static ExceptionArgumentDelegate argumentOutOfRangeDelegate = new ExceptionArgumentDelegate(SetPendingArgumentOutOfRangeException); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="SWIGRegisterExceptionCallbacks_GrapeshotUploadSessionDBAccessor")] + public static extern void SWIGRegisterExceptionCallbacks_GrapeshotUploadSessionDBAccessor( + ExceptionDelegate applicationDelegate, + ExceptionDelegate arithmeticDelegate, + ExceptionDelegate divideByZeroDelegate, + ExceptionDelegate indexOutOfRangeDelegate, + ExceptionDelegate invalidCastDelegate, + ExceptionDelegate invalidOperationDelegate, + ExceptionDelegate ioDelegate, + ExceptionDelegate nullReferenceDelegate, + ExceptionDelegate outOfMemoryDelegate, + ExceptionDelegate overflowDelegate, + ExceptionDelegate systemExceptionDelegate); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="SWIGRegisterExceptionArgumentCallbacks_GrapeshotUploadSessionDBAccessor")] + public static extern void SWIGRegisterExceptionCallbacksArgument_GrapeshotUploadSessionDBAccessor( + ExceptionArgumentDelegate argumentDelegate, + ExceptionArgumentDelegate argumentNullDelegate, + ExceptionArgumentDelegate argumentOutOfRangeDelegate); + + + [GrapeshotUploadSessionDBAccessorPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingApplicationException(string message) { + SWIGPendingException.Set(new global::System.ApplicationException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotUploadSessionDBAccessorPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingArithmeticException(string message) { + SWIGPendingException.Set(new global::System.ArithmeticException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotUploadSessionDBAccessorPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingDivideByZeroException(string message) { + SWIGPendingException.Set(new global::System.DivideByZeroException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotUploadSessionDBAccessorPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingIndexOutOfRangeException(string message) { + SWIGPendingException.Set(new global::System.IndexOutOfRangeException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotUploadSessionDBAccessorPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingInvalidCastException(string message) { + SWIGPendingException.Set(new global::System.InvalidCastException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotUploadSessionDBAccessorPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingInvalidOperationException(string message) { + SWIGPendingException.Set(new global::System.InvalidOperationException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotUploadSessionDBAccessorPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingIOException(string message) { + SWIGPendingException.Set(new global::System.IO.IOException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotUploadSessionDBAccessorPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingNullReferenceException(string message) { + SWIGPendingException.Set(new global::System.NullReferenceException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotUploadSessionDBAccessorPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingOutOfMemoryException(string message) { + SWIGPendingException.Set(new global::System.OutOfMemoryException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotUploadSessionDBAccessorPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingOverflowException(string message) { + SWIGPendingException.Set(new global::System.OverflowException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotUploadSessionDBAccessorPINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingSystemException(string message) { + SWIGPendingException.Set(new global::System.SystemException(message, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotUploadSessionDBAccessorPINVOKE.MonoPInvokeCallback(typeof(ExceptionArgumentDelegate))] + + + static void SetPendingArgumentException(string message, string paramName) { + SWIGPendingException.Set(new global::System.ArgumentException(message, paramName, SWIGPendingException.Retrieve())); + } + + + + [GrapeshotUploadSessionDBAccessorPINVOKE.MonoPInvokeCallback(typeof(ExceptionArgumentDelegate))] + + + static void SetPendingArgumentNullException(string message, string paramName) { + global::System.Exception e = SWIGPendingException.Retrieve(); + if (e != null) message = message + " Inner Exception: " + e.Message; + SWIGPendingException.Set(new global::System.ArgumentNullException(paramName, message)); + } + + + + [GrapeshotUploadSessionDBAccessorPINVOKE.MonoPInvokeCallback(typeof(ExceptionArgumentDelegate))] + + + static void SetPendingArgumentOutOfRangeException(string message, string paramName) { + global::System.Exception e = SWIGPendingException.Retrieve(); + if (e != null) message = message + " Inner Exception: " + e.Message; + SWIGPendingException.Set(new global::System.ArgumentOutOfRangeException(paramName, message)); + } + + static SWIGExceptionHelper() { + SWIGRegisterExceptionCallbacks_GrapeshotUploadSessionDBAccessor( + applicationDelegate, + arithmeticDelegate, + divideByZeroDelegate, + indexOutOfRangeDelegate, + invalidCastDelegate, + invalidOperationDelegate, + ioDelegate, + nullReferenceDelegate, + outOfMemoryDelegate, + overflowDelegate, + systemDelegate); + + SWIGRegisterExceptionCallbacksArgument_GrapeshotUploadSessionDBAccessor( + argumentDelegate, + argumentNullDelegate, + argumentOutOfRangeDelegate); + } + } + + protected static SWIGExceptionHelper swigExceptionHelper = new SWIGExceptionHelper(); + + public class SWIGPendingException { + [global::System.ThreadStatic] + private static global::System.Exception pendingException = null; + private static int numExceptionsPending = 0; + + public static bool Pending { + get { + bool pending = false; + if (numExceptionsPending > 0) + if (pendingException != null) + pending = true; + return pending; + } + } + + public static void Set(global::System.Exception e) { + if (pendingException != null) + throw new global::System.ApplicationException("FATAL: An earlier pending exception from unmanaged code was missed and thus not thrown (" + pendingException.ToString() + ")", e); + pendingException = e; + lock(typeof(GrapeshotUploadSessionDBAccessorPINVOKE)) { + numExceptionsPending++; + } + } + + public static global::System.Exception Retrieve() { + global::System.Exception e = null; + if (numExceptionsPending > 0) { + if (pendingException != null) { + e = pendingException; + pendingException = null; + lock(typeof(GrapeshotUploadSessionDBAccessorPINVOKE)) { + numExceptionsPending--; + } + } + } + return e; + } + } + + + protected class SWIGStringHelper { + public delegate string SWIGStringDelegate(string message); + static SWIGStringDelegate stringDelegate = new SWIGStringDelegate(CreateString); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="SWIGRegisterStringCallback_GrapeshotUploadSessionDBAccessor")] + public static extern void SWIGRegisterStringCallback_GrapeshotUploadSessionDBAccessor(SWIGStringDelegate stringDelegate); + + + [GrapeshotUploadSessionDBAccessorPINVOKE.MonoPInvokeCallback(typeof(SWIGStringDelegate))] + + + static string CreateString(string cString) { + return cString; + } + + static SWIGStringHelper() { + SWIGRegisterStringCallback_GrapeshotUploadSessionDBAccessor(stringDelegate); + } + } + + static protected SWIGStringHelper swigStringHelper = new SWIGStringHelper(); + + + static GrapeshotUploadSessionDBAccessorPINVOKE() { + } + + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_delete_UploadSessionDBAccessor")] + public static extern void delete_UploadSessionDBAccessor(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_new_LocalUploadSessionDBAccessor")] + public static extern global::System.IntPtr new_LocalUploadSessionDBAccessor(); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_delete_LocalUploadSessionDBAccessor")] + public static extern void delete_LocalUploadSessionDBAccessor(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_LocalUploadSessionDBAccessor_SWIGSmartPtrUpcast")] + public static extern global::System.IntPtr LocalUploadSessionDBAccessor_SWIGSmartPtrUpcast(global::System.IntPtr jarg1); +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotUploadSessionDBAccessorPINVOKE.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotUploadSessionDBAccessorPINVOKE.cs.meta new file mode 100644 index 0000000..9490467 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/GrapeshotUploadSessionDBAccessorPINVOKE.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: b5e51fa5f95ac040913dfebf9ee42547 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/InterprocDriver.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/InterprocDriver.cs new file mode 100644 index 0000000..e5a410d --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/InterprocDriver.cs @@ -0,0 +1,76 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public class InterprocDriver : Driver { + private global::System.Runtime.InteropServices.HandleRef swigCPtr; + private bool swigCMemOwnDerived; + + internal InterprocDriver(global::System.IntPtr cPtr, bool cMemoryOwn) : base(GrapeshotDriverPINVOKE.InterprocDriver_SWIGSmartPtrUpcast(cPtr), true) { + swigCMemOwnDerived = cMemoryOwn; + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr); + } + + internal static global::System.Runtime.InteropServices.HandleRef getCPtr(InterprocDriver obj) { + return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; + } + + ~InterprocDriver() { + Dispose(); + } + + public override void Dispose() { + lock(this) { + if (swigCPtr.Handle != global::System.IntPtr.Zero) { + if (swigCMemOwnDerived) { + swigCMemOwnDerived = false; + GrapeshotDriverPINVOKE.delete_InterprocDriver(swigCPtr); + } + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); + } + global::System.GC.SuppressFinalize(this); + base.Dispose(); + } + } + + public override void process() { + GrapeshotDriverPINVOKE.InterprocDriver_process(swigCPtr); + if (GrapeshotDriverPINVOKE.SWIGPendingException.Pending) throw GrapeshotDriverPINVOKE.SWIGPendingException.Retrieve(); + } + + public override void sendChunk(System.Guid clientIdentifier, ror.schema.upload.UploadChunkRequest chunk, RequestCallback_FunctionApplicationBridgeBase callback) { +var clientIdentifier_Bytes = clientIdentifier.ToByteArray();var clientIdentifier_ByteArrayHandle = System.Runtime.InteropServices.GCHandle.Alloc(clientIdentifier_Bytes ,System.Runtime.InteropServices.GCHandleType.Pinned);var clientIdentifier_buffer_ptr = clientIdentifier_ByteArrayHandle.AddrOfPinnedObject(); +var chunk_table = FlatBuffers.TableUtils.GetTable(chunk);var chunk_length = chunk_table.bb.Length;var chunk_pos = chunk_table.bb_pos;var chunk_seg = chunk_table.bb.ToArraySegment(chunk_pos, chunk_length - chunk_pos);var chunk_managed_array = chunk_seg.Array;var chunk_managed_handle = System.Runtime.InteropServices.GCHandle.Alloc(chunk_managed_array, System.Runtime.InteropServices.GCHandleType.Pinned);var chunk_buffer_ptr = chunk_managed_handle.AddrOfPinnedObject();System.IntPtr chunk_fb_ptr;unsafe { var chunk_buffer_unsafe_ptr = (byte*) chunk_buffer_ptr.ToPointer(); chunk_fb_ptr = (System.IntPtr) (chunk_buffer_unsafe_ptr + chunk_pos);}var chunk_intermediate = new FBIntermediateBuffer();chunk_intermediate.ptr = chunk_fb_ptr; +callback.allocApplicationCallback(); + try { + GrapeshotDriverPINVOKE.InterprocDriver_sendChunk(swigCPtr, clientIdentifier_buffer_ptr, chunk_intermediate, RequestCallback_FunctionApplicationBridgeBase.getCPtr(callback)); + if (GrapeshotDriverPINVOKE.SWIGPendingException.Pending) throw GrapeshotDriverPINVOKE.SWIGPendingException.Retrieve(); + } finally { +clientIdentifier_ByteArrayHandle.Free(); +chunk_managed_handle.Free(); + } + } + + static private global::System.IntPtr SwigConstructInterprocDriver(System.Guid stage, UploadSessionDBAccessor uploadSessionDB) { +var stage_Bytes = stage.ToByteArray();var stage_ByteArrayHandle = System.Runtime.InteropServices.GCHandle.Alloc(stage_Bytes ,System.Runtime.InteropServices.GCHandleType.Pinned);var stage_buffer_ptr = stage_ByteArrayHandle.AddrOfPinnedObject(); + try { + return GrapeshotDriverPINVOKE.new_InterprocDriver(stage_buffer_ptr, UploadSessionDBAccessor.getCPtr(uploadSessionDB)); + } finally { +stage_ByteArrayHandle.Free(); + } + } + + public InterprocDriver(System.Guid stage, UploadSessionDBAccessor uploadSessionDB) : this(InterprocDriver.SwigConstructInterprocDriver(stage, uploadSessionDB), true) { + } + +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/InterprocDriver.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/InterprocDriver.cs.meta new file mode 100644 index 0000000..dc5cf22 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/InterprocDriver.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 35c10d0f69007bd1ddb533d5c1bc794f diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/LocalUploadSessionDBAccessor.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/LocalUploadSessionDBAccessor.cs new file mode 100644 index 0000000..d524669 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/LocalUploadSessionDBAccessor.cs @@ -0,0 +1,49 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public class LocalUploadSessionDBAccessor : UploadSessionDBAccessor { + private global::System.Runtime.InteropServices.HandleRef swigCPtr; + private bool swigCMemOwnDerived; + + internal LocalUploadSessionDBAccessor(global::System.IntPtr cPtr, bool cMemoryOwn) : base(GrapeshotUploadSessionDBAccessorPINVOKE.LocalUploadSessionDBAccessor_SWIGSmartPtrUpcast(cPtr), true) { + swigCMemOwnDerived = cMemoryOwn; + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr); + } + + internal static global::System.Runtime.InteropServices.HandleRef getCPtr(LocalUploadSessionDBAccessor obj) { + return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; + } + + ~LocalUploadSessionDBAccessor() { + Dispose(); + } + + public override void Dispose() { + lock(this) { + if (swigCPtr.Handle != global::System.IntPtr.Zero) { + if (swigCMemOwnDerived) { + swigCMemOwnDerived = false; + GrapeshotUploadSessionDBAccessorPINVOKE.delete_LocalUploadSessionDBAccessor(swigCPtr); + } + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); + } + global::System.GC.SuppressFinalize(this); + base.Dispose(); + } + } + + public LocalUploadSessionDBAccessor() : this(GrapeshotUploadSessionDBAccessorPINVOKE.new_LocalUploadSessionDBAccessor(), true) { + } + +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/LocalUploadSessionDBAccessor.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/LocalUploadSessionDBAccessor.cs.meta new file mode 100644 index 0000000..19b9226 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/LocalUploadSessionDBAccessor.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 2bd85441a730f0981cbd91da83500086 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/MultiRate.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/MultiRate.cs new file mode 100644 index 0000000..6abf89f --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/MultiRate.cs @@ -0,0 +1,87 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public class MultiRate : Rate { + private global::System.Runtime.InteropServices.HandleRef swigCPtr; + private bool swigCMemOwnDerived; + + internal MultiRate(global::System.IntPtr cPtr, bool cMemoryOwn) : base(GrapeshotMultiRatePINVOKE.MultiRate_SWIGSmartPtrUpcast(cPtr), true) { + swigCMemOwnDerived = cMemoryOwn; + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr); + } + + internal static global::System.Runtime.InteropServices.HandleRef getCPtr(MultiRate obj) { + return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; + } + + ~MultiRate() { + Dispose(); + } + + public override void Dispose() { + lock(this) { + if (swigCPtr.Handle != global::System.IntPtr.Zero) { + if (swigCMemOwnDerived) { + swigCMemOwnDerived = false; + GrapeshotMultiRatePINVOKE.delete_MultiRate(swigCPtr); + } + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); + } + global::System.GC.SuppressFinalize(this); + base.Dispose(); + } + } + + public static MultiRate createMultiRate(params Rate[] rates) { + return createMultiRate(new RateVector(rates)); + } + + public override RateTicket claimTicket(ror.schema.upload.UploadChunkRequest chunkRequest) { +var chunkRequest_table = FlatBuffers.TableUtils.GetTable(chunkRequest);var chunkRequest_length = chunkRequest_table.bb.Length;var chunkRequest_pos = chunkRequest_table.bb_pos;var chunkRequest_seg = chunkRequest_table.bb.ToArraySegment(chunkRequest_pos, chunkRequest_length - chunkRequest_pos);var chunkRequest_managed_array = chunkRequest_seg.Array;var chunkRequest_managed_handle = System.Runtime.InteropServices.GCHandle.Alloc(chunkRequest_managed_array, System.Runtime.InteropServices.GCHandleType.Pinned);var chunkRequest_buffer_ptr = chunkRequest_managed_handle.AddrOfPinnedObject();System.IntPtr chunkRequest_fb_ptr;unsafe { var chunkRequest_buffer_unsafe_ptr = (byte*) chunkRequest_buffer_ptr.ToPointer(); chunkRequest_fb_ptr = (System.IntPtr) (chunkRequest_buffer_unsafe_ptr + chunkRequest_pos);}var chunkRequest_intermediate = new FBIntermediateBuffer();chunkRequest_intermediate.ptr = chunkRequest_fb_ptr; + try { + global::System.IntPtr cPtr = GrapeshotMultiRatePINVOKE.MultiRate_claimTicket(swigCPtr, chunkRequest_intermediate); + RateTicket ret = (cPtr == global::System.IntPtr.Zero) ? null : new RateTicket(cPtr, true); + if (GrapeshotMultiRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotMultiRatePINVOKE.SWIGPendingException.Retrieve(); + return ret; + } finally { +chunkRequest_managed_handle.Free(); + } + } + + public override RateTicket tryClaimTicket(ror.schema.upload.UploadChunkRequest chunkRequest) { +var chunkRequest_table = FlatBuffers.TableUtils.GetTable(chunkRequest);var chunkRequest_length = chunkRequest_table.bb.Length;var chunkRequest_pos = chunkRequest_table.bb_pos;var chunkRequest_seg = chunkRequest_table.bb.ToArraySegment(chunkRequest_pos, chunkRequest_length - chunkRequest_pos);var chunkRequest_managed_array = chunkRequest_seg.Array;var chunkRequest_managed_handle = System.Runtime.InteropServices.GCHandle.Alloc(chunkRequest_managed_array, System.Runtime.InteropServices.GCHandleType.Pinned);var chunkRequest_buffer_ptr = chunkRequest_managed_handle.AddrOfPinnedObject();System.IntPtr chunkRequest_fb_ptr;unsafe { var chunkRequest_buffer_unsafe_ptr = (byte*) chunkRequest_buffer_ptr.ToPointer(); chunkRequest_fb_ptr = (System.IntPtr) (chunkRequest_buffer_unsafe_ptr + chunkRequest_pos);}var chunkRequest_intermediate = new FBIntermediateBuffer();chunkRequest_intermediate.ptr = chunkRequest_fb_ptr; + try { + global::System.IntPtr cPtr = GrapeshotMultiRatePINVOKE.MultiRate_tryClaimTicket(swigCPtr, chunkRequest_intermediate); + RateTicket ret = (cPtr == global::System.IntPtr.Zero) ? null : new RateTicket(cPtr, true); + if (GrapeshotMultiRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotMultiRatePINVOKE.SWIGPendingException.Retrieve(); + return ret; + } finally { +chunkRequest_managed_handle.Free(); + } + } + + public override bool areFreeTickets() { + bool ret = GrapeshotMultiRatePINVOKE.MultiRate_areFreeTickets(swigCPtr); + if (GrapeshotMultiRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotMultiRatePINVOKE.SWIGPendingException.Retrieve(); + return ret; + } + + public static MultiRate createMultiRate(RateVector innerRates) { + global::System.IntPtr cPtr = GrapeshotMultiRatePINVOKE.MultiRate_createMultiRate(RateVector.getCPtr(innerRates)); + MultiRate ret = (cPtr == global::System.IntPtr.Zero) ? null : new MultiRate(cPtr, true); + if (GrapeshotMultiRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotMultiRatePINVOKE.SWIGPendingException.Retrieve(); + return ret; + } + +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/MultiRate.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/MultiRate.cs.meta new file mode 100644 index 0000000..16471b8 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/MultiRate.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: c47cee3e7897e3d28e767580e495e22e diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/PendingBytesRate.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/PendingBytesRate.cs new file mode 100644 index 0000000..81809cd --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/PendingBytesRate.cs @@ -0,0 +1,89 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public sealed class PendingBytesRate : Rate { + private global::System.Runtime.InteropServices.HandleRef swigCPtr; + private bool swigCMemOwnDerived; + + internal PendingBytesRate(global::System.IntPtr cPtr, bool cMemoryOwn) : base(GrapeshotRatePINVOKE.PendingBytesRate_SWIGSmartPtrUpcast(cPtr), true) { + swigCMemOwnDerived = cMemoryOwn; + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr); + } + + internal static global::System.Runtime.InteropServices.HandleRef getCPtr(PendingBytesRate obj) { + return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; + } + + ~PendingBytesRate() { + Dispose(); + } + + public override void Dispose() { + lock(this) { + if (swigCPtr.Handle != global::System.IntPtr.Zero) { + if (swigCMemOwnDerived) { + swigCMemOwnDerived = false; + GrapeshotRatePINVOKE.delete_PendingBytesRate(swigCPtr); + } + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); + } + global::System.GC.SuppressFinalize(this); + base.Dispose(); + } + } + + public override void process() { + GrapeshotRatePINVOKE.PendingBytesRate_process(swigCPtr); + if (GrapeshotRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotRatePINVOKE.SWIGPendingException.Retrieve(); + } + + public override RateTicket claimTicket(ror.schema.upload.UploadChunkRequest chunkRequest) { +var chunkRequest_table = FlatBuffers.TableUtils.GetTable(chunkRequest);var chunkRequest_length = chunkRequest_table.bb.Length;var chunkRequest_pos = chunkRequest_table.bb_pos;var chunkRequest_seg = chunkRequest_table.bb.ToArraySegment(chunkRequest_pos, chunkRequest_length - chunkRequest_pos);var chunkRequest_managed_array = chunkRequest_seg.Array;var chunkRequest_managed_handle = System.Runtime.InteropServices.GCHandle.Alloc(chunkRequest_managed_array, System.Runtime.InteropServices.GCHandleType.Pinned);var chunkRequest_buffer_ptr = chunkRequest_managed_handle.AddrOfPinnedObject();System.IntPtr chunkRequest_fb_ptr;unsafe { var chunkRequest_buffer_unsafe_ptr = (byte*) chunkRequest_buffer_ptr.ToPointer(); chunkRequest_fb_ptr = (System.IntPtr) (chunkRequest_buffer_unsafe_ptr + chunkRequest_pos);}var chunkRequest_intermediate = new FBIntermediateBuffer();chunkRequest_intermediate.ptr = chunkRequest_fb_ptr; + try { + global::System.IntPtr cPtr = GrapeshotRatePINVOKE.PendingBytesRate_claimTicket(swigCPtr, chunkRequest_intermediate); + RateTicket ret = (cPtr == global::System.IntPtr.Zero) ? null : new RateTicket(cPtr, true); + if (GrapeshotRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotRatePINVOKE.SWIGPendingException.Retrieve(); + return ret; + } finally { +chunkRequest_managed_handle.Free(); + } + } + + public override RateTicket tryClaimTicket(ror.schema.upload.UploadChunkRequest chunkRequest) { +var chunkRequest_table = FlatBuffers.TableUtils.GetTable(chunkRequest);var chunkRequest_length = chunkRequest_table.bb.Length;var chunkRequest_pos = chunkRequest_table.bb_pos;var chunkRequest_seg = chunkRequest_table.bb.ToArraySegment(chunkRequest_pos, chunkRequest_length - chunkRequest_pos);var chunkRequest_managed_array = chunkRequest_seg.Array;var chunkRequest_managed_handle = System.Runtime.InteropServices.GCHandle.Alloc(chunkRequest_managed_array, System.Runtime.InteropServices.GCHandleType.Pinned);var chunkRequest_buffer_ptr = chunkRequest_managed_handle.AddrOfPinnedObject();System.IntPtr chunkRequest_fb_ptr;unsafe { var chunkRequest_buffer_unsafe_ptr = (byte*) chunkRequest_buffer_ptr.ToPointer(); chunkRequest_fb_ptr = (System.IntPtr) (chunkRequest_buffer_unsafe_ptr + chunkRequest_pos);}var chunkRequest_intermediate = new FBIntermediateBuffer();chunkRequest_intermediate.ptr = chunkRequest_fb_ptr; + try { + global::System.IntPtr cPtr = GrapeshotRatePINVOKE.PendingBytesRate_tryClaimTicket(swigCPtr, chunkRequest_intermediate); + RateTicket ret = (cPtr == global::System.IntPtr.Zero) ? null : new RateTicket(cPtr, true); + if (GrapeshotRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotRatePINVOKE.SWIGPendingException.Retrieve(); + return ret; + } finally { +chunkRequest_managed_handle.Free(); + } + } + + public override bool areFreeTickets() { + bool ret = GrapeshotRatePINVOKE.PendingBytesRate_areFreeTickets(swigCPtr); + if (GrapeshotRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotRatePINVOKE.SWIGPendingException.Retrieve(); + return ret; + } + + public PendingBytesRate(StageNamedInstance stageNamedInstance, long maxAllowedPending) : this(GrapeshotRatePINVOKE.new_PendingBytesRate__SWIG_0(StageNamedInstance.getCPtr(stageNamedInstance), maxAllowedPending), true) { + if (GrapeshotRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotRatePINVOKE.SWIGPendingException.Retrieve(); + } + + public PendingBytesRate(StageNamedInstance stageNamedInstance) : this(GrapeshotRatePINVOKE.new_PendingBytesRate__SWIG_1(StageNamedInstance.getCPtr(stageNamedInstance)), true) { + if (GrapeshotRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotRatePINVOKE.SWIGPendingException.Retrieve(); + } + +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/PendingBytesRate.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/PendingBytesRate.cs.meta new file mode 100644 index 0000000..dc9e5b0 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/PendingBytesRate.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 40b97aad132428b2275236aab1c07376 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RORStage.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RORStage.cs new file mode 100644 index 0000000..837d181 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RORStage.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public class RORStage { +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RORStage.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RORStage.cs.meta new file mode 100644 index 0000000..b16d04e --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RORStage.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 776579b8ea55c5bb5756934d12a74d03 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RORStagePINVOKE.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RORStagePINVOKE.cs new file mode 100644 index 0000000..2c30e28 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RORStagePINVOKE.cs @@ -0,0 +1,289 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +class RORStagePINVOKE { + + /// For Mono AOT platforms compatibility + /// This attribute can be defined in any assembly for Mono AOT to use it. + public class MonoPInvokeCallbackAttribute : global::System.Attribute { + public MonoPInvokeCallbackAttribute(global::System.Type t) { + } + } + + + protected class SWIGExceptionHelper { + public delegate void ExceptionDelegate(string message); + public delegate void ExceptionArgumentDelegate(string message, string paramName); + + static ExceptionDelegate applicationDelegate = new ExceptionDelegate(SetPendingApplicationException); + static ExceptionDelegate arithmeticDelegate = new ExceptionDelegate(SetPendingArithmeticException); + static ExceptionDelegate divideByZeroDelegate = new ExceptionDelegate(SetPendingDivideByZeroException); + static ExceptionDelegate indexOutOfRangeDelegate = new ExceptionDelegate(SetPendingIndexOutOfRangeException); + static ExceptionDelegate invalidCastDelegate = new ExceptionDelegate(SetPendingInvalidCastException); + static ExceptionDelegate invalidOperationDelegate = new ExceptionDelegate(SetPendingInvalidOperationException); + static ExceptionDelegate ioDelegate = new ExceptionDelegate(SetPendingIOException); + static ExceptionDelegate nullReferenceDelegate = new ExceptionDelegate(SetPendingNullReferenceException); + static ExceptionDelegate outOfMemoryDelegate = new ExceptionDelegate(SetPendingOutOfMemoryException); + static ExceptionDelegate overflowDelegate = new ExceptionDelegate(SetPendingOverflowException); + static ExceptionDelegate systemDelegate = new ExceptionDelegate(SetPendingSystemException); + + static ExceptionArgumentDelegate argumentDelegate = new ExceptionArgumentDelegate(SetPendingArgumentException); + static ExceptionArgumentDelegate argumentNullDelegate = new ExceptionArgumentDelegate(SetPendingArgumentNullException); + static ExceptionArgumentDelegate argumentOutOfRangeDelegate = new ExceptionArgumentDelegate(SetPendingArgumentOutOfRangeException); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="SWIGRegisterExceptionCallbacks_RORStage")] + public static extern void SWIGRegisterExceptionCallbacks_RORStage( + ExceptionDelegate applicationDelegate, + ExceptionDelegate arithmeticDelegate, + ExceptionDelegate divideByZeroDelegate, + ExceptionDelegate indexOutOfRangeDelegate, + ExceptionDelegate invalidCastDelegate, + ExceptionDelegate invalidOperationDelegate, + ExceptionDelegate ioDelegate, + ExceptionDelegate nullReferenceDelegate, + ExceptionDelegate outOfMemoryDelegate, + ExceptionDelegate overflowDelegate, + ExceptionDelegate systemExceptionDelegate); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="SWIGRegisterExceptionArgumentCallbacks_RORStage")] + public static extern void SWIGRegisterExceptionCallbacksArgument_RORStage( + ExceptionArgumentDelegate argumentDelegate, + ExceptionArgumentDelegate argumentNullDelegate, + ExceptionArgumentDelegate argumentOutOfRangeDelegate); + + + [RORStagePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingApplicationException(string message) { + SWIGPendingException.Set(new global::System.ApplicationException(message, SWIGPendingException.Retrieve())); + } + + + + [RORStagePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingArithmeticException(string message) { + SWIGPendingException.Set(new global::System.ArithmeticException(message, SWIGPendingException.Retrieve())); + } + + + + [RORStagePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingDivideByZeroException(string message) { + SWIGPendingException.Set(new global::System.DivideByZeroException(message, SWIGPendingException.Retrieve())); + } + + + + [RORStagePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingIndexOutOfRangeException(string message) { + SWIGPendingException.Set(new global::System.IndexOutOfRangeException(message, SWIGPendingException.Retrieve())); + } + + + + [RORStagePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingInvalidCastException(string message) { + SWIGPendingException.Set(new global::System.InvalidCastException(message, SWIGPendingException.Retrieve())); + } + + + + [RORStagePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingInvalidOperationException(string message) { + SWIGPendingException.Set(new global::System.InvalidOperationException(message, SWIGPendingException.Retrieve())); + } + + + + [RORStagePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingIOException(string message) { + SWIGPendingException.Set(new global::System.IO.IOException(message, SWIGPendingException.Retrieve())); + } + + + + [RORStagePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingNullReferenceException(string message) { + SWIGPendingException.Set(new global::System.NullReferenceException(message, SWIGPendingException.Retrieve())); + } + + + + [RORStagePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingOutOfMemoryException(string message) { + SWIGPendingException.Set(new global::System.OutOfMemoryException(message, SWIGPendingException.Retrieve())); + } + + + + [RORStagePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingOverflowException(string message) { + SWIGPendingException.Set(new global::System.OverflowException(message, SWIGPendingException.Retrieve())); + } + + + + [RORStagePINVOKE.MonoPInvokeCallback(typeof(ExceptionDelegate))] + + + static void SetPendingSystemException(string message) { + SWIGPendingException.Set(new global::System.SystemException(message, SWIGPendingException.Retrieve())); + } + + + + [RORStagePINVOKE.MonoPInvokeCallback(typeof(ExceptionArgumentDelegate))] + + + static void SetPendingArgumentException(string message, string paramName) { + SWIGPendingException.Set(new global::System.ArgumentException(message, paramName, SWIGPendingException.Retrieve())); + } + + + + [RORStagePINVOKE.MonoPInvokeCallback(typeof(ExceptionArgumentDelegate))] + + + static void SetPendingArgumentNullException(string message, string paramName) { + global::System.Exception e = SWIGPendingException.Retrieve(); + if (e != null) message = message + " Inner Exception: " + e.Message; + SWIGPendingException.Set(new global::System.ArgumentNullException(paramName, message)); + } + + + + [RORStagePINVOKE.MonoPInvokeCallback(typeof(ExceptionArgumentDelegate))] + + + static void SetPendingArgumentOutOfRangeException(string message, string paramName) { + global::System.Exception e = SWIGPendingException.Retrieve(); + if (e != null) message = message + " Inner Exception: " + e.Message; + SWIGPendingException.Set(new global::System.ArgumentOutOfRangeException(paramName, message)); + } + + static SWIGExceptionHelper() { + SWIGRegisterExceptionCallbacks_RORStage( + applicationDelegate, + arithmeticDelegate, + divideByZeroDelegate, + indexOutOfRangeDelegate, + invalidCastDelegate, + invalidOperationDelegate, + ioDelegate, + nullReferenceDelegate, + outOfMemoryDelegate, + overflowDelegate, + systemDelegate); + + SWIGRegisterExceptionCallbacksArgument_RORStage( + argumentDelegate, + argumentNullDelegate, + argumentOutOfRangeDelegate); + } + } + + protected static SWIGExceptionHelper swigExceptionHelper = new SWIGExceptionHelper(); + + public class SWIGPendingException { + [global::System.ThreadStatic] + private static global::System.Exception pendingException = null; + private static int numExceptionsPending = 0; + + public static bool Pending { + get { + bool pending = false; + if (numExceptionsPending > 0) + if (pendingException != null) + pending = true; + return pending; + } + } + + public static void Set(global::System.Exception e) { + if (pendingException != null) + throw new global::System.ApplicationException("FATAL: An earlier pending exception from unmanaged code was missed and thus not thrown (" + pendingException.ToString() + ")", e); + pendingException = e; + lock(typeof(RORStagePINVOKE)) { + numExceptionsPending++; + } + } + + public static global::System.Exception Retrieve() { + global::System.Exception e = null; + if (numExceptionsPending > 0) { + if (pendingException != null) { + e = pendingException; + pendingException = null; + lock(typeof(RORStagePINVOKE)) { + numExceptionsPending--; + } + } + } + return e; + } + } + + + protected class SWIGStringHelper { + public delegate string SWIGStringDelegate(string message); + static SWIGStringDelegate stringDelegate = new SWIGStringDelegate(CreateString); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="SWIGRegisterStringCallback_RORStage")] + public static extern void SWIGRegisterStringCallback_RORStage(SWIGStringDelegate stringDelegate); + + + [RORStagePINVOKE.MonoPInvokeCallback(typeof(SWIGStringDelegate))] + + + static string CreateString(string cString) { + return cString; + } + + static SWIGStringHelper() { + SWIGRegisterStringCallback_RORStage(stringDelegate); + } + } + + static protected SWIGStringHelper swigStringHelper = new SWIGStringHelper(); + + + static RORStagePINVOKE() { + } + + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_new_StageNamedInstance")] + public static extern global::System.IntPtr new_StageNamedInstance(System.IntPtr jarg1, string jarg2); + + [global::System.Runtime.InteropServices.DllImport(Grapeshot.LibraryHelper.libraryName, EntryPoint="CSharp_Grapeshot_delete_StageNamedInstance")] + public static extern void delete_StageNamedInstance(global::System.Runtime.InteropServices.HandleRef jarg1); +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RORStagePINVOKE.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RORStagePINVOKE.cs.meta new file mode 100644 index 0000000..62137a9 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RORStagePINVOKE.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 1f5a7f2db6ada00756e662c85ca40ce2 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/Rate.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/Rate.cs new file mode 100644 index 0000000..d898dd5 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/Rate.cs @@ -0,0 +1,80 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public class Rate : global::System.IDisposable { + private global::System.Runtime.InteropServices.HandleRef swigCPtr; + private bool swigCMemOwnBase; + + internal Rate(global::System.IntPtr cPtr, bool cMemoryOwn) { + swigCMemOwnBase = cMemoryOwn; + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr); + } + + internal static global::System.Runtime.InteropServices.HandleRef getCPtr(Rate obj) { + return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; + } + + ~Rate() { + Dispose(); + } + + public virtual void Dispose() { + lock(this) { + if (swigCPtr.Handle != global::System.IntPtr.Zero) { + if (swigCMemOwnBase) { + swigCMemOwnBase = false; + GrapeshotRatePINVOKE.delete_Rate(swigCPtr); + } + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); + } + global::System.GC.SuppressFinalize(this); + } + } + + public virtual void process() { + GrapeshotRatePINVOKE.Rate_process(swigCPtr); + if (GrapeshotRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotRatePINVOKE.SWIGPendingException.Retrieve(); + } + + public virtual RateTicket claimTicket(ror.schema.upload.UploadChunkRequest chunkRequest) { +var chunkRequest_table = FlatBuffers.TableUtils.GetTable(chunkRequest);var chunkRequest_length = chunkRequest_table.bb.Length;var chunkRequest_pos = chunkRequest_table.bb_pos;var chunkRequest_seg = chunkRequest_table.bb.ToArraySegment(chunkRequest_pos, chunkRequest_length - chunkRequest_pos);var chunkRequest_managed_array = chunkRequest_seg.Array;var chunkRequest_managed_handle = System.Runtime.InteropServices.GCHandle.Alloc(chunkRequest_managed_array, System.Runtime.InteropServices.GCHandleType.Pinned);var chunkRequest_buffer_ptr = chunkRequest_managed_handle.AddrOfPinnedObject();System.IntPtr chunkRequest_fb_ptr;unsafe { var chunkRequest_buffer_unsafe_ptr = (byte*) chunkRequest_buffer_ptr.ToPointer(); chunkRequest_fb_ptr = (System.IntPtr) (chunkRequest_buffer_unsafe_ptr + chunkRequest_pos);}var chunkRequest_intermediate = new FBIntermediateBuffer();chunkRequest_intermediate.ptr = chunkRequest_fb_ptr; + try { + global::System.IntPtr cPtr = GrapeshotRatePINVOKE.Rate_claimTicket(swigCPtr, chunkRequest_intermediate); + RateTicket ret = (cPtr == global::System.IntPtr.Zero) ? null : new RateTicket(cPtr, true); + if (GrapeshotRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotRatePINVOKE.SWIGPendingException.Retrieve(); + return ret; + } finally { +chunkRequest_managed_handle.Free(); + } + } + + public virtual RateTicket tryClaimTicket(ror.schema.upload.UploadChunkRequest chunkRequest) { +var chunkRequest_table = FlatBuffers.TableUtils.GetTable(chunkRequest);var chunkRequest_length = chunkRequest_table.bb.Length;var chunkRequest_pos = chunkRequest_table.bb_pos;var chunkRequest_seg = chunkRequest_table.bb.ToArraySegment(chunkRequest_pos, chunkRequest_length - chunkRequest_pos);var chunkRequest_managed_array = chunkRequest_seg.Array;var chunkRequest_managed_handle = System.Runtime.InteropServices.GCHandle.Alloc(chunkRequest_managed_array, System.Runtime.InteropServices.GCHandleType.Pinned);var chunkRequest_buffer_ptr = chunkRequest_managed_handle.AddrOfPinnedObject();System.IntPtr chunkRequest_fb_ptr;unsafe { var chunkRequest_buffer_unsafe_ptr = (byte*) chunkRequest_buffer_ptr.ToPointer(); chunkRequest_fb_ptr = (System.IntPtr) (chunkRequest_buffer_unsafe_ptr + chunkRequest_pos);}var chunkRequest_intermediate = new FBIntermediateBuffer();chunkRequest_intermediate.ptr = chunkRequest_fb_ptr; + try { + global::System.IntPtr cPtr = GrapeshotRatePINVOKE.Rate_tryClaimTicket(swigCPtr, chunkRequest_intermediate); + RateTicket ret = (cPtr == global::System.IntPtr.Zero) ? null : new RateTicket(cPtr, true); + if (GrapeshotRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotRatePINVOKE.SWIGPendingException.Retrieve(); + return ret; + } finally { +chunkRequest_managed_handle.Free(); + } + } + + public virtual bool areFreeTickets() { + bool ret = GrapeshotRatePINVOKE.Rate_areFreeTickets(swigCPtr); + if (GrapeshotRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotRatePINVOKE.SWIGPendingException.Retrieve(); + return ret; + } + +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/Rate.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/Rate.cs.meta new file mode 100644 index 0000000..2fe2419 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/Rate.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: b348a374eb34748c2442256b42406270 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RateTicket.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RateTicket.cs new file mode 100644 index 0000000..4bd918f --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RateTicket.cs @@ -0,0 +1,48 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public class RateTicket : global::System.IDisposable { + private global::System.Runtime.InteropServices.HandleRef swigCPtr; + private bool swigCMemOwnBase; + + internal RateTicket(global::System.IntPtr cPtr, bool cMemoryOwn) { + swigCMemOwnBase = cMemoryOwn; + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr); + } + + internal static global::System.Runtime.InteropServices.HandleRef getCPtr(RateTicket obj) { + return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; + } + + ~RateTicket() { + Dispose(); + } + + public virtual void Dispose() { + lock(this) { + if (swigCPtr.Handle != global::System.IntPtr.Zero) { + if (swigCMemOwnBase) { + swigCMemOwnBase = false; + GrapeshotRatePINVOKE.delete_RateTicket(swigCPtr); + } + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); + } + global::System.GC.SuppressFinalize(this); + } + } + + public RateTicket() : this(GrapeshotRatePINVOKE.new_RateTicket(), true) { + } + +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RateTicket.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RateTicket.cs.meta new file mode 100644 index 0000000..cae3210 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RateTicket.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: eebbbc8c26f187676481359c01dcb1b5 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RateTicketReturn.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RateTicketReturn.cs new file mode 100644 index 0000000..1beb0e1 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RateTicketReturn.cs @@ -0,0 +1,52 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public class RateTicketReturn : global::System.IDisposable { + private global::System.Runtime.InteropServices.HandleRef swigCPtr; + protected bool swigCMemOwn; + + internal RateTicketReturn(global::System.IntPtr cPtr, bool cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr); + } + + internal static global::System.Runtime.InteropServices.HandleRef getCPtr(RateTicketReturn obj) { + return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; + } + + ~RateTicketReturn() { + Dispose(); + } + + public virtual void Dispose() { + lock(this) { + if (swigCPtr.Handle != global::System.IntPtr.Zero) { + if (swigCMemOwn) { + swigCMemOwn = false; + GrapeshotApplicationRatePINVOKE.delete_RateTicketReturn(swigCPtr); + } + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); + } + global::System.GC.SuppressFinalize(this); + } + } + + public void ret(RateTicket ticket) { + GrapeshotApplicationRatePINVOKE.RateTicketReturn_ret(swigCPtr, RateTicket.getCPtr(ticket)); + } + + public RateTicketReturn() : this(GrapeshotApplicationRatePINVOKE.new_RateTicketReturn(), true) { + } + +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RateTicketReturn.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RateTicketReturn.cs.meta new file mode 100644 index 0000000..e9f615d --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RateTicketReturn.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 2746bdb7da5231d4500a3117c3277e7a diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RateVector.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RateVector.cs new file mode 100644 index 0000000..0707f0c --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RateVector.cs @@ -0,0 +1,325 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public class RateVector : global::System.IDisposable, global::System.Collections.IEnumerable + , global::System.Collections.Generic.IEnumerable + { + private global::System.Runtime.InteropServices.HandleRef swigCPtr; + protected bool swigCMemOwn; + + internal RateVector(global::System.IntPtr cPtr, bool cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr); + } + + internal static global::System.Runtime.InteropServices.HandleRef getCPtr(RateVector obj) { + return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; + } + + ~RateVector() { + Dispose(); + } + + public virtual void Dispose() { + lock(this) { + if (swigCPtr.Handle != global::System.IntPtr.Zero) { + if (swigCMemOwn) { + swigCMemOwn = false; + GrapeshotMultiRatePINVOKE.delete_RateVector(swigCPtr); + } + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); + } + global::System.GC.SuppressFinalize(this); + } + } + + public RateVector(global::System.Collections.IEnumerable c) : this() { + if (c == null) + throw new global::System.ArgumentNullException("c"); + foreach (Rate element in c) { + this.Add(element); + } + } + + public RateVector(global::System.Collections.Generic.IEnumerable c) : this() { + if (c == null) + throw new global::System.ArgumentNullException("c"); + foreach (Rate element in c) { + this.Add(element); + } + } + + public bool IsFixedSize { + get { + return false; + } + } + + public bool IsReadOnly { + get { + return false; + } + } + + public Rate this[int index] { + get { + return getitem(index); + } + set { + setitem(index, value); + } + } + + public int Capacity { + get { + return (int)capacity(); + } + set { + if (value < size()) + throw new global::System.ArgumentOutOfRangeException("Capacity"); + reserve((uint)value); + } + } + + public int Count { + get { + return (int)size(); + } + } + + public bool IsSynchronized { + get { + return false; + } + } + + public void CopyTo(Rate[] array) + { + CopyTo(0, array, 0, this.Count); + } + + public void CopyTo(Rate[] array, int arrayIndex) + { + CopyTo(0, array, arrayIndex, this.Count); + } + + public void CopyTo(int index, Rate[] array, int arrayIndex, int count) + { + if (array == null) + throw new global::System.ArgumentNullException("array"); + if (index < 0) + throw new global::System.ArgumentOutOfRangeException("index", "Value is less than zero"); + if (arrayIndex < 0) + throw new global::System.ArgumentOutOfRangeException("arrayIndex", "Value is less than zero"); + if (count < 0) + throw new global::System.ArgumentOutOfRangeException("count", "Value is less than zero"); + if (array.Rank > 1) + throw new global::System.ArgumentException("Multi dimensional array.", "array"); + if (index+count > this.Count || arrayIndex+count > array.Length) + throw new global::System.ArgumentException("Number of elements to copy is too large."); + for (int i=0; i global::System.Collections.Generic.IEnumerable.GetEnumerator() { + return new RateVectorEnumerator(this); + } + + global::System.Collections.IEnumerator global::System.Collections.IEnumerable.GetEnumerator() { + return new RateVectorEnumerator(this); + } + + public RateVectorEnumerator GetEnumerator() { + return new RateVectorEnumerator(this); + } + + // Type-safe enumerator + /// Note that the IEnumerator documentation requires an InvalidOperationException to be thrown + /// whenever the collection is modified. This has been done for changes in the size of the + /// collection but not when one of the elements of the collection is modified as it is a bit + /// tricky to detect unmanaged code that modifies the collection under our feet. + public sealed class RateVectorEnumerator : global::System.Collections.IEnumerator + , global::System.Collections.Generic.IEnumerator + { + private RateVector collectionRef; + private int currentIndex; + private object currentObject; + private int currentSize; + + public RateVectorEnumerator(RateVector collection) { + collectionRef = collection; + currentIndex = -1; + currentObject = null; + currentSize = collectionRef.Count; + } + + // Type-safe iterator Current + public Rate Current { + get { + if (currentIndex == -1) + throw new global::System.InvalidOperationException("Enumeration not started."); + if (currentIndex > currentSize - 1) + throw new global::System.InvalidOperationException("Enumeration finished."); + if (currentObject == null) + throw new global::System.InvalidOperationException("Collection modified."); + return (Rate)currentObject; + } + } + + // Type-unsafe IEnumerator.Current + object global::System.Collections.IEnumerator.Current { + get { + return Current; + } + } + + public bool MoveNext() { + int size = collectionRef.Count; + bool moveOkay = (currentIndex+1 < size) && (size == currentSize); + if (moveOkay) { + currentIndex++; + currentObject = collectionRef[currentIndex]; + } else { + currentObject = null; + } + return moveOkay; + } + + public void Reset() { + currentIndex = -1; + currentObject = null; + if (collectionRef.Count != currentSize) { + throw new global::System.InvalidOperationException("Collection modified."); + } + } + + public void Dispose() { + currentIndex = -1; + currentObject = null; + } + } + + public void Clear() { + GrapeshotMultiRatePINVOKE.RateVector_Clear(swigCPtr); + } + + public void Add(Rate x) { + GrapeshotMultiRatePINVOKE.RateVector_Add(swigCPtr, Rate.getCPtr(x)); + if (GrapeshotMultiRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotMultiRatePINVOKE.SWIGPendingException.Retrieve(); + } + + private uint size() { + uint ret = GrapeshotMultiRatePINVOKE.RateVector_size(swigCPtr); + return ret; + } + + private uint capacity() { + uint ret = GrapeshotMultiRatePINVOKE.RateVector_capacity(swigCPtr); + return ret; + } + + private void reserve(uint n) { + GrapeshotMultiRatePINVOKE.RateVector_reserve(swigCPtr, n); + } + + public RateVector() : this(GrapeshotMultiRatePINVOKE.new_RateVector__SWIG_0(), true) { + } + + public RateVector(RateVector other) : this(GrapeshotMultiRatePINVOKE.new_RateVector__SWIG_1(RateVector.getCPtr(other)), true) { + if (GrapeshotMultiRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotMultiRatePINVOKE.SWIGPendingException.Retrieve(); + } + + public RateVector(int capacity) : this(GrapeshotMultiRatePINVOKE.new_RateVector__SWIG_2(capacity), true) { + if (GrapeshotMultiRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotMultiRatePINVOKE.SWIGPendingException.Retrieve(); + } + + private Rate getitemcopy(int index) { + global::System.IntPtr cPtr = GrapeshotMultiRatePINVOKE.RateVector_getitemcopy(swigCPtr, index); + Rate ret = (cPtr == global::System.IntPtr.Zero) ? null : new Rate(cPtr, true); + if (GrapeshotMultiRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotMultiRatePINVOKE.SWIGPendingException.Retrieve(); + return ret; + } + + private Rate getitem(int index) { + global::System.IntPtr cPtr = GrapeshotMultiRatePINVOKE.RateVector_getitem(swigCPtr, index); + Rate ret = (cPtr == global::System.IntPtr.Zero) ? null : new Rate(cPtr, true); + if (GrapeshotMultiRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotMultiRatePINVOKE.SWIGPendingException.Retrieve(); + return ret; + } + + private void setitem(int index, Rate value) { + GrapeshotMultiRatePINVOKE.RateVector_setitem(swigCPtr, index, Rate.getCPtr(value)); + if (GrapeshotMultiRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotMultiRatePINVOKE.SWIGPendingException.Retrieve(); + } + + public void AddRange(RateVector values) { + GrapeshotMultiRatePINVOKE.RateVector_AddRange(swigCPtr, RateVector.getCPtr(values)); + if (GrapeshotMultiRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotMultiRatePINVOKE.SWIGPendingException.Retrieve(); + } + + public RateVector GetRange(int index, int count) { + global::System.IntPtr cPtr = GrapeshotMultiRatePINVOKE.RateVector_GetRange(swigCPtr, index, count); + RateVector ret = (cPtr == global::System.IntPtr.Zero) ? null : new RateVector(cPtr, true); + if (GrapeshotMultiRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotMultiRatePINVOKE.SWIGPendingException.Retrieve(); + return ret; + } + + public void Insert(int index, Rate x) { + GrapeshotMultiRatePINVOKE.RateVector_Insert(swigCPtr, index, Rate.getCPtr(x)); + if (GrapeshotMultiRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotMultiRatePINVOKE.SWIGPendingException.Retrieve(); + } + + public void InsertRange(int index, RateVector values) { + GrapeshotMultiRatePINVOKE.RateVector_InsertRange(swigCPtr, index, RateVector.getCPtr(values)); + if (GrapeshotMultiRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotMultiRatePINVOKE.SWIGPendingException.Retrieve(); + } + + public void RemoveAt(int index) { + GrapeshotMultiRatePINVOKE.RateVector_RemoveAt(swigCPtr, index); + if (GrapeshotMultiRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotMultiRatePINVOKE.SWIGPendingException.Retrieve(); + } + + public void RemoveRange(int index, int count) { + GrapeshotMultiRatePINVOKE.RateVector_RemoveRange(swigCPtr, index, count); + if (GrapeshotMultiRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotMultiRatePINVOKE.SWIGPendingException.Retrieve(); + } + + public static RateVector Repeat(Rate value, int count) { + global::System.IntPtr cPtr = GrapeshotMultiRatePINVOKE.RateVector_Repeat(Rate.getCPtr(value), count); + RateVector ret = (cPtr == global::System.IntPtr.Zero) ? null : new RateVector(cPtr, true); + if (GrapeshotMultiRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotMultiRatePINVOKE.SWIGPendingException.Retrieve(); + return ret; + } + + public void Reverse() { + GrapeshotMultiRatePINVOKE.RateVector_Reverse__SWIG_0(swigCPtr); + } + + public void Reverse(int index, int count) { + GrapeshotMultiRatePINVOKE.RateVector_Reverse__SWIG_1(swigCPtr, index, count); + if (GrapeshotMultiRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotMultiRatePINVOKE.SWIGPendingException.Retrieve(); + } + + public void SetRange(int index, RateVector values) { + GrapeshotMultiRatePINVOKE.RateVector_SetRange(swigCPtr, index, RateVector.getCPtr(values)); + if (GrapeshotMultiRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotMultiRatePINVOKE.SWIGPendingException.Retrieve(); + } + +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RateVector.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RateVector.cs.meta new file mode 100644 index 0000000..6e1bb5b --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RateVector.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 6cabff3f4141c0ca0f5a87994a18fa01 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RequestCallback_FunctionApplicationBridge.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RequestCallback_FunctionApplicationBridge.cs new file mode 100644 index 0000000..a14ecd0 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RequestCallback_FunctionApplicationBridge.cs @@ -0,0 +1,36 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public sealed class RequestCallback_FunctionApplicationBridge : RequestCallback_FunctionApplicationBridgeBase { + public delegate void Delegate(ror.schema.upload.UploadChunkResponse arg); + + private Delegate _delegate; + + public RequestCallback_FunctionApplicationBridge(Delegate d) : base() { + _delegate = d; + } + + public override void releaseApplicationCallback() { + // This doesn't do anything except update reflection info so that the director thinks it needs + // to call this. + base.releaseApplicationCallback(); + } + + public override void invokeApplicationLogic(ror.schema.upload.UploadChunkResponse arg) { + try { + _delegate(arg); + } catch {} + } + +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RequestCallback_FunctionApplicationBridge.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RequestCallback_FunctionApplicationBridge.cs.meta new file mode 100644 index 0000000..d93875d --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RequestCallback_FunctionApplicationBridge.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 88a954fc3f99d21b64f1e0e31d119be9 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RequestCallback_FunctionApplicationBridgeBase.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RequestCallback_FunctionApplicationBridgeBase.cs new file mode 100644 index 0000000..44ed4a0 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RequestCallback_FunctionApplicationBridgeBase.cs @@ -0,0 +1,157 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public abstract class RequestCallback_FunctionApplicationBridgeBase : global::System.IDisposable { + /** DO NOT REMOVE THE FOLLOWING COMMENT **/ + /** THIS HAS BEEN SWIG CORRECTED: JJDKFJSIIIIDKJ **/ + private global::System.Runtime.InteropServices.GCHandle _swigDelegateHandle1; + private global::System.Runtime.InteropServices.GCHandle _swigDelegateHandle0; + private global::System.Runtime.InteropServices.HandleRef swigCPtr; + protected bool swigCMemOwn; + + internal RequestCallback_FunctionApplicationBridgeBase(global::System.IntPtr cPtr, bool cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr); + } + + internal static global::System.Runtime.InteropServices.HandleRef getCPtr(RequestCallback_FunctionApplicationBridgeBase obj) { + return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; + } + + ~RequestCallback_FunctionApplicationBridgeBase() { + Dispose(); + } + + public virtual void Dispose() { + lock(this) { + if (swigCPtr.Handle != global::System.IntPtr.Zero) { + if (swigCMemOwn) { + swigCMemOwn = false; + GrapeshotDriverPINVOKE.delete_RequestCallback_FunctionApplicationBridgeBase(swigCPtr); + } + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); + } + global::System.GC.SuppressFinalize(this); + _swigDelegateHandle0.Free(); + _swigDelegateHandle1.Free(); + } + } + + // Information used to prevent pre-mature GC of callbacks still being used from C++. + private ulong _refCount; + private System.Runtime.InteropServices.GCHandle _handle; + + /// Allocates a reference to this application callback so that it can't be released from memory + /// until all allocs have been meet with an equal number of releaseApplicationCallback. + public void allocApplicationCallback() { + lock(this) { + if (_refCount == 0) { + _handle = System.Runtime.InteropServices.GCHandle.Alloc(this); + } + + _refCount++; + } + } + + public virtual void invokeApplicationLogic(ror.schema.upload.UploadChunkResponse RequestCallback_arg) { throw new System.NotImplementedException(); } + + public virtual void releaseApplicationCallback() { + // When releasing the application side callback, this means that one of the native side holds + // was terminated, thus cs should remove a reference count, once that count is zero free the + // handle. + lock(this) { + if (_refCount <= 0) { + return; + } + + _refCount -= 1; + + if (_refCount <= 0) { + _handle.Free(); + } + } + } + + + public RequestCallback_FunctionApplicationBridgeBase() : this(GrapeshotDriverPINVOKE.new_RequestCallback_FunctionApplicationBridgeBase(), true) { + SwigDirectorConnect(); + } + + private void SwigDirectorConnect() { + global::System.IntPtr swigDelegate0gcHandlePtr = global::System.IntPtr.Zero; + if (SwigDerivedClassHasMethod("invokeApplicationLogic", swigMethodTypes0)) { + swigDelegate0 = new SwigDelegateRequestCallback_FunctionApplicationBridgeBase_0(SwigDirectorinvokeApplicationLogic); + swigDelegate0dispatcher = new SwigDelegateRequestCallback_FunctionApplicationBridgeBase_0_Dispatcher(SwigDirectorinvokeApplicationLogic_Dispatcher); + + global::System.Runtime.InteropServices.GCHandle swigDelegate0gcHandle = global::System.Runtime.InteropServices.GCHandle.Alloc(swigDelegate0, global::System.Runtime.InteropServices.GCHandleType.Normal); + _swigDelegateHandle0 = swigDelegate0gcHandle; + swigDelegate0gcHandlePtr = global::System.Runtime.InteropServices.GCHandle.ToIntPtr(swigDelegate0gcHandle); + } + global::System.IntPtr swigDelegate1gcHandlePtr = global::System.IntPtr.Zero; + if (SwigDerivedClassHasMethod("releaseApplicationCallback", swigMethodTypes1)) { + swigDelegate1 = new SwigDelegateRequestCallback_FunctionApplicationBridgeBase_1(SwigDirectorreleaseApplicationCallback); + swigDelegate1dispatcher = new SwigDelegateRequestCallback_FunctionApplicationBridgeBase_1_Dispatcher(SwigDirectorreleaseApplicationCallback_Dispatcher); + + global::System.Runtime.InteropServices.GCHandle swigDelegate1gcHandle = global::System.Runtime.InteropServices.GCHandle.Alloc(swigDelegate1, global::System.Runtime.InteropServices.GCHandleType.Normal); + _swigDelegateHandle1 = swigDelegate1gcHandle; + swigDelegate1gcHandlePtr = global::System.Runtime.InteropServices.GCHandle.ToIntPtr(swigDelegate1gcHandle); + } + GrapeshotDriverPINVOKE.RequestCallback_FunctionApplicationBridgeBase_director_connect(swigCPtr, swigDelegate0dispatcher, swigDelegate0gcHandlePtr, swigDelegate1dispatcher, swigDelegate1gcHandlePtr); + } + + private bool SwigDerivedClassHasMethod(string methodName, global::System.Type[] methodTypes) { + global::System.Reflection.MethodInfo methodInfo = this.GetType().GetMethod(methodName, global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance, null, methodTypes, null); + bool hasDerivedMethod = methodInfo.DeclaringType.IsSubclassOf(typeof(RequestCallback_FunctionApplicationBridgeBase)); + return hasDerivedMethod; + } + + private void SwigDirectorinvokeApplicationLogic(FBIntermediateBuffer RequestCallback_arg) { +var RequestCallback_arg_buffer = new byte[RequestCallback_arg.size];UnityEngine.Assertions.Assert.AreNotEqual(RequestCallback_arg.size, (ulong) 0);System.Runtime.InteropServices.Marshal.Copy(RequestCallback_arg.ptr, RequestCallback_arg_buffer, 0, (int) RequestCallback_arg.size);var RequestCallback_arg_bb = new FlatBuffers.ByteBuffer(RequestCallback_arg_buffer);var RequestCallback_arg_fb = new ror.schema.upload.UploadChunkResponse();RequestCallback_arg_fb.__assign(RequestCallback_arg_bb.GetInt(RequestCallback_arg_bb.Position) + RequestCallback_arg_bb.Position, RequestCallback_arg_bb); + invokeApplicationLogic(RequestCallback_arg_fb); + } + + [GrapeshotDriverPINVOKE.MonoPInvokeCallback(typeof(SwigDelegateRequestCallback_FunctionApplicationBridgeBase_0_Dispatcher))] + private static void SwigDirectorinvokeApplicationLogic_Dispatcher(global::System.IntPtr swigDelegateRequestCallback_FunctionApplicationBridgeBase_0_Handle, FBIntermediateBuffer RequestCallback_arg) { +var RequestCallback_arg_buffer = new byte[RequestCallback_arg.size];UnityEngine.Assertions.Assert.AreNotEqual(RequestCallback_arg.size, (ulong) 0);System.Runtime.InteropServices.Marshal.Copy(RequestCallback_arg.ptr, RequestCallback_arg_buffer, 0, (int) RequestCallback_arg.size);var RequestCallback_arg_bb = new FlatBuffers.ByteBuffer(RequestCallback_arg_buffer);var RequestCallback_arg_fb = new ror.schema.upload.UploadChunkResponse();RequestCallback_arg_fb.__assign(RequestCallback_arg_bb.GetInt(RequestCallback_arg_bb.Position) + RequestCallback_arg_bb.Position, RequestCallback_arg_bb); + global::System.Runtime.InteropServices.GCHandle gcHandle = global::System.Runtime.InteropServices.GCHandle.FromIntPtr(swigDelegateRequestCallback_FunctionApplicationBridgeBase_0_Handle); + SwigDelegateRequestCallback_FunctionApplicationBridgeBase_0 delegateSwigDelegateRequestCallback_FunctionApplicationBridgeBase_0 = (SwigDelegateRequestCallback_FunctionApplicationBridgeBase_0) gcHandle.Target; +delegateSwigDelegateRequestCallback_FunctionApplicationBridgeBase_0(RequestCallback_arg); + } + + private void SwigDirectorreleaseApplicationCallback() { + releaseApplicationCallback(); + } + + [GrapeshotDriverPINVOKE.MonoPInvokeCallback(typeof(SwigDelegateRequestCallback_FunctionApplicationBridgeBase_1_Dispatcher))] + private static void SwigDirectorreleaseApplicationCallback_Dispatcher(global::System.IntPtr swigDelegateRequestCallback_FunctionApplicationBridgeBase_1_Handle) { + global::System.Runtime.InteropServices.GCHandle gcHandle = global::System.Runtime.InteropServices.GCHandle.FromIntPtr(swigDelegateRequestCallback_FunctionApplicationBridgeBase_1_Handle); + SwigDelegateRequestCallback_FunctionApplicationBridgeBase_1 delegateSwigDelegateRequestCallback_FunctionApplicationBridgeBase_1 = (SwigDelegateRequestCallback_FunctionApplicationBridgeBase_1) gcHandle.Target; +delegateSwigDelegateRequestCallback_FunctionApplicationBridgeBase_1(); + } + + public delegate void SwigDelegateRequestCallback_FunctionApplicationBridgeBase_0(FBIntermediateBuffer RequestCallback_arg); + public delegate void SwigDelegateRequestCallback_FunctionApplicationBridgeBase_1(); + + private SwigDelegateRequestCallback_FunctionApplicationBridgeBase_0 swigDelegate0; + private SwigDelegateRequestCallback_FunctionApplicationBridgeBase_1 swigDelegate1; + + public delegate void SwigDelegateRequestCallback_FunctionApplicationBridgeBase_0_Dispatcher(global::System.IntPtr swigDelegateRequestCallback_FunctionApplicationBridgeBase_0_Handle, FBIntermediateBuffer RequestCallback_arg); + public delegate void SwigDelegateRequestCallback_FunctionApplicationBridgeBase_1_Dispatcher(global::System.IntPtr swigDelegateRequestCallback_FunctionApplicationBridgeBase_1_Handle); + + private SwigDelegateRequestCallback_FunctionApplicationBridgeBase_0_Dispatcher swigDelegate0dispatcher; + private SwigDelegateRequestCallback_FunctionApplicationBridgeBase_1_Dispatcher swigDelegate1dispatcher; + + private static global::System.Type[] swigMethodTypes0 = new global::System.Type[] { typeof(ror.schema.upload.UploadChunkResponse) }; + private static global::System.Type[] swigMethodTypes1 = new global::System.Type[] { }; +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RequestCallback_FunctionApplicationBridgeBase.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RequestCallback_FunctionApplicationBridgeBase.cs.meta new file mode 100644 index 0000000..af5aeb5 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/RequestCallback_FunctionApplicationBridgeBase.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 1a8f552c0077b3d8a83800a94ae5a23c diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/ResponseCallback_FunctionApplicationBridge.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/ResponseCallback_FunctionApplicationBridge.cs new file mode 100644 index 0000000..4b36052 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/ResponseCallback_FunctionApplicationBridge.cs @@ -0,0 +1,36 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public sealed class ResponseCallback_FunctionApplicationBridge : ResponseCallback_FunctionApplicationBridgeBase { + public delegate void Delegate(ror.schema.upload.UploadChunkResponse arg); + + private Delegate _delegate; + + public ResponseCallback_FunctionApplicationBridge(Delegate d) : base() { + _delegate = d; + } + + public override void releaseApplicationCallback() { + // This doesn't do anything except update reflection info so that the director thinks it needs + // to call this. + base.releaseApplicationCallback(); + } + + public override void invokeApplicationLogic(ror.schema.upload.UploadChunkResponse arg) { + try { + _delegate(arg); + } catch {} + } + +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/ResponseCallback_FunctionApplicationBridge.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/ResponseCallback_FunctionApplicationBridge.cs.meta new file mode 100644 index 0000000..5ad6eaa --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/ResponseCallback_FunctionApplicationBridge.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: aa2ef63068c7f4bcedd6696c8085cd13 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/ResponseCallback_FunctionApplicationBridgeBase.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/ResponseCallback_FunctionApplicationBridgeBase.cs new file mode 100644 index 0000000..083e817 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/ResponseCallback_FunctionApplicationBridgeBase.cs @@ -0,0 +1,157 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public abstract class ResponseCallback_FunctionApplicationBridgeBase : global::System.IDisposable { + /** DO NOT REMOVE THE FOLLOWING COMMENT **/ + /** THIS HAS BEEN SWIG CORRECTED: JJDKFJSIIIIDKJ **/ + private global::System.Runtime.InteropServices.GCHandle _swigDelegateHandle1; + private global::System.Runtime.InteropServices.GCHandle _swigDelegateHandle0; + private global::System.Runtime.InteropServices.HandleRef swigCPtr; + protected bool swigCMemOwn; + + internal ResponseCallback_FunctionApplicationBridgeBase(global::System.IntPtr cPtr, bool cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr); + } + + internal static global::System.Runtime.InteropServices.HandleRef getCPtr(ResponseCallback_FunctionApplicationBridgeBase obj) { + return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; + } + + ~ResponseCallback_FunctionApplicationBridgeBase() { + Dispose(); + } + + public virtual void Dispose() { + lock(this) { + if (swigCPtr.Handle != global::System.IntPtr.Zero) { + if (swigCMemOwn) { + swigCMemOwn = false; + GrapeshotSessionPINVOKE.delete_ResponseCallback_FunctionApplicationBridgeBase(swigCPtr); + } + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); + } + global::System.GC.SuppressFinalize(this); + _swigDelegateHandle0.Free(); + _swigDelegateHandle1.Free(); + } + } + + // Information used to prevent pre-mature GC of callbacks still being used from C++. + private ulong _refCount; + private System.Runtime.InteropServices.GCHandle _handle; + + /// Allocates a reference to this application callback so that it can't be released from memory + /// until all allocs have been meet with an equal number of releaseApplicationCallback. + public void allocApplicationCallback() { + lock(this) { + if (_refCount == 0) { + _handle = System.Runtime.InteropServices.GCHandle.Alloc(this); + } + + _refCount++; + } + } + + public virtual void invokeApplicationLogic(ror.schema.upload.UploadChunkResponse ResponseCallback_arg) { throw new System.NotImplementedException(); } + + public virtual void releaseApplicationCallback() { + // When releasing the application side callback, this means that one of the native side holds + // was terminated, thus cs should remove a reference count, once that count is zero free the + // handle. + lock(this) { + if (_refCount <= 0) { + return; + } + + _refCount -= 1; + + if (_refCount <= 0) { + _handle.Free(); + } + } + } + + + public ResponseCallback_FunctionApplicationBridgeBase() : this(GrapeshotSessionPINVOKE.new_ResponseCallback_FunctionApplicationBridgeBase(), true) { + SwigDirectorConnect(); + } + + private void SwigDirectorConnect() { + global::System.IntPtr swigDelegate0gcHandlePtr = global::System.IntPtr.Zero; + if (SwigDerivedClassHasMethod("invokeApplicationLogic", swigMethodTypes0)) { + swigDelegate0 = new SwigDelegateResponseCallback_FunctionApplicationBridgeBase_0(SwigDirectorinvokeApplicationLogic); + swigDelegate0dispatcher = new SwigDelegateResponseCallback_FunctionApplicationBridgeBase_0_Dispatcher(SwigDirectorinvokeApplicationLogic_Dispatcher); + + global::System.Runtime.InteropServices.GCHandle swigDelegate0gcHandle = global::System.Runtime.InteropServices.GCHandle.Alloc(swigDelegate0, global::System.Runtime.InteropServices.GCHandleType.Normal); + _swigDelegateHandle0 = swigDelegate0gcHandle; + swigDelegate0gcHandlePtr = global::System.Runtime.InteropServices.GCHandle.ToIntPtr(swigDelegate0gcHandle); + } + global::System.IntPtr swigDelegate1gcHandlePtr = global::System.IntPtr.Zero; + if (SwigDerivedClassHasMethod("releaseApplicationCallback", swigMethodTypes1)) { + swigDelegate1 = new SwigDelegateResponseCallback_FunctionApplicationBridgeBase_1(SwigDirectorreleaseApplicationCallback); + swigDelegate1dispatcher = new SwigDelegateResponseCallback_FunctionApplicationBridgeBase_1_Dispatcher(SwigDirectorreleaseApplicationCallback_Dispatcher); + + global::System.Runtime.InteropServices.GCHandle swigDelegate1gcHandle = global::System.Runtime.InteropServices.GCHandle.Alloc(swigDelegate1, global::System.Runtime.InteropServices.GCHandleType.Normal); + _swigDelegateHandle1 = swigDelegate1gcHandle; + swigDelegate1gcHandlePtr = global::System.Runtime.InteropServices.GCHandle.ToIntPtr(swigDelegate1gcHandle); + } + GrapeshotSessionPINVOKE.ResponseCallback_FunctionApplicationBridgeBase_director_connect(swigCPtr, swigDelegate0dispatcher, swigDelegate0gcHandlePtr, swigDelegate1dispatcher, swigDelegate1gcHandlePtr); + } + + private bool SwigDerivedClassHasMethod(string methodName, global::System.Type[] methodTypes) { + global::System.Reflection.MethodInfo methodInfo = this.GetType().GetMethod(methodName, global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance, null, methodTypes, null); + bool hasDerivedMethod = methodInfo.DeclaringType.IsSubclassOf(typeof(ResponseCallback_FunctionApplicationBridgeBase)); + return hasDerivedMethod; + } + + private void SwigDirectorinvokeApplicationLogic(FBIntermediateBuffer ResponseCallback_arg) { +var ResponseCallback_arg_buffer = new byte[ResponseCallback_arg.size];UnityEngine.Assertions.Assert.AreNotEqual(ResponseCallback_arg.size, (ulong) 0);System.Runtime.InteropServices.Marshal.Copy(ResponseCallback_arg.ptr, ResponseCallback_arg_buffer, 0, (int) ResponseCallback_arg.size);var ResponseCallback_arg_bb = new FlatBuffers.ByteBuffer(ResponseCallback_arg_buffer);var ResponseCallback_arg_fb = new ror.schema.upload.UploadChunkResponse();ResponseCallback_arg_fb.__assign(ResponseCallback_arg_bb.GetInt(ResponseCallback_arg_bb.Position) + ResponseCallback_arg_bb.Position, ResponseCallback_arg_bb); + invokeApplicationLogic(ResponseCallback_arg_fb); + } + + [GrapeshotSessionPINVOKE.MonoPInvokeCallback(typeof(SwigDelegateResponseCallback_FunctionApplicationBridgeBase_0_Dispatcher))] + private static void SwigDirectorinvokeApplicationLogic_Dispatcher(global::System.IntPtr swigDelegateResponseCallback_FunctionApplicationBridgeBase_0_Handle, FBIntermediateBuffer ResponseCallback_arg) { +var ResponseCallback_arg_buffer = new byte[ResponseCallback_arg.size];UnityEngine.Assertions.Assert.AreNotEqual(ResponseCallback_arg.size, (ulong) 0);System.Runtime.InteropServices.Marshal.Copy(ResponseCallback_arg.ptr, ResponseCallback_arg_buffer, 0, (int) ResponseCallback_arg.size);var ResponseCallback_arg_bb = new FlatBuffers.ByteBuffer(ResponseCallback_arg_buffer);var ResponseCallback_arg_fb = new ror.schema.upload.UploadChunkResponse();ResponseCallback_arg_fb.__assign(ResponseCallback_arg_bb.GetInt(ResponseCallback_arg_bb.Position) + ResponseCallback_arg_bb.Position, ResponseCallback_arg_bb); + global::System.Runtime.InteropServices.GCHandle gcHandle = global::System.Runtime.InteropServices.GCHandle.FromIntPtr(swigDelegateResponseCallback_FunctionApplicationBridgeBase_0_Handle); + SwigDelegateResponseCallback_FunctionApplicationBridgeBase_0 delegateSwigDelegateResponseCallback_FunctionApplicationBridgeBase_0 = (SwigDelegateResponseCallback_FunctionApplicationBridgeBase_0) gcHandle.Target; +delegateSwigDelegateResponseCallback_FunctionApplicationBridgeBase_0(ResponseCallback_arg); + } + + private void SwigDirectorreleaseApplicationCallback() { + releaseApplicationCallback(); + } + + [GrapeshotSessionPINVOKE.MonoPInvokeCallback(typeof(SwigDelegateResponseCallback_FunctionApplicationBridgeBase_1_Dispatcher))] + private static void SwigDirectorreleaseApplicationCallback_Dispatcher(global::System.IntPtr swigDelegateResponseCallback_FunctionApplicationBridgeBase_1_Handle) { + global::System.Runtime.InteropServices.GCHandle gcHandle = global::System.Runtime.InteropServices.GCHandle.FromIntPtr(swigDelegateResponseCallback_FunctionApplicationBridgeBase_1_Handle); + SwigDelegateResponseCallback_FunctionApplicationBridgeBase_1 delegateSwigDelegateResponseCallback_FunctionApplicationBridgeBase_1 = (SwigDelegateResponseCallback_FunctionApplicationBridgeBase_1) gcHandle.Target; +delegateSwigDelegateResponseCallback_FunctionApplicationBridgeBase_1(); + } + + public delegate void SwigDelegateResponseCallback_FunctionApplicationBridgeBase_0(FBIntermediateBuffer ResponseCallback_arg); + public delegate void SwigDelegateResponseCallback_FunctionApplicationBridgeBase_1(); + + private SwigDelegateResponseCallback_FunctionApplicationBridgeBase_0 swigDelegate0; + private SwigDelegateResponseCallback_FunctionApplicationBridgeBase_1 swigDelegate1; + + public delegate void SwigDelegateResponseCallback_FunctionApplicationBridgeBase_0_Dispatcher(global::System.IntPtr swigDelegateResponseCallback_FunctionApplicationBridgeBase_0_Handle, FBIntermediateBuffer ResponseCallback_arg); + public delegate void SwigDelegateResponseCallback_FunctionApplicationBridgeBase_1_Dispatcher(global::System.IntPtr swigDelegateResponseCallback_FunctionApplicationBridgeBase_1_Handle); + + private SwigDelegateResponseCallback_FunctionApplicationBridgeBase_0_Dispatcher swigDelegate0dispatcher; + private SwigDelegateResponseCallback_FunctionApplicationBridgeBase_1_Dispatcher swigDelegate1dispatcher; + + private static global::System.Type[] swigMethodTypes0 = new global::System.Type[] { typeof(ror.schema.upload.UploadChunkResponse) }; + private static global::System.Type[] swigMethodTypes1 = new global::System.Type[] { }; +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/ResponseCallback_FunctionApplicationBridgeBase.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/ResponseCallback_FunctionApplicationBridgeBase.cs.meta new file mode 100644 index 0000000..27e789e --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/ResponseCallback_FunctionApplicationBridgeBase.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 52ff5e3f4e3e2545a16ca8103b7b9783 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/Session.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/Session.cs new file mode 100644 index 0000000..fe4cb8c --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/Session.cs @@ -0,0 +1,91 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public class Session : global::System.IDisposable { + private global::System.Runtime.InteropServices.HandleRef swigCPtr; + private bool swigCMemOwnBase; + + internal Session(global::System.IntPtr cPtr, bool cMemoryOwn) { + swigCMemOwnBase = cMemoryOwn; + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr); + } + + internal static global::System.Runtime.InteropServices.HandleRef getCPtr(Session obj) { + return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; + } + + ~Session() { + Dispose(); + } + + public virtual void Dispose() { + lock(this) { + if (swigCPtr.Handle != global::System.IntPtr.Zero) { + if (swigCMemOwnBase) { + swigCMemOwnBase = false; + GrapeshotSessionPINVOKE.delete_Session(swigCPtr); + } + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); + } + global::System.GC.SuppressFinalize(this); + } + } + + public System.Collections.IEnumerator waitTillFinishedRoutine(uint maxChunkCount = 1) { + while(!isFinished()) { + process(maxChunkCount); + yield return null; + } + } + + public void process(uint maxChunks) { + GrapeshotSessionPINVOKE.Session_process__SWIG_0(swigCPtr, maxChunks); + if (GrapeshotSessionPINVOKE.SWIGPendingException.Pending) throw GrapeshotSessionPINVOKE.SWIGPendingException.Retrieve(); + } + + public void process() { + GrapeshotSessionPINVOKE.Session_process__SWIG_1(swigCPtr); + if (GrapeshotSessionPINVOKE.SWIGPendingException.Pending) throw GrapeshotSessionPINVOKE.SWIGPendingException.Retrieve(); + } + + public bool isFinished() { + bool ret = GrapeshotSessionPINVOKE.Session_isFinished(swigCPtr); + if (GrapeshotSessionPINVOKE.SWIGPendingException.Pending) throw GrapeshotSessionPINVOKE.SWIGPendingException.Retrieve(); + return ret; + } + + public void waitTillFinished() { + GrapeshotSessionPINVOKE.Session_waitTillFinished(swigCPtr); + if (GrapeshotSessionPINVOKE.SWIGPendingException.Pending) throw GrapeshotSessionPINVOKE.SWIGPendingException.Retrieve(); + } + + static private global::System.IntPtr SwigConstructSession(System.Guid clientIdentifier, ror.schema.upload.UploadSessionInfo sessionInfo, Driver driver, Rate rate, ApplicationChunkFetcher_FunctionApplicationBridgeBase applicationChunkFetcher, FinishedCallback_FunctionApplicationBridgeBase finishedCallback, ResponseCallback_FunctionApplicationBridgeBase responseCallback) { +var clientIdentifier_Bytes = clientIdentifier.ToByteArray();var clientIdentifier_ByteArrayHandle = System.Runtime.InteropServices.GCHandle.Alloc(clientIdentifier_Bytes ,System.Runtime.InteropServices.GCHandleType.Pinned);var clientIdentifier_buffer_ptr = clientIdentifier_ByteArrayHandle.AddrOfPinnedObject(); +var sessionInfo_table = FlatBuffers.TableUtils.GetTable(sessionInfo);var sessionInfo_length = sessionInfo_table.bb.Length;var sessionInfo_pos = sessionInfo_table.bb_pos;var sessionInfo_seg = sessionInfo_table.bb.ToArraySegment(sessionInfo_pos, sessionInfo_length - sessionInfo_pos);var sessionInfo_managed_array = sessionInfo_seg.Array;var sessionInfo_managed_handle = System.Runtime.InteropServices.GCHandle.Alloc(sessionInfo_managed_array, System.Runtime.InteropServices.GCHandleType.Pinned);var sessionInfo_buffer_ptr = sessionInfo_managed_handle.AddrOfPinnedObject();System.IntPtr sessionInfo_fb_ptr;unsafe { var sessionInfo_buffer_unsafe_ptr = (byte*) sessionInfo_buffer_ptr.ToPointer(); sessionInfo_fb_ptr = (System.IntPtr) (sessionInfo_buffer_unsafe_ptr + sessionInfo_pos);}var sessionInfo_intermediate = new FBIntermediateBuffer();sessionInfo_intermediate.ptr = sessionInfo_fb_ptr; +applicationChunkFetcher.allocApplicationCallback(); +finishedCallback.allocApplicationCallback(); +responseCallback.allocApplicationCallback(); + try { + return GrapeshotSessionPINVOKE.new_Session(clientIdentifier_buffer_ptr, sessionInfo_intermediate, Driver.getCPtr(driver), Rate.getCPtr(rate), ApplicationChunkFetcher_FunctionApplicationBridgeBase.getCPtr(applicationChunkFetcher), FinishedCallback_FunctionApplicationBridgeBase.getCPtr(finishedCallback), ResponseCallback_FunctionApplicationBridgeBase.getCPtr(responseCallback)); + } finally { +clientIdentifier_ByteArrayHandle.Free(); +sessionInfo_managed_handle.Free(); + } + } + + public Session(System.Guid clientIdentifier, ror.schema.upload.UploadSessionInfo sessionInfo, Driver driver, Rate rate, ApplicationChunkFetcher_FunctionApplicationBridgeBase applicationChunkFetcher, FinishedCallback_FunctionApplicationBridgeBase finishedCallback, ResponseCallback_FunctionApplicationBridgeBase responseCallback) : this(Session.SwigConstructSession(clientIdentifier, sessionInfo, driver, rate, applicationChunkFetcher, finishedCallback, responseCallback), true) { + if (GrapeshotSessionPINVOKE.SWIGPendingException.Pending) throw GrapeshotSessionPINVOKE.SWIGPendingException.Retrieve(); + } + +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/Session.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/Session.cs.meta new file mode 100644 index 0000000..eaebec1 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/Session.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 65f4c32c4c68d12cae75fea3dfb39b50 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/StageNamedInstance.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/StageNamedInstance.cs new file mode 100644 index 0000000..38b2329 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/StageNamedInstance.cs @@ -0,0 +1,58 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public class StageNamedInstance : global::System.IDisposable { + private global::System.Runtime.InteropServices.HandleRef swigCPtr; + protected bool swigCMemOwn; + + internal StageNamedInstance(global::System.IntPtr cPtr, bool cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr); + } + + internal static global::System.Runtime.InteropServices.HandleRef getCPtr(StageNamedInstance obj) { + return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; + } + + ~StageNamedInstance() { + Dispose(); + } + + public virtual void Dispose() { + lock(this) { + if (swigCPtr.Handle != global::System.IntPtr.Zero) { + if (swigCMemOwn) { + swigCMemOwn = false; + RORStagePINVOKE.delete_StageNamedInstance(swigCPtr); + } + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); + } + global::System.GC.SuppressFinalize(this); + } + } + + static private global::System.IntPtr SwigConstructStageNamedInstance(System.Guid stage, string name) { +var stage_Bytes = stage.ToByteArray();var stage_ByteArrayHandle = System.Runtime.InteropServices.GCHandle.Alloc(stage_Bytes ,System.Runtime.InteropServices.GCHandleType.Pinned);var stage_buffer_ptr = stage_ByteArrayHandle.AddrOfPinnedObject(); + try { + return RORStagePINVOKE.new_StageNamedInstance(stage_buffer_ptr, name); + } finally { +stage_ByteArrayHandle.Free(); + } + } + + public StageNamedInstance(System.Guid stage, string name) : this(StageNamedInstance.SwigConstructStageNamedInstance(stage, name), true) { + if (RORStagePINVOKE.SWIGPendingException.Pending) throw RORStagePINVOKE.SWIGPendingException.Retrieve(); + } + +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/StageNamedInstance.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/StageNamedInstance.cs.meta new file mode 100644 index 0000000..d1ed7da --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/StageNamedInstance.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 4165c4a73b6bef0606708ed8d0d63134 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/Topology.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/Topology.cs new file mode 100644 index 0000000..5d6284e --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/Topology.cs @@ -0,0 +1,45 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public class Topology : global::System.IDisposable { + private global::System.Runtime.InteropServices.HandleRef swigCPtr; + private bool swigCMemOwnBase; + + internal Topology(global::System.IntPtr cPtr, bool cMemoryOwn) { + swigCMemOwnBase = cMemoryOwn; + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr); + } + + internal static global::System.Runtime.InteropServices.HandleRef getCPtr(Topology obj) { + return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; + } + + ~Topology() { + Dispose(); + } + + public virtual void Dispose() { + lock(this) { + if (swigCPtr.Handle != global::System.IntPtr.Zero) { + if (swigCMemOwnBase) { + swigCMemOwnBase = false; + GrapeshotBackendTopologyPINVOKE.delete_Topology(swigCPtr); + } + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); + } + global::System.GC.SuppressFinalize(this); + } + } + +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/Topology.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/Topology.cs.meta new file mode 100644 index 0000000..67f49cd --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/Topology.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 4416143d999f31ecc93588c75f86c910 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/UnlimitedRate.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/UnlimitedRate.cs new file mode 100644 index 0000000..cde2652 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/UnlimitedRate.cs @@ -0,0 +1,84 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public sealed class UnlimitedRate : Rate { + private global::System.Runtime.InteropServices.HandleRef swigCPtr; + private bool swigCMemOwnDerived; + + internal UnlimitedRate(global::System.IntPtr cPtr, bool cMemoryOwn) : base(GrapeshotRatePINVOKE.UnlimitedRate_SWIGSmartPtrUpcast(cPtr), true) { + swigCMemOwnDerived = cMemoryOwn; + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr); + } + + internal static global::System.Runtime.InteropServices.HandleRef getCPtr(UnlimitedRate obj) { + return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; + } + + ~UnlimitedRate() { + Dispose(); + } + + public override void Dispose() { + lock(this) { + if (swigCPtr.Handle != global::System.IntPtr.Zero) { + if (swigCMemOwnDerived) { + swigCMemOwnDerived = false; + GrapeshotRatePINVOKE.delete_UnlimitedRate(swigCPtr); + } + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); + } + global::System.GC.SuppressFinalize(this); + base.Dispose(); + } + } + + public override void process() { + GrapeshotRatePINVOKE.UnlimitedRate_process(swigCPtr); + if (GrapeshotRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotRatePINVOKE.SWIGPendingException.Retrieve(); + } + + public override RateTicket claimTicket(ror.schema.upload.UploadChunkRequest chunkRequest) { +var chunkRequest_table = FlatBuffers.TableUtils.GetTable(chunkRequest);var chunkRequest_length = chunkRequest_table.bb.Length;var chunkRequest_pos = chunkRequest_table.bb_pos;var chunkRequest_seg = chunkRequest_table.bb.ToArraySegment(chunkRequest_pos, chunkRequest_length - chunkRequest_pos);var chunkRequest_managed_array = chunkRequest_seg.Array;var chunkRequest_managed_handle = System.Runtime.InteropServices.GCHandle.Alloc(chunkRequest_managed_array, System.Runtime.InteropServices.GCHandleType.Pinned);var chunkRequest_buffer_ptr = chunkRequest_managed_handle.AddrOfPinnedObject();System.IntPtr chunkRequest_fb_ptr;unsafe { var chunkRequest_buffer_unsafe_ptr = (byte*) chunkRequest_buffer_ptr.ToPointer(); chunkRequest_fb_ptr = (System.IntPtr) (chunkRequest_buffer_unsafe_ptr + chunkRequest_pos);}var chunkRequest_intermediate = new FBIntermediateBuffer();chunkRequest_intermediate.ptr = chunkRequest_fb_ptr; + try { + global::System.IntPtr cPtr = GrapeshotRatePINVOKE.UnlimitedRate_claimTicket(swigCPtr, chunkRequest_intermediate); + RateTicket ret = (cPtr == global::System.IntPtr.Zero) ? null : new RateTicket(cPtr, true); + if (GrapeshotRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotRatePINVOKE.SWIGPendingException.Retrieve(); + return ret; + } finally { +chunkRequest_managed_handle.Free(); + } + } + + public override RateTicket tryClaimTicket(ror.schema.upload.UploadChunkRequest chunkRequest) { +var chunkRequest_table = FlatBuffers.TableUtils.GetTable(chunkRequest);var chunkRequest_length = chunkRequest_table.bb.Length;var chunkRequest_pos = chunkRequest_table.bb_pos;var chunkRequest_seg = chunkRequest_table.bb.ToArraySegment(chunkRequest_pos, chunkRequest_length - chunkRequest_pos);var chunkRequest_managed_array = chunkRequest_seg.Array;var chunkRequest_managed_handle = System.Runtime.InteropServices.GCHandle.Alloc(chunkRequest_managed_array, System.Runtime.InteropServices.GCHandleType.Pinned);var chunkRequest_buffer_ptr = chunkRequest_managed_handle.AddrOfPinnedObject();System.IntPtr chunkRequest_fb_ptr;unsafe { var chunkRequest_buffer_unsafe_ptr = (byte*) chunkRequest_buffer_ptr.ToPointer(); chunkRequest_fb_ptr = (System.IntPtr) (chunkRequest_buffer_unsafe_ptr + chunkRequest_pos);}var chunkRequest_intermediate = new FBIntermediateBuffer();chunkRequest_intermediate.ptr = chunkRequest_fb_ptr; + try { + global::System.IntPtr cPtr = GrapeshotRatePINVOKE.UnlimitedRate_tryClaimTicket(swigCPtr, chunkRequest_intermediate); + RateTicket ret = (cPtr == global::System.IntPtr.Zero) ? null : new RateTicket(cPtr, true); + if (GrapeshotRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotRatePINVOKE.SWIGPendingException.Retrieve(); + return ret; + } finally { +chunkRequest_managed_handle.Free(); + } + } + + public override bool areFreeTickets() { + bool ret = GrapeshotRatePINVOKE.UnlimitedRate_areFreeTickets(swigCPtr); + if (GrapeshotRatePINVOKE.SWIGPendingException.Pending) throw GrapeshotRatePINVOKE.SWIGPendingException.Retrieve(); + return ret; + } + + public UnlimitedRate() : this(GrapeshotRatePINVOKE.new_UnlimitedRate(), true) { + } + +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/UnlimitedRate.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/UnlimitedRate.cs.meta new file mode 100644 index 0000000..c798fbf --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/UnlimitedRate.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 54dbb478acf63523db6cea09bbebb4c2 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/UploadAuth_Ret.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/UploadAuth_Ret.cs new file mode 100644 index 0000000..0b846e7 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/UploadAuth_Ret.cs @@ -0,0 +1,57 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public class UploadAuth_Ret : global::System.IDisposable { + private global::System.Runtime.InteropServices.HandleRef swigCPtr; + protected bool swigCMemOwn; + + internal UploadAuth_Ret(global::System.IntPtr cPtr, bool cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr); + } + + internal static global::System.Runtime.InteropServices.HandleRef getCPtr(UploadAuth_Ret obj) { + return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; + } + + ~UploadAuth_Ret() { + Dispose(); + } + + public virtual void Dispose() { + lock(this) { + if (swigCPtr.Handle != global::System.IntPtr.Zero) { + if (swigCMemOwn) { + swigCMemOwn = false; + GrapeshotUploadFlatbuffersPINVOKE.delete_UploadAuth_Ret(swigCPtr); + } + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); + } + global::System.GC.SuppressFinalize(this); + } + } + + public void ret(ror.schema.upload.UploadAuth newValue) { +var newValue_table = FlatBuffers.TableUtils.GetTable(newValue);var newValue_length = newValue_table.bb.Length;var newValue_pos = newValue_table.bb_pos;var newValue_seg = newValue_table.bb.ToArraySegment(newValue_pos, newValue_length - newValue_pos);var newValue_managed_array = newValue_seg.Array;var newValue_managed_handle = System.Runtime.InteropServices.GCHandle.Alloc(newValue_managed_array, System.Runtime.InteropServices.GCHandleType.Pinned);var newValue_buffer_ptr = newValue_managed_handle.AddrOfPinnedObject();System.IntPtr newValue_fb_ptr;unsafe { var newValue_buffer_unsafe_ptr = (byte*) newValue_buffer_ptr.ToPointer(); newValue_fb_ptr = (System.IntPtr) (newValue_buffer_unsafe_ptr + newValue_pos);}var newValue_intermediate = new FBIntermediateBuffer();newValue_intermediate.ptr = newValue_fb_ptr; + try { + GrapeshotUploadFlatbuffersPINVOKE.UploadAuth_Ret_ret(swigCPtr, newValue_intermediate); + } finally { +newValue_managed_handle.Free(); + } + } + + public UploadAuth_Ret() : this(GrapeshotUploadFlatbuffersPINVOKE.new_UploadAuth_Ret(), true) { + } + +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/UploadAuth_Ret.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/UploadAuth_Ret.cs.meta new file mode 100644 index 0000000..43f9b4b --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/UploadAuth_Ret.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 4fb5180bc32d6bbf5e6d72f5adb3b35d diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/UploadChunkBody_Ret.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/UploadChunkBody_Ret.cs new file mode 100644 index 0000000..a1a2093 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/UploadChunkBody_Ret.cs @@ -0,0 +1,57 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public class UploadChunkBody_Ret : global::System.IDisposable { + private global::System.Runtime.InteropServices.HandleRef swigCPtr; + protected bool swigCMemOwn; + + internal UploadChunkBody_Ret(global::System.IntPtr cPtr, bool cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr); + } + + internal static global::System.Runtime.InteropServices.HandleRef getCPtr(UploadChunkBody_Ret obj) { + return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; + } + + ~UploadChunkBody_Ret() { + Dispose(); + } + + public virtual void Dispose() { + lock(this) { + if (swigCPtr.Handle != global::System.IntPtr.Zero) { + if (swigCMemOwn) { + swigCMemOwn = false; + GrapeshotUploadFlatbuffersPINVOKE.delete_UploadChunkBody_Ret(swigCPtr); + } + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); + } + global::System.GC.SuppressFinalize(this); + } + } + + public void ret(ror.schema.upload.UploadChunkBody newValue) { +var newValue_table = FlatBuffers.TableUtils.GetTable(newValue);var newValue_length = newValue_table.bb.Length;var newValue_pos = newValue_table.bb_pos;var newValue_seg = newValue_table.bb.ToArraySegment(newValue_pos, newValue_length - newValue_pos);var newValue_managed_array = newValue_seg.Array;var newValue_managed_handle = System.Runtime.InteropServices.GCHandle.Alloc(newValue_managed_array, System.Runtime.InteropServices.GCHandleType.Pinned);var newValue_buffer_ptr = newValue_managed_handle.AddrOfPinnedObject();System.IntPtr newValue_fb_ptr;unsafe { var newValue_buffer_unsafe_ptr = (byte*) newValue_buffer_ptr.ToPointer(); newValue_fb_ptr = (System.IntPtr) (newValue_buffer_unsafe_ptr + newValue_pos);}var newValue_intermediate = new FBIntermediateBuffer();newValue_intermediate.ptr = newValue_fb_ptr; + try { + GrapeshotUploadFlatbuffersPINVOKE.UploadChunkBody_Ret_ret(swigCPtr, newValue_intermediate); + } finally { +newValue_managed_handle.Free(); + } + } + + public UploadChunkBody_Ret() : this(GrapeshotUploadFlatbuffersPINVOKE.new_UploadChunkBody_Ret(), true) { + } + +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/UploadChunkBody_Ret.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/UploadChunkBody_Ret.cs.meta new file mode 100644 index 0000000..b6e8492 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/UploadChunkBody_Ret.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: dc6e9da4e0e2cf652d65acfac8f8a623 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/UploadChunkRequest_Ret.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/UploadChunkRequest_Ret.cs new file mode 100644 index 0000000..309f85a --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/UploadChunkRequest_Ret.cs @@ -0,0 +1,57 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public class UploadChunkRequest_Ret : global::System.IDisposable { + private global::System.Runtime.InteropServices.HandleRef swigCPtr; + protected bool swigCMemOwn; + + internal UploadChunkRequest_Ret(global::System.IntPtr cPtr, bool cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr); + } + + internal static global::System.Runtime.InteropServices.HandleRef getCPtr(UploadChunkRequest_Ret obj) { + return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; + } + + ~UploadChunkRequest_Ret() { + Dispose(); + } + + public virtual void Dispose() { + lock(this) { + if (swigCPtr.Handle != global::System.IntPtr.Zero) { + if (swigCMemOwn) { + swigCMemOwn = false; + GrapeshotUploadFlatbuffersPINVOKE.delete_UploadChunkRequest_Ret(swigCPtr); + } + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); + } + global::System.GC.SuppressFinalize(this); + } + } + + public void ret(ror.schema.upload.UploadChunkRequest newValue) { +var newValue_table = FlatBuffers.TableUtils.GetTable(newValue);var newValue_length = newValue_table.bb.Length;var newValue_pos = newValue_table.bb_pos;var newValue_seg = newValue_table.bb.ToArraySegment(newValue_pos, newValue_length - newValue_pos);var newValue_managed_array = newValue_seg.Array;var newValue_managed_handle = System.Runtime.InteropServices.GCHandle.Alloc(newValue_managed_array, System.Runtime.InteropServices.GCHandleType.Pinned);var newValue_buffer_ptr = newValue_managed_handle.AddrOfPinnedObject();System.IntPtr newValue_fb_ptr;unsafe { var newValue_buffer_unsafe_ptr = (byte*) newValue_buffer_ptr.ToPointer(); newValue_fb_ptr = (System.IntPtr) (newValue_buffer_unsafe_ptr + newValue_pos);}var newValue_intermediate = new FBIntermediateBuffer();newValue_intermediate.ptr = newValue_fb_ptr; + try { + GrapeshotUploadFlatbuffersPINVOKE.UploadChunkRequest_Ret_ret(swigCPtr, newValue_intermediate); + } finally { +newValue_managed_handle.Free(); + } + } + + public UploadChunkRequest_Ret() : this(GrapeshotUploadFlatbuffersPINVOKE.new_UploadChunkRequest_Ret(), true) { + } + +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/UploadChunkRequest_Ret.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/UploadChunkRequest_Ret.cs.meta new file mode 100644 index 0000000..0b1ada8 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/UploadChunkRequest_Ret.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 1da7aa606b2ad33335a56daab5741219 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/UploadServiceInfo_Ret.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/UploadServiceInfo_Ret.cs new file mode 100644 index 0000000..3746574 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/UploadServiceInfo_Ret.cs @@ -0,0 +1,57 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public class UploadServiceInfo_Ret : global::System.IDisposable { + private global::System.Runtime.InteropServices.HandleRef swigCPtr; + protected bool swigCMemOwn; + + internal UploadServiceInfo_Ret(global::System.IntPtr cPtr, bool cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr); + } + + internal static global::System.Runtime.InteropServices.HandleRef getCPtr(UploadServiceInfo_Ret obj) { + return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; + } + + ~UploadServiceInfo_Ret() { + Dispose(); + } + + public virtual void Dispose() { + lock(this) { + if (swigCPtr.Handle != global::System.IntPtr.Zero) { + if (swigCMemOwn) { + swigCMemOwn = false; + GrapeshotUploadFlatbuffersPINVOKE.delete_UploadServiceInfo_Ret(swigCPtr); + } + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); + } + global::System.GC.SuppressFinalize(this); + } + } + + public void ret(ror.schema.upload.UploadServiceInfo newValue) { +var newValue_table = FlatBuffers.TableUtils.GetTable(newValue);var newValue_length = newValue_table.bb.Length;var newValue_pos = newValue_table.bb_pos;var newValue_seg = newValue_table.bb.ToArraySegment(newValue_pos, newValue_length - newValue_pos);var newValue_managed_array = newValue_seg.Array;var newValue_managed_handle = System.Runtime.InteropServices.GCHandle.Alloc(newValue_managed_array, System.Runtime.InteropServices.GCHandleType.Pinned);var newValue_buffer_ptr = newValue_managed_handle.AddrOfPinnedObject();System.IntPtr newValue_fb_ptr;unsafe { var newValue_buffer_unsafe_ptr = (byte*) newValue_buffer_ptr.ToPointer(); newValue_fb_ptr = (System.IntPtr) (newValue_buffer_unsafe_ptr + newValue_pos);}var newValue_intermediate = new FBIntermediateBuffer();newValue_intermediate.ptr = newValue_fb_ptr; + try { + GrapeshotUploadFlatbuffersPINVOKE.UploadServiceInfo_Ret_ret(swigCPtr, newValue_intermediate); + } finally { +newValue_managed_handle.Free(); + } + } + + public UploadServiceInfo_Ret() : this(GrapeshotUploadFlatbuffersPINVOKE.new_UploadServiceInfo_Ret(), true) { + } + +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/UploadServiceInfo_Ret.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/UploadServiceInfo_Ret.cs.meta new file mode 100644 index 0000000..750e8e4 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/UploadServiceInfo_Ret.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 698bcebab579cddf7b51a929820c91ad diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/UploadSessionDBAccessor.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/UploadSessionDBAccessor.cs new file mode 100644 index 0000000..9f1a021 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/UploadSessionDBAccessor.cs @@ -0,0 +1,45 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (http://www.swig.org). +// Version 4.0.0 +// +// Do not make changes to this file unless you know what you are doing--modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace Grapeshot { + +public abstract class UploadSessionDBAccessor : global::System.IDisposable { + private global::System.Runtime.InteropServices.HandleRef swigCPtr; + private bool swigCMemOwnBase; + + internal UploadSessionDBAccessor(global::System.IntPtr cPtr, bool cMemoryOwn) { + swigCMemOwnBase = cMemoryOwn; + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr); + } + + internal static global::System.Runtime.InteropServices.HandleRef getCPtr(UploadSessionDBAccessor obj) { + return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; + } + + ~UploadSessionDBAccessor() { + Dispose(); + } + + public virtual void Dispose() { + lock(this) { + if (swigCPtr.Handle != global::System.IntPtr.Zero) { + if (swigCMemOwnBase) { + swigCMemOwnBase = false; + GrapeshotUploadSessionDBAccessorPINVOKE.delete_UploadSessionDBAccessor(swigCPtr); + } + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); + } + global::System.GC.SuppressFinalize(this); + } + } + +} + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/UploadSessionDBAccessor.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/UploadSessionDBAccessor.cs.meta new file mode 100644 index 0000000..45e0f89 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/grapeshot_unity_application/UploadSessionDBAccessor.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: f8b8b9840d25f8927635a908771468db diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services.meta new file mode 100644 index 0000000..c41588b --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c9314bcb1f5024123a889bd0aeaffdd1 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/BackendTopology.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/BackendTopology.cs new file mode 100644 index 0000000..87b77aa --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/BackendTopology.cs @@ -0,0 +1,41 @@ +using System; +using Grapeshot; + +namespace ARDK.Grapeshot { + /// + /// Before uploading, the user must create an upload topology. This topology will create the + /// upload workers needed to do the upload, this needs to only be created once. + /// + public interface IBackendTopology : IDisposable { + /// + /// The stage to perform upload sessions on. A topology is mapped to one stage. + /// + Guid Stage { get; } + } + + public class BackendTopology : IBackendTopology { + private Topology _backendTopology; + private Guid _stage; + + public BackendTopology() { + if (_backendTopology == null) { + _stage = Guid.NewGuid(); + _backendTopology = GrapeshotBackendTopology.createDefaultGCSTopology(_stage); + } + } + + public Guid Stage { + get { + return _stage; + } + } + + public void Dispose() { + var backendTopology = _backendTopology; + if (backendTopology != null) { + _backendTopology = null; + backendTopology.Dispose(); + } + } + } +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/BackendTopology.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/BackendTopology.cs.meta new file mode 100644 index 0000000..441754d --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/BackendTopology.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 07a294dad1eb0f201dfec9dc43de5cec diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/GcsInfoProvider.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/GcsInfoProvider.cs new file mode 100644 index 0000000..52caf7e --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/GcsInfoProvider.cs @@ -0,0 +1,143 @@ +// Copyright 2013-2020 Niantic, Inc. All Rights Reserved. + +using FlatBuffers; +using ror.schema.upload; + +namespace ARDK.Grapeshot { + /// + /// GCS provider for signed url related authentication and info. This helper class takes in the + /// provided information and creates a flatbuffer object out of it. + /// + public static class GcsInfoProvider { + private const string FORWARD_SLASH = "/"; + private const string BACKWARD_SLASH = "\\"; + + /// + /// Create authentication for GCS Signed URL. + /// + /// flatbuffer for construct data on. + /// Signed url string. + /// Date string. + /// A flatbuffer offset of type UploadAuth. + public static Offset WriteGcsSignedUrlAuth( + FlatBufferBuilder fbb, + string authorization, + string date + ) { + // Add compose auth + var gcsSignedAuthComposeOffset = fbb.CreateString(authorization); + var dateComposeOffset = fbb.CreateString(date); + var gcsComposedOffset = GCSSignedAuth.CreateGCSSignedAuth( + fbb, + gcsSignedAuthComposeOffset, + dateComposeOffset + ); + var gcsSignedComposedUrlOffset = GCSSignedComposeURL.CreateGCSSignedComposeURL( + fbb, + gcsComposedOffset + ); + + return UploadAuth.CreateUploadAuth( + fbb, + ServiceAuths.GCSSignedComposeURL, + gcsSignedComposedUrlOffset.Value + ); + } + + /// + /// Create GCS service info for each upload chunk. + /// + /// Initial size of flatbuffer. + /// GCS bucket name in string. + /// File path string for each chunk. + /// Returns a flatbuffer object with upload service info per chunk. + public static UploadServiceInfo CreateGcsServiceInfoPerChunk( + int flatBufferSize, + string bucketName, + string filePath + ) { + var fbb = new FlatBufferBuilder(flatBufferSize); + + // Populate info about uploading to GCS bucket per chunk + var bucketOffset = fbb.CreateString(bucketName); + var objectOffset = fbb.CreateString(StripFilePathSlash(filePath)); + var serviceInfoOffset = GCSServiceInfo.CreateGCSServiceInfo(fbb, objectOffset, bucketOffset); + + var offset = UploadServiceInfo.CreateUploadServiceInfo( + fbb, + ServiceInfos.GCSServiceInfo, + serviceInfoOffset.Value + ); + + fbb.Finish(offset.Value); + return UploadServiceInfo.GetRootAsUploadServiceInfo(fbb.DataBuffer); + } + + /// + /// Create GCS signed write auth flatbuffer object for each upload chunk. + /// + /// Initial size of flatbuffer. + /// Upload authorization string. + /// Upload auth date string. + /// Delete authorization string. + /// Delete auth date string. + /// Returns a flatbuffer object with upload auth per chunk. + public static UploadAuth CreateGcsSignedWriteUploadAuthPerChunk( + int flatBufferSize, + string uploadAuth, + string uploadAuthDate, + string deleteAuth, + string deleteAuthDate + ) { + var fbb = new FlatBufferBuilder(flatBufferSize); + + // Populate upload authentication info + var createAuthorizationOffset = fbb.CreateString(uploadAuth); + var createDateOffset = fbb.CreateString(uploadAuthDate); + var createAuthOffset = GCSSignedAuth.CreateGCSSignedAuth( + fbb, + createAuthorizationOffset, + createDateOffset + ); + + // Populate delete authentication info + var deleteAuthorizationOffset = fbb.CreateString(deleteAuth); + var deleteDateOffset = fbb.CreateString(deleteAuthDate); + var deleteAuthOffset = GCSSignedAuth.CreateGCSSignedAuth( + fbb, + deleteAuthorizationOffset, + deleteDateOffset + ); + var gcsSignedAuthOffset = GCSSignedWriteURL.CreateGCSSignedWriteURL( + fbb, + createAuthOffset, + deleteAuthOffset + ); + + // Populate upload auth info by combining the previous data + var offset = UploadAuth.CreateUploadAuth( + fbb, + ServiceAuths.GCSSignedWriteURL, + gcsSignedAuthOffset.Value + ); + + fbb.Finish(offset.Value); + + return UploadAuth.GetRootAsUploadAuth(fbb.DataBuffer); + } + + /// + /// Check and strip file path slashes. Note that these are not OS dependent, strings are usually + /// from server settings. + /// + /// File path string, typically from server setting + /// Sanitized file path string. + public static string StripFilePathSlash(string filePath) { + if (filePath.StartsWith(FORWARD_SLASH) || filePath.StartsWith(BACKWARD_SLASH)) { + filePath = filePath.Substring(1); + } + + return filePath; + } + } +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/GcsInfoProvider.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/GcsInfoProvider.cs.meta new file mode 100644 index 0000000..4937081 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/GcsInfoProvider.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 4074d786c3db1160edba050984bd03d2 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/GcsSignedUrlUploadService.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/GcsSignedUrlUploadService.cs new file mode 100644 index 0000000..ddef2e8 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/GcsSignedUrlUploadService.cs @@ -0,0 +1,199 @@ +// Copyright 2013-2020 Niantic, Inc. All Rights Reserved. + +using System; +using System.IO; +using FlatBuffers; +using Grapeshot; +using ror.schema; +using ror.schema.upload; +using Random = UnityEngine.Random; +using UnityEngine; + +namespace ARDK.Grapeshot { + /// + /// This interface directly interacts with the swig-generated native grapeshot API. It + /// specifically handles multiple chunk upload through GCS signed URLs. + /// + public interface IGcsSignedUrlUploadService { + /// + /// Create a unique session that operates uploading for the provided file. + /// + /// stage identifier created from backend topology> + /// Where the file is stored. + /// Proto containing list of signed urls for each chunk and compose. + /// Number of chunks to upload in a batch. + /// Rate limits for upload session + /// Callback when upload is finished. + /// Callback when a single chunk is processed. + IGrapeshotSession CreateGrapeshotUploadSession( + Guid stage, + string filePath, + IGrapeshotUploadData proto, + int chunkCount, + Rate[] rates, + Action uploadSuccessCallback, + Action uploadChunkResponseCallback + ); + } + + public class GcsSignedUrlUploadService : IGcsSignedUrlUploadService { + private const int FLAT_BUFFER_INITIAL_SIZE = 1024; + + public IGrapeshotSession CreateGrapeshotUploadSession( + Guid stage, + string filePath, + IGrapeshotUploadData data, + int chunkCount, + Rate[] rates, + Action uploadSuccessCallback, + Action uploadChunkResponseCallback + ) { + var uploadSessionInfo = CreateUploadSessionInfo( + data, + chunkCount + ); + + // Create our session object that will handle the work of uploading. + return new GrapeshotSession( + Guid.Empty, + uploadSessionInfo, + new InterprocDriver(stage, new LocalUploadSessionDBAccessor()), + MultiRate.createMultiRate(rates), + (cfParams) => { ChunkFetchCallback(cfParams, filePath, data, chunkCount); }, + uploadSuccessCallback, + (response) => { UploadChunkResponse(response, uploadChunkResponseCallback); } + ); + } + + /// + // Create upload session info that contains the default auth used for each chunk, as well as + // the auth used for operations not on a single chunk (such as composing). + /// + /// Titan protobuf with all upload data + /// number of chunks that the upload is divided into + /// + private static UploadSessionInfo CreateUploadSessionInfo( + IGrapeshotUploadData data, + int chunkCount + ) { + // Populate info about upload to GCS bucket + var fbb = new FlatBufferBuilder(FLAT_BUFFER_INITIAL_SIZE); + var bucketOffset = fbb.CreateString(data.GcsBucket); + var objectOffset = fbb.CreateString( + GcsInfoProvider.StripFilePathSlash(data.ComposeData.TargetFilePath) + ); + var serviceInfoOffset = GCSServiceInfo.CreateGCSServiceInfo(fbb, objectOffset, bucketOffset); + + // Populate session authentication info + var authOffset = GcsInfoProvider.WriteGcsSignedUrlAuth( + fbb, + data.ComposeData.Authentication.Authorization, + data.ComposeData.Authentication.Date + ); + + // Populate the upload session info with the combined data above + UploadSessionInfo.StartUploadSessionInfo(fbb); + var sessionIdOffset = UUID.CreateUUID( + fbb, + (ulong) Random.Range(0, int.MaxValue), + (ulong) Random.Range(0, int.MaxValue) + ); + + UploadSessionInfo.AddSession(fbb, sessionIdOffset); + UploadSessionInfo.AddServiceInfoType(fbb, ServiceInfos.GCSServiceInfo); + UploadSessionInfo.AddServiceInfo(fbb, serviceInfoOffset.Value); + UploadSessionInfo.AddSessionAuth(fbb, authOffset); + UploadSessionInfo.AddOutOf(fbb, (ulong) chunkCount); + var uploadSessionInfoOffset = UploadSessionInfo.EndUploadSessionInfo(fbb); + + fbb.Finish(uploadSessionInfoOffset.Value); + + return UploadSessionInfo.GetRootAsUploadSessionInfo(fbb.DataBuffer); + } + + private static void UploadChunkResponse( + UploadChunkResponse response, + Action uploadChunkResponseCallback + ) { + var wrapperResponse = new GrapeshotUploadChunkResponse(response); + uploadChunkResponseCallback(wrapperResponse); + } + + private static void ChunkFetchCallback( + ChunkFetcherParams cfParams, + string filePath, + IGrapeshotUploadData data, + int chunkCount + ) { + using (var fileStream = File.OpenRead(filePath)) { + // Calculate the portion of data to be sending and convert it to a byte[]. + var chunkSize = fileStream.Length / chunkCount; + var startIndex = ((int) cfParams.index * chunkSize); + + // The chunk size is an average chunk size, that may go over/under the end of the data. To + // prevent this, we re-calculate if the chunk goes over the back to fit the back of + // the array. + if ((int) cfParams.index + 1 == chunkCount) { + chunkSize = fileStream.Length - startIndex; + } + + var chunkFbb = new FlatBufferBuilder(FLAT_BUFFER_INITIAL_SIZE); + + // Store the data to send into it. + UploadChunkBody.StartDataVector(chunkFbb, (int) chunkSize); + + var buffer = new byte[chunkSize]; + + fileStream.Seek(startIndex, SeekOrigin.Begin); + var bytesRead = fileStream.Read(buffer, 0, buffer.Length); + + if (bytesRead > 0) { + for (var i = chunkSize - 1; i >= 0; i--) { + var b = buffer[i]; + chunkFbb.PutByte(b); + } + } else { + Debug.LogError("Filestream is reading empty byte"); + } + + CreateChunkBodyAndUpload(cfParams, data, chunkFbb); + } + } + + private static void CreateChunkBodyAndUpload( + ChunkFetcherParams cfParams, + IGrapeshotUploadData data, + FlatBufferBuilder chunkFbb + ) { + // Store the data to send into it. + var dataOffset = chunkFbb.EndVector(); + + // Create the chunk body as the root piece. + UploadChunkBody.StartUploadChunkBody(chunkFbb); + UploadChunkBody.AddData(chunkFbb, dataOffset); + var chunkBodyOffset = UploadChunkBody.EndUploadChunkBody(chunkFbb); + chunkFbb.Finish(chunkBodyOffset.Value); + + // Convert back into an object, and set the body return to that flatbuffer. + var chunkBody = UploadChunkBody.GetRootAsUploadChunkBody(chunkFbb.DataBuffer); + + var chunkData = data.ChunkData[(int) cfParams.index]; + var authBody = GcsInfoProvider.CreateGcsSignedWriteUploadAuthPerChunk( + FLAT_BUFFER_INITIAL_SIZE, + chunkData.UploadAuthentication.Authorization, + chunkData.UploadAuthentication.Date, + chunkData.DeleteAuthentication.Authorization, + chunkData.DeleteAuthentication.Date + ); + var serviceBody = GcsInfoProvider.CreateGcsServiceInfoPerChunk( + FLAT_BUFFER_INITIAL_SIZE, + data.GcsBucket, + chunkData.FilePath + ); + + cfParams.serviceInfoReturn.ret(serviceBody); + cfParams.authReturn.ret(authBody); + cfParams.bodyReturn.ret(chunkBody); + } + } +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/GcsSignedUrlUploadService.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/GcsSignedUrlUploadService.cs.meta new file mode 100644 index 0000000..894c961 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/GcsSignedUrlUploadService.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 0379052707aea529e17daa21d11dba44 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/GrapeshotSession.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/GrapeshotSession.cs new file mode 100644 index 0000000..e2e76f1 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/GrapeshotSession.cs @@ -0,0 +1,73 @@ +// Copyright 2013-2020 Niantic, Inc. All Rights Reserved. + +using System; +using Grapeshot; +using ror.schema.upload; + +namespace ARDK.Grapeshot { + /// + /// Wrapper around grapeshot API's Session, which runs an upload session for a single file. + /// + public interface IGrapeshotSession : IDisposable { + /// + /// Is the upload process of the session finished. + /// + /// True if finished, false if in progress. + bool IsFinished(); + + /// + /// Wrapper around grapeshot session's Process(), which prosecutes all free chunk tickets. + /// + void Process(); + } + + public class GrapeshotSession : IGrapeshotSession { + private Session _session; + + public GrapeshotSession( + Guid guid, + UploadSessionInfo uploadSessionInfo, + Driver driver, + Rate rates, + Action chunkFetcherCallback, + Action uploadSuccessCallback, + Action uploadChunkResponseCallback + ) { + _session = new Session( + guid, + uploadSessionInfo, + driver, + rates, + new ApplicationChunkFetcher_FunctionApplicationBridge(cfParams => { + if (chunkFetcherCallback != null) { chunkFetcherCallback.Invoke(cfParams); } + } + ), + new FinishedCallback_FunctionApplicationBridge(success => { + if (uploadSuccessCallback != null) { uploadSuccessCallback.Invoke(success); } + }), + new ResponseCallback_FunctionApplicationBridge(response => { + if (uploadChunkResponseCallback != null) { uploadChunkResponseCallback.Invoke(response); } + })); + } + + public bool IsFinished() { + var session = _session; + if (session == null) + return true; + + return session.isFinished(); + } + + public void Process() { + _session.process(); + } + + public void Dispose() { + var session = _session; + if (session != null) { + _session = null; + session.Dispose(); + } + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/GrapeshotSession.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/GrapeshotSession.cs.meta new file mode 100644 index 0000000..1f5921a --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/GrapeshotSession.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 0184dd2d05a550a3d436722c6da2eca0 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/GrapeshotUploadChunkResponse.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/GrapeshotUploadChunkResponse.cs new file mode 100644 index 0000000..cd1e1c5 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/GrapeshotUploadChunkResponse.cs @@ -0,0 +1,31 @@ +// Copyright 2013-2020 Niantic, Inc. All Rights Reserved. + +using ror.schema.upload; + +namespace ARDK.Grapeshot { + /// + /// A wrapper around grapeshot API's UploadChunkResponse to add testability and expose the + /// necessary parameters. + /// + public interface IGrapeshotUploadChunkResponse { + /// + /// Upload status of the chunk + /// + ChunkStatus Status { get; } + + /// + /// Error message if the chunk upload fails + /// + string StatusMessage { get; } + } + + public class GrapeshotUploadChunkResponse : IGrapeshotUploadChunkResponse { + public GrapeshotUploadChunkResponse(UploadChunkResponse response) { + Status = response.Status; + StatusMessage = response.StatusMessage; + } + + public ChunkStatus Status { get; private set; } + public string StatusMessage { get; private set; } + } +} \ No newline at end of file diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/GrapeshotUploadChunkResponse.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/GrapeshotUploadChunkResponse.cs.meta new file mode 100644 index 0000000..4c08cd5 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/GrapeshotUploadChunkResponse.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 511cb7dbf0471b7800e340a8469c1837 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/GrapeshotUploadData.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/GrapeshotUploadData.cs new file mode 100644 index 0000000..9a99146 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/GrapeshotUploadData.cs @@ -0,0 +1,88 @@ +using System.Collections.Generic; + +namespace ARDK.Grapeshot { + // Information needed to perform an upload through Grapeshot through signed URL. Authentication + // is needed per operation, which includes each chunk upload and compose step. + public interface IGrapeshotUploadData { + // Google Cloud Storage bucket that the file is uploaded to + string GcsBucket { get; } + // Number of chunks to divid file into + int NumberOfChunks { get; } + // Info for compose step + ComposeData ComposeData { get; } + // Info for each chunk + List ChunkData { get; } + } + + public class GrapeshotUploadData : IGrapeshotUploadData { + public string GcsBucket { get; private set; } + public int NumberOfChunks { get; private set; } + public ComposeData ComposeData { get; private set; } + public List ChunkData { get; private set; } + + public GrapeshotUploadData( + string gcsBucket, + int numOfChunks, + ComposeData composeData, + List chunkData + ) { + GcsBucket = gcsBucket; + NumberOfChunks = numOfChunks; + ComposeData = composeData; + ChunkData = chunkData; + } + } + + /// + /// Information needed for compose step. + /// + public struct ComposeData { + // File path where the final, re-stitched file goes to + public string TargetFilePath { get; private set; } + // Auth info + public Authentication Authentication { get; private set; } + + public ComposeData(string targetFilePath, Authentication authentication) : this() { + TargetFilePath = targetFilePath; + Authentication = authentication; + } + } + + /// + /// Information for each chunk upload + /// + public struct ChunkData { + // File path where each chunk is stored. + public string FilePath { get; private set; } + // Auth for upload step + public Authentication UploadAuthentication { get; private set; } + // Auth for delete step + public Authentication DeleteAuthentication { get; private set; } + + public ChunkData( + string filePath, + Authentication uploadAuthentication, + Authentication deleteAuthentication + ) : this() { + FilePath = filePath; + UploadAuthentication = uploadAuthentication; + DeleteAuthentication = deleteAuthentication; + } + } + + /// + /// Signed URL authentication is needed per operation, which includes each chunk upload and + /// compose step. + /// + public struct Authentication { + // Signed url auth + public string Authorization { get; private set; } + // Signed url auth date + public string Date { get; private set; } + + public Authentication(string authorization, string date) : this() { + Authorization = authorization; + Date = date; + } + } +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/GrapeshotUploadData.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/GrapeshotUploadData.cs.meta new file mode 100644 index 0000000..dff237c --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/GrapeshotUploadData.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 55fe2821cf1e385c2ef3c9d6b5be4b48 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/MockBackendTopology.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/MockBackendTopology.cs new file mode 100644 index 0000000..15cbd06 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/MockBackendTopology.cs @@ -0,0 +1,11 @@ +using System; + +namespace ARDK.Grapeshot { + public class MockBackendTopology : IBackendTopology { + public void Dispose() { + throw new NotImplementedException(); + } + + public Guid Stage { get; private set; } + } +} \ No newline at end of file diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/MockBackendTopology.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/MockBackendTopology.cs.meta new file mode 100644 index 0000000..34aa47a --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/MockBackendTopology.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 426007e835738a72d0168e1cf6b6e014 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/MockGrapeshotSession.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/MockGrapeshotSession.cs new file mode 100644 index 0000000..9289b3a --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/MockGrapeshotSession.cs @@ -0,0 +1,22 @@ +using System; + +namespace ARDK.Grapeshot { + /// + /// Mock class of grapeshot session. + /// + public class MockSession : IGrapeshotSession { + public bool IsFinished() { + return IsSessionFinished; + } + + public void Process() { + throw new NotImplementedException(); + } + + public void Dispose() { + throw new NotImplementedException(); + } + + private bool IsSessionFinished { get; set; } + } +} \ No newline at end of file diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/MockGrapeshotSession.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/MockGrapeshotSession.cs.meta new file mode 100644 index 0000000..55f1d3e --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/MockGrapeshotSession.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: d9d3f8aff9ca807feb18a92133ba7a0d diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/MockGrapeshotUploadChunkResponse.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/MockGrapeshotUploadChunkResponse.cs new file mode 100644 index 0000000..e8c4653 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/MockGrapeshotUploadChunkResponse.cs @@ -0,0 +1,8 @@ +using ror.schema.upload; + +namespace ARDK.Grapeshot { + public class MockUploadChunkResponse : IGrapeshotUploadChunkResponse { + public ChunkStatus Status { get; set; } + public string StatusMessage { get; set; } + } +} \ No newline at end of file diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/MockGrapeshotUploadChunkResponse.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/MockGrapeshotUploadChunkResponse.cs.meta new file mode 100644 index 0000000..908ad6f --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/MockGrapeshotUploadChunkResponse.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 73d0ef425b52fb69678fd1f798eeed45 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/MockGrapeshotUploadData.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/MockGrapeshotUploadData.cs new file mode 100644 index 0000000..51dc4d0 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/MockGrapeshotUploadData.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; + +namespace ARDK.Grapeshot { + /// + /// Mock grapeshot upload data structure + /// + public class MockGrapeshotUploadData : IGrapeshotUploadData { + public string GcsBucket { get; private set; } + public int NumberOfChunks { get; private set; } + public ComposeData ComposeData { get; private set; } + public List ChunkData { get; private set; } + } +} \ No newline at end of file diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/MockGrapeshotUploadData.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/MockGrapeshotUploadData.cs.meta new file mode 100644 index 0000000..cc0a149 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/services/MockGrapeshotUploadData.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 46974589a803e020319f18ec99692630 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/unity_ext.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/unity_ext.meta new file mode 100644 index 0000000..dceee65 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/unity_ext.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5528b5d8e8af047ec9ab9620a593f85a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/unity_ext/WifiOnlyRate.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/unity_ext/WifiOnlyRate.cs new file mode 100644 index 0000000..7f39510 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/unity_ext/WifiOnlyRate.cs @@ -0,0 +1,38 @@ +using System; +using System.Threading; +using ror.schema.upload; +using UnityEngine; + +namespace Grapeshot { + public class WifiOnlyRate : ApplicationRate { + private readonly TimeSpan _updateTime; + + public WifiOnlyRate(TimeSpan updateTime) { + _updateTime = updateTime; + } + + public override void applicationClaimTicket(UploadChunkRequest chunkRequest, RateTicketReturn rateTicketReturn) { + // Wait indefinetly for internet. + while (!areFreeTickets()) { + // Check every 15 seconds. + Thread.Sleep(_updateTime); + } + + applicationTryClaimTicket(chunkRequest, rateTicketReturn); + } + + public override void applicationTryClaimTicket(UploadChunkRequest chunkRequest, + RateTicketReturn rateTicketReturn) { + if (areFreeTickets()) { + // Tickets must be allocated and held from the C# side until the C++ side has a safe reference to it. + // When the C# side is done we must call dispose! Otherwise the ticket will only be freed when GC is + // called. + using (var rateTicket = new RateTicket()) { rateTicketReturn.ret(rateTicket); } + } + } + + public override bool areFreeTickets() { + return Application.internetReachability == NetworkReachability.ReachableViaLocalAreaNetwork; + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/unity_ext/WifiOnlyRate.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/unity_ext/WifiOnlyRate.cs.meta new file mode 100644 index 0000000..49b8be6 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/grapeshot_unity_application/unity_ext/WifiOnlyRate.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: d7f7b5d9ee8d18a435d5af14f3cfbbcb diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto.meta new file mode 100644 index 0000000..c7f55e6 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3cc4c1ff40a884b5db19327644cc821e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp.meta new file mode 100644 index 0000000..d36666f --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4db364f2428b244628c8cdf82bd9aaf9 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/ArCommonMetadata.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/ArCommonMetadata.cs new file mode 100644 index 0000000..c096aba --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/ArCommonMetadata.cs @@ -0,0 +1,602 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: common/ar_common_metadata.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Niantic.ARDK.AR.Protobuf { + + /// Holder for reflection information generated from common/ar_common_metadata.proto + public static partial class ArCommonMetadataReflection { + + #region Descriptor + /// File descriptor for common/ar_common_metadata.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static ArCommonMetadataReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "Ch9jb21tb24vYXJfY29tbW9uX21ldGFkYXRhLnByb3RvEg1uYXIudGVsZW1l", + "dHJ5IuoBChBBUkNvbW1vbk1ldGFkYXRhEhYKDmFwcGxpY2F0aW9uX2lkGAEg", + "ASgJEhAKCHBsYXRmb3JtGAIgASgJEhQKDG1hbnVmYWN0dXJlchgDIAEoCRIU", + "CgxkZXZpY2VfbW9kZWwYBCABKAkSDwoHdXNlcl9pZBgFIAEoCRIRCgljbGll", + "bnRfaWQYBiABKAkSFAoMZGV2ZWxvcGVyX2lkGAcgASgJEhQKDGFyZGtfdmVy", + "c2lvbhgIIAEoCRIcChRhcmRrX2FwcF9pbnN0YW5jZV9pZBgJIAEoCRISCgpy", + "ZXF1ZXN0X2lkGAogASgJQlYKIWNvbS5uaWFudGljcHJvamVjdC5hcmRrLnRl", + "bGVtZXRyeVoWbmlhbnRpYy9hcmRrL3RlbGVtZXRyeaoCGE5pYW50aWMuQVJE", + "Sy5BUi5Qcm90b2J1ZmIGcHJvdG8z")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { }, + new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Niantic.ARDK.AR.Protobuf.ARCommonMetadata), global::Niantic.ARDK.AR.Protobuf.ARCommonMetadata.Parser, new[]{ "ApplicationId", "Platform", "Manufacturer", "DeviceModel", "UserId", "ClientId", "DeveloperId", "ArdkVersion", "ArdkAppInstanceId", "RequestId" }, null, null, null, null) + })); + } + #endregion + + } + #region Messages + public sealed partial class ARCommonMetadata : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ARCommonMetadata()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Niantic.ARDK.AR.Protobuf.ArCommonMetadataReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ARCommonMetadata() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ARCommonMetadata(ARCommonMetadata other) : this() { + applicationId_ = other.applicationId_; + platform_ = other.platform_; + manufacturer_ = other.manufacturer_; + deviceModel_ = other.deviceModel_; + userId_ = other.userId_; + clientId_ = other.clientId_; + developerId_ = other.developerId_; + ardkVersion_ = other.ardkVersion_; + ardkAppInstanceId_ = other.ardkAppInstanceId_; + requestId_ = other.requestId_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ARCommonMetadata Clone() { + return new ARCommonMetadata(this); + } + + /// Field number for the "application_id" field. + public const int ApplicationIdFieldNumber = 1; + private string applicationId_ = ""; + /// + /// Name/ID of the application which sent this request + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string ApplicationId { + get { return applicationId_; } + set { + applicationId_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "platform" field. + public const int PlatformFieldNumber = 2; + private string platform_ = ""; + /// + /// e.g. IOS, android + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Platform { + get { return platform_; } + set { + platform_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "manufacturer" field. + public const int ManufacturerFieldNumber = 3; + private string manufacturer_ = ""; + /// + /// e.g. Apple, Google + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Manufacturer { + get { return manufacturer_; } + set { + manufacturer_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "device_model" field. + public const int DeviceModelFieldNumber = 4; + private string deviceModel_ = ""; + /// + /// e.g. iPhone 12 + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string DeviceModel { + get { return deviceModel_; } + set { + deviceModel_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "user_id" field. + public const int UserIdFieldNumber = 5; + private string userId_ = ""; + /// + /// Verified user ID + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string UserId { + get { return userId_; } + set { + userId_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "client_id" field. + public const int ClientIdFieldNumber = 6; + private string clientId_ = ""; + /// + /// Client device ID, provided by ARDK + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string ClientId { + get { return clientId_; } + set { + clientId_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "developer_id" field. + public const int DeveloperIdFieldNumber = 7; + private string developerId_ = ""; + /// + /// Developer ID, resolved from API key + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string DeveloperId { + get { return developerId_; } + set { + developerId_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "ardk_version" field. + public const int ArdkVersionFieldNumber = 8; + private string ardkVersion_ = ""; + /// + /// ARDK version + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string ArdkVersion { + get { return ardkVersion_; } + set { + ardkVersion_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "ardk_app_instance_id" field. + public const int ArdkAppInstanceIdFieldNumber = 9; + private string ardkAppInstanceId_ = ""; + /// + /// ARDK application instance ID + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string ArdkAppInstanceId { + get { return ardkAppInstanceId_; } + set { + ardkAppInstanceId_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "request_id" field. + public const int RequestIdFieldNumber = 10; + private string requestId_ = ""; + /// + /// Guid request id encoded into a string. May be null + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string RequestId { + get { return requestId_; } + set { + requestId_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ARCommonMetadata); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ARCommonMetadata other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (ApplicationId != other.ApplicationId) return false; + if (Platform != other.Platform) return false; + if (Manufacturer != other.Manufacturer) return false; + if (DeviceModel != other.DeviceModel) return false; + if (UserId != other.UserId) return false; + if (ClientId != other.ClientId) return false; + if (DeveloperId != other.DeveloperId) return false; + if (ArdkVersion != other.ArdkVersion) return false; + if (ArdkAppInstanceId != other.ArdkAppInstanceId) return false; + if (RequestId != other.RequestId) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (ApplicationId.Length != 0) hash ^= ApplicationId.GetHashCode(); + if (Platform.Length != 0) hash ^= Platform.GetHashCode(); + if (Manufacturer.Length != 0) hash ^= Manufacturer.GetHashCode(); + if (DeviceModel.Length != 0) hash ^= DeviceModel.GetHashCode(); + if (UserId.Length != 0) hash ^= UserId.GetHashCode(); + if (ClientId.Length != 0) hash ^= ClientId.GetHashCode(); + if (DeveloperId.Length != 0) hash ^= DeveloperId.GetHashCode(); + if (ArdkVersion.Length != 0) hash ^= ArdkVersion.GetHashCode(); + if (ArdkAppInstanceId.Length != 0) hash ^= ArdkAppInstanceId.GetHashCode(); + if (RequestId.Length != 0) hash ^= RequestId.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (ApplicationId.Length != 0) { + output.WriteRawTag(10); + output.WriteString(ApplicationId); + } + if (Platform.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Platform); + } + if (Manufacturer.Length != 0) { + output.WriteRawTag(26); + output.WriteString(Manufacturer); + } + if (DeviceModel.Length != 0) { + output.WriteRawTag(34); + output.WriteString(DeviceModel); + } + if (UserId.Length != 0) { + output.WriteRawTag(42); + output.WriteString(UserId); + } + if (ClientId.Length != 0) { + output.WriteRawTag(50); + output.WriteString(ClientId); + } + if (DeveloperId.Length != 0) { + output.WriteRawTag(58); + output.WriteString(DeveloperId); + } + if (ArdkVersion.Length != 0) { + output.WriteRawTag(66); + output.WriteString(ArdkVersion); + } + if (ArdkAppInstanceId.Length != 0) { + output.WriteRawTag(74); + output.WriteString(ArdkAppInstanceId); + } + if (RequestId.Length != 0) { + output.WriteRawTag(82); + output.WriteString(RequestId); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (ApplicationId.Length != 0) { + output.WriteRawTag(10); + output.WriteString(ApplicationId); + } + if (Platform.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Platform); + } + if (Manufacturer.Length != 0) { + output.WriteRawTag(26); + output.WriteString(Manufacturer); + } + if (DeviceModel.Length != 0) { + output.WriteRawTag(34); + output.WriteString(DeviceModel); + } + if (UserId.Length != 0) { + output.WriteRawTag(42); + output.WriteString(UserId); + } + if (ClientId.Length != 0) { + output.WriteRawTag(50); + output.WriteString(ClientId); + } + if (DeveloperId.Length != 0) { + output.WriteRawTag(58); + output.WriteString(DeveloperId); + } + if (ArdkVersion.Length != 0) { + output.WriteRawTag(66); + output.WriteString(ArdkVersion); + } + if (ArdkAppInstanceId.Length != 0) { + output.WriteRawTag(74); + output.WriteString(ArdkAppInstanceId); + } + if (RequestId.Length != 0) { + output.WriteRawTag(82); + output.WriteString(RequestId); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (ApplicationId.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(ApplicationId); + } + if (Platform.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Platform); + } + if (Manufacturer.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Manufacturer); + } + if (DeviceModel.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(DeviceModel); + } + if (UserId.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(UserId); + } + if (ClientId.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(ClientId); + } + if (DeveloperId.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(DeveloperId); + } + if (ArdkVersion.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(ArdkVersion); + } + if (ArdkAppInstanceId.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(ArdkAppInstanceId); + } + if (RequestId.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(RequestId); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ARCommonMetadata other) { + if (other == null) { + return; + } + if (other.ApplicationId.Length != 0) { + ApplicationId = other.ApplicationId; + } + if (other.Platform.Length != 0) { + Platform = other.Platform; + } + if (other.Manufacturer.Length != 0) { + Manufacturer = other.Manufacturer; + } + if (other.DeviceModel.Length != 0) { + DeviceModel = other.DeviceModel; + } + if (other.UserId.Length != 0) { + UserId = other.UserId; + } + if (other.ClientId.Length != 0) { + ClientId = other.ClientId; + } + if (other.DeveloperId.Length != 0) { + DeveloperId = other.DeveloperId; + } + if (other.ArdkVersion.Length != 0) { + ArdkVersion = other.ArdkVersion; + } + if (other.ArdkAppInstanceId.Length != 0) { + ArdkAppInstanceId = other.ArdkAppInstanceId; + } + if (other.RequestId.Length != 0) { + RequestId = other.RequestId; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + ApplicationId = input.ReadString(); + break; + } + case 18: { + Platform = input.ReadString(); + break; + } + case 26: { + Manufacturer = input.ReadString(); + break; + } + case 34: { + DeviceModel = input.ReadString(); + break; + } + case 42: { + UserId = input.ReadString(); + break; + } + case 50: { + ClientId = input.ReadString(); + break; + } + case 58: { + DeveloperId = input.ReadString(); + break; + } + case 66: { + ArdkVersion = input.ReadString(); + break; + } + case 74: { + ArdkAppInstanceId = input.ReadString(); + break; + } + case 82: { + RequestId = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + ApplicationId = input.ReadString(); + break; + } + case 18: { + Platform = input.ReadString(); + break; + } + case 26: { + Manufacturer = input.ReadString(); + break; + } + case 34: { + DeviceModel = input.ReadString(); + break; + } + case 42: { + UserId = input.ReadString(); + break; + } + case 50: { + ClientId = input.ReadString(); + break; + } + case 58: { + DeveloperId = input.ReadString(); + break; + } + case 66: { + ArdkVersion = input.ReadString(); + break; + } + case 74: { + ArdkAppInstanceId = input.ReadString(); + break; + } + case 82: { + RequestId = input.ReadString(); + break; + } + } + } + } + #endif + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/ArCommonMetadata.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/ArCommonMetadata.cs.meta new file mode 100644 index 0000000..2a4a813 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/ArCommonMetadata.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: a298aac09bfccda3cebb651bd68d3a25 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/ArdkTelemetry.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/ArdkTelemetry.cs new file mode 100644 index 0000000..3e8dcb5 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/ArdkTelemetry.cs @@ -0,0 +1,1926 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: common/telemetry/ardk_telemetry.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Niantic.ARDK.AR.Protobuf { + + /// Holder for reflection information generated from common/telemetry/ardk_telemetry.proto + public static partial class ArdkTelemetryReflection { + + #region Descriptor + /// File descriptor for common/telemetry/ardk_telemetry.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static ArdkTelemetryReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "CiVjb21tb24vdGVsZW1ldHJ5L2FyZGtfdGVsZW1ldHJ5LnByb3RvEg1uYXIu", + "dGVsZW1ldHJ5Gh9jb21tb24vYXJfY29tbW9uX21ldGFkYXRhLnByb3RvGh9n", + "b29nbGUvcHJvdG9idWYvdGltZXN0YW1wLnByb3RvIqcEChZBUkRLVGVsZW1l", + "dHJ5T21uaVByb3RvEkIKFGluaXRpYWxpemF0aW9uX2V2ZW50GAEgASgLMiIu", + "bmFyLnRlbGVtZXRyeS5Jbml0aWFsaXphdGlvbkV2ZW50SAASOQoQYXJfc2Vz", + "c2lvbl9ldmVudBgCIAEoCzIdLm5hci50ZWxlbWV0cnkuQVJTZXNzaW9uRXZl", + "bnRIABJHChdsaWdodHNoaXBfc2VydmljZV9ldmVudBgDIAEoCzIkLm5hci50", + "ZWxlbWV0cnkuTGlnaHRzaGlwU2VydmljZUV2ZW50SAASUQocbXVsdGlwbGF5", + "ZXJfY29ubmVjdGlvbl9ldmVudBgEIAEoCzIpLm5hci50ZWxlbWV0cnkuTXVs", + "dGlwbGF5ZXJDb25uZWN0aW9uRXZlbnRIABJbCiFlbmFibGVfY29udGV4dHVh", + "bF9hd2FyZW5lc3NfZXZlbnQYBSABKAsyLi5uYXIudGVsZW1ldHJ5LkVuYWJs", + "ZWRDb250ZXh0dWFsQXdhcmVuZXNzRXZlbnRIABI6ChBjb21tb25fbWV0YV9k", + "YXRhGOgHIAEoCzIfLm5hci50ZWxlbWV0cnkuQVJDb21tb25NZXRhZGF0YRIW", + "Cg1kZXZlbG9wZXJfa2V5GOkHIAEoCRIuCgl0aW1lc3RhbXAY6gcgASgLMhou", + "Z29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcEIRCg90ZWxlbWV0cnlfZXZlbnQi", + "QgoTSW5pdGlhbGl6YXRpb25FdmVudBIUCgxpbnN0YWxsX21vZGUYASABKAkS", + "FQoNbG9jYWxlX3JlZ2lvbhgCIAEoCSKlAQoOQVJTZXNzaW9uRXZlbnQSOgoN", + "c2Vzc2lvbl9zdGF0ZRgBIAEoDjIjLm5hci50ZWxlbWV0cnkuQVJTZXNzaW9u", + "RXZlbnQuU3RhdGUSEgoKc2Vzc2lvbl9pZBgCIAEoCSJDCgVTdGF0ZRILCgdV", + "TktOT1dOEAASCwoHQ1JFQVRFRBABEgcKA1JVThACEgkKBVBBVVNFEAMSDAoI", + "RElTUE9TRUQQBCIXChVMaWdodHNoaXBTZXJ2aWNlRXZlbnQi2QMKGk11bHRp", + "cGxheWVyQ29ubmVjdGlvbkV2ZW50EkoKCmNvbm5lY3Rpb24YASABKA4yNi5u", + "YXIudGVsZW1ldHJ5Lk11bHRpcGxheWVyQ29ubmVjdGlvbkV2ZW50LkNvbm5l", + "Y3RTdGF0ZRIhChlhcmJlX3Nlc3NzaW9uX2luc3RhbmNlX2lkGAIgASgJEhIK", + "CnNlc3Npb25faWQYAyABKAkSRwoKcGVlcl9zdGF0ZRgEIAEoDjIzLm5hci50", + "ZWxlbWV0cnkuTXVsdGlwbGF5ZXJDb25uZWN0aW9uRXZlbnQuUGVlclN0YXRl", + "IlMKDENvbm5lY3RTdGF0ZRILCgdVTktOT1dOEAASCQoFU1RBUlQQARIICgRK", + "T0lOEAISDQoJQ09OTkVDVEVEEAMSCQoFTEVBVkUQBBIHCgNFTkQQBSKZAQoJ", + "UGVlclN0YXRlEhEKDVNUQVRFX1VOS05PV04QABIQCgxJTklUSUFMSVpJTkcQ", + "ARIhCh1XQUlUSU5HX0ZPUl9MT0NBTElaQVRJT05fREFUQRACEg4KCkxPQ0FM", + "SVpJTkcQAxIPCgtTVEFCSUxJWklORxAEEgoKBlNUQUJMRRAFEgsKB0xJTUlU", + "RUQQBhIKCgZGQUlMRUQQByJkCh9FbmFibGVkQ29udGV4dHVhbEF3YXJlbmVz", + "c0V2ZW50Eg8KB21lc2hpbmcYASABKAgSDgoGZnVzaW9uGAIgASgIEg0KBWRl", + "cHRoGAMgASgIEhEKCXNlbWFudGljcxgEIAEoCEJWCiFjb20ubmlhbnRpY3By", + "b2plY3QuYXJkay50ZWxlbWV0cnlaFm5pYW50aWMvYXJkay90ZWxlbWV0cnmq", + "AhhOaWFudGljLkFSREsuQVIuUHJvdG9idWZiBnByb3RvMw==")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { global::Niantic.ARDK.AR.Protobuf.ArCommonMetadataReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.TimestampReflection.Descriptor, }, + new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Niantic.ARDK.AR.Protobuf.ARDKTelemetryOmniProto), global::Niantic.ARDK.AR.Protobuf.ARDKTelemetryOmniProto.Parser, new[]{ "InitializationEvent", "ArSessionEvent", "LightshipServiceEvent", "MultiplayerConnectionEvent", "EnableContextualAwarenessEvent", "CommonMetaData", "DeveloperKey", "Timestamp" }, new[]{ "TelemetryEvent" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Niantic.ARDK.AR.Protobuf.InitializationEvent), global::Niantic.ARDK.AR.Protobuf.InitializationEvent.Parser, new[]{ "InstallMode", "LocaleRegion" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Niantic.ARDK.AR.Protobuf.ARSessionEvent), global::Niantic.ARDK.AR.Protobuf.ARSessionEvent.Parser, new[]{ "SessionState", "SessionId" }, null, new[]{ typeof(global::Niantic.ARDK.AR.Protobuf.ARSessionEvent.Types.State) }, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Niantic.ARDK.AR.Protobuf.LightshipServiceEvent), global::Niantic.ARDK.AR.Protobuf.LightshipServiceEvent.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Niantic.ARDK.AR.Protobuf.MultiplayerConnectionEvent), global::Niantic.ARDK.AR.Protobuf.MultiplayerConnectionEvent.Parser, new[]{ "Connection", "ArbeSesssionInstanceId", "SessionId", "PeerState" }, null, new[]{ typeof(global::Niantic.ARDK.AR.Protobuf.MultiplayerConnectionEvent.Types.ConnectState), typeof(global::Niantic.ARDK.AR.Protobuf.MultiplayerConnectionEvent.Types.PeerState) }, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Niantic.ARDK.AR.Protobuf.EnabledContextualAwarenessEvent), global::Niantic.ARDK.AR.Protobuf.EnabledContextualAwarenessEvent.Parser, new[]{ "Meshing", "Fusion", "Depth", "Semantics" }, null, null, null, null) + })); + } + #endregion + + } + #region Messages + public sealed partial class ARDKTelemetryOmniProto : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ARDKTelemetryOmniProto()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Niantic.ARDK.AR.Protobuf.ArdkTelemetryReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ARDKTelemetryOmniProto() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ARDKTelemetryOmniProto(ARDKTelemetryOmniProto other) : this() { + commonMetaData_ = other.commonMetaData_ != null ? other.commonMetaData_.Clone() : null; + developerKey_ = other.developerKey_; + timestamp_ = other.timestamp_ != null ? other.timestamp_.Clone() : null; + switch (other.TelemetryEventCase) { + case TelemetryEventOneofCase.InitializationEvent: + InitializationEvent = other.InitializationEvent.Clone(); + break; + case TelemetryEventOneofCase.ArSessionEvent: + ArSessionEvent = other.ArSessionEvent.Clone(); + break; + case TelemetryEventOneofCase.LightshipServiceEvent: + LightshipServiceEvent = other.LightshipServiceEvent.Clone(); + break; + case TelemetryEventOneofCase.MultiplayerConnectionEvent: + MultiplayerConnectionEvent = other.MultiplayerConnectionEvent.Clone(); + break; + case TelemetryEventOneofCase.EnableContextualAwarenessEvent: + EnableContextualAwarenessEvent = other.EnableContextualAwarenessEvent.Clone(); + break; + } + + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ARDKTelemetryOmniProto Clone() { + return new ARDKTelemetryOmniProto(this); + } + + /// Field number for the "initialization_event" field. + public const int InitializationEventFieldNumber = 1; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Niantic.ARDK.AR.Protobuf.InitializationEvent InitializationEvent { + get { return telemetryEventCase_ == TelemetryEventOneofCase.InitializationEvent ? (global::Niantic.ARDK.AR.Protobuf.InitializationEvent) telemetryEvent_ : null; } + set { + telemetryEvent_ = value; + telemetryEventCase_ = value == null ? TelemetryEventOneofCase.None : TelemetryEventOneofCase.InitializationEvent; + } + } + + /// Field number for the "ar_session_event" field. + public const int ArSessionEventFieldNumber = 2; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Niantic.ARDK.AR.Protobuf.ARSessionEvent ArSessionEvent { + get { return telemetryEventCase_ == TelemetryEventOneofCase.ArSessionEvent ? (global::Niantic.ARDK.AR.Protobuf.ARSessionEvent) telemetryEvent_ : null; } + set { + telemetryEvent_ = value; + telemetryEventCase_ = value == null ? TelemetryEventOneofCase.None : TelemetryEventOneofCase.ArSessionEvent; + } + } + + /// Field number for the "lightship_service_event" field. + public const int LightshipServiceEventFieldNumber = 3; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Niantic.ARDK.AR.Protobuf.LightshipServiceEvent LightshipServiceEvent { + get { return telemetryEventCase_ == TelemetryEventOneofCase.LightshipServiceEvent ? (global::Niantic.ARDK.AR.Protobuf.LightshipServiceEvent) telemetryEvent_ : null; } + set { + telemetryEvent_ = value; + telemetryEventCase_ = value == null ? TelemetryEventOneofCase.None : TelemetryEventOneofCase.LightshipServiceEvent; + } + } + + /// Field number for the "multiplayer_connection_event" field. + public const int MultiplayerConnectionEventFieldNumber = 4; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Niantic.ARDK.AR.Protobuf.MultiplayerConnectionEvent MultiplayerConnectionEvent { + get { return telemetryEventCase_ == TelemetryEventOneofCase.MultiplayerConnectionEvent ? (global::Niantic.ARDK.AR.Protobuf.MultiplayerConnectionEvent) telemetryEvent_ : null; } + set { + telemetryEvent_ = value; + telemetryEventCase_ = value == null ? TelemetryEventOneofCase.None : TelemetryEventOneofCase.MultiplayerConnectionEvent; + } + } + + /// Field number for the "enable_contextual_awareness_event" field. + public const int EnableContextualAwarenessEventFieldNumber = 5; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Niantic.ARDK.AR.Protobuf.EnabledContextualAwarenessEvent EnableContextualAwarenessEvent { + get { return telemetryEventCase_ == TelemetryEventOneofCase.EnableContextualAwarenessEvent ? (global::Niantic.ARDK.AR.Protobuf.EnabledContextualAwarenessEvent) telemetryEvent_ : null; } + set { + telemetryEvent_ = value; + telemetryEventCase_ = value == null ? TelemetryEventOneofCase.None : TelemetryEventOneofCase.EnableContextualAwarenessEvent; + } + } + + /// Field number for the "common_meta_data" field. + public const int CommonMetaDataFieldNumber = 1000; + private global::Niantic.ARDK.AR.Protobuf.ARCommonMetadata commonMetaData_; + /// + /// Common meta data for all the telemetry protos. The field will be filled in on Unity. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Niantic.ARDK.AR.Protobuf.ARCommonMetadata CommonMetaData { + get { return commonMetaData_; } + set { + commonMetaData_ = value; + } + } + + /// Field number for the "developer_key" field. + public const int DeveloperKeyFieldNumber = 1001; + private string developerKey_ = ""; + /// + /// Active developer key + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string DeveloperKey { + get { return developerKey_; } + set { + developerKey_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "timestamp" field. + public const int TimestampFieldNumber = 1002; + private global::Google.Protobuf.WellKnownTypes.Timestamp timestamp_; + /// + /// Timestamp from the current device representing a point in time independent of any time zone or calendar. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Google.Protobuf.WellKnownTypes.Timestamp Timestamp { + get { return timestamp_; } + set { + timestamp_ = value; + } + } + + private object telemetryEvent_; + /// Enum of possible cases for the "telemetry_event" oneof. + public enum TelemetryEventOneofCase { + None = 0, + InitializationEvent = 1, + ArSessionEvent = 2, + LightshipServiceEvent = 3, + MultiplayerConnectionEvent = 4, + EnableContextualAwarenessEvent = 5, + } + private TelemetryEventOneofCase telemetryEventCase_ = TelemetryEventOneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public TelemetryEventOneofCase TelemetryEventCase { + get { return telemetryEventCase_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void ClearTelemetryEvent() { + telemetryEventCase_ = TelemetryEventOneofCase.None; + telemetryEvent_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ARDKTelemetryOmniProto); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ARDKTelemetryOmniProto other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(InitializationEvent, other.InitializationEvent)) return false; + if (!object.Equals(ArSessionEvent, other.ArSessionEvent)) return false; + if (!object.Equals(LightshipServiceEvent, other.LightshipServiceEvent)) return false; + if (!object.Equals(MultiplayerConnectionEvent, other.MultiplayerConnectionEvent)) return false; + if (!object.Equals(EnableContextualAwarenessEvent, other.EnableContextualAwarenessEvent)) return false; + if (!object.Equals(CommonMetaData, other.CommonMetaData)) return false; + if (DeveloperKey != other.DeveloperKey) return false; + if (!object.Equals(Timestamp, other.Timestamp)) return false; + if (TelemetryEventCase != other.TelemetryEventCase) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (telemetryEventCase_ == TelemetryEventOneofCase.InitializationEvent) hash ^= InitializationEvent.GetHashCode(); + if (telemetryEventCase_ == TelemetryEventOneofCase.ArSessionEvent) hash ^= ArSessionEvent.GetHashCode(); + if (telemetryEventCase_ == TelemetryEventOneofCase.LightshipServiceEvent) hash ^= LightshipServiceEvent.GetHashCode(); + if (telemetryEventCase_ == TelemetryEventOneofCase.MultiplayerConnectionEvent) hash ^= MultiplayerConnectionEvent.GetHashCode(); + if (telemetryEventCase_ == TelemetryEventOneofCase.EnableContextualAwarenessEvent) hash ^= EnableContextualAwarenessEvent.GetHashCode(); + if (commonMetaData_ != null) hash ^= CommonMetaData.GetHashCode(); + if (DeveloperKey.Length != 0) hash ^= DeveloperKey.GetHashCode(); + if (timestamp_ != null) hash ^= Timestamp.GetHashCode(); + hash ^= (int) telemetryEventCase_; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (telemetryEventCase_ == TelemetryEventOneofCase.InitializationEvent) { + output.WriteRawTag(10); + output.WriteMessage(InitializationEvent); + } + if (telemetryEventCase_ == TelemetryEventOneofCase.ArSessionEvent) { + output.WriteRawTag(18); + output.WriteMessage(ArSessionEvent); + } + if (telemetryEventCase_ == TelemetryEventOneofCase.LightshipServiceEvent) { + output.WriteRawTag(26); + output.WriteMessage(LightshipServiceEvent); + } + if (telemetryEventCase_ == TelemetryEventOneofCase.MultiplayerConnectionEvent) { + output.WriteRawTag(34); + output.WriteMessage(MultiplayerConnectionEvent); + } + if (telemetryEventCase_ == TelemetryEventOneofCase.EnableContextualAwarenessEvent) { + output.WriteRawTag(42); + output.WriteMessage(EnableContextualAwarenessEvent); + } + if (commonMetaData_ != null) { + output.WriteRawTag(194, 62); + output.WriteMessage(CommonMetaData); + } + if (DeveloperKey.Length != 0) { + output.WriteRawTag(202, 62); + output.WriteString(DeveloperKey); + } + if (timestamp_ != null) { + output.WriteRawTag(210, 62); + output.WriteMessage(Timestamp); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (telemetryEventCase_ == TelemetryEventOneofCase.InitializationEvent) { + output.WriteRawTag(10); + output.WriteMessage(InitializationEvent); + } + if (telemetryEventCase_ == TelemetryEventOneofCase.ArSessionEvent) { + output.WriteRawTag(18); + output.WriteMessage(ArSessionEvent); + } + if (telemetryEventCase_ == TelemetryEventOneofCase.LightshipServiceEvent) { + output.WriteRawTag(26); + output.WriteMessage(LightshipServiceEvent); + } + if (telemetryEventCase_ == TelemetryEventOneofCase.MultiplayerConnectionEvent) { + output.WriteRawTag(34); + output.WriteMessage(MultiplayerConnectionEvent); + } + if (telemetryEventCase_ == TelemetryEventOneofCase.EnableContextualAwarenessEvent) { + output.WriteRawTag(42); + output.WriteMessage(EnableContextualAwarenessEvent); + } + if (commonMetaData_ != null) { + output.WriteRawTag(194, 62); + output.WriteMessage(CommonMetaData); + } + if (DeveloperKey.Length != 0) { + output.WriteRawTag(202, 62); + output.WriteString(DeveloperKey); + } + if (timestamp_ != null) { + output.WriteRawTag(210, 62); + output.WriteMessage(Timestamp); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (telemetryEventCase_ == TelemetryEventOneofCase.InitializationEvent) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(InitializationEvent); + } + if (telemetryEventCase_ == TelemetryEventOneofCase.ArSessionEvent) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(ArSessionEvent); + } + if (telemetryEventCase_ == TelemetryEventOneofCase.LightshipServiceEvent) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(LightshipServiceEvent); + } + if (telemetryEventCase_ == TelemetryEventOneofCase.MultiplayerConnectionEvent) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(MultiplayerConnectionEvent); + } + if (telemetryEventCase_ == TelemetryEventOneofCase.EnableContextualAwarenessEvent) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(EnableContextualAwarenessEvent); + } + if (commonMetaData_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(CommonMetaData); + } + if (DeveloperKey.Length != 0) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(DeveloperKey); + } + if (timestamp_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(Timestamp); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ARDKTelemetryOmniProto other) { + if (other == null) { + return; + } + if (other.commonMetaData_ != null) { + if (commonMetaData_ == null) { + CommonMetaData = new global::Niantic.ARDK.AR.Protobuf.ARCommonMetadata(); + } + CommonMetaData.MergeFrom(other.CommonMetaData); + } + if (other.DeveloperKey.Length != 0) { + DeveloperKey = other.DeveloperKey; + } + if (other.timestamp_ != null) { + if (timestamp_ == null) { + Timestamp = new global::Google.Protobuf.WellKnownTypes.Timestamp(); + } + Timestamp.MergeFrom(other.Timestamp); + } + switch (other.TelemetryEventCase) { + case TelemetryEventOneofCase.InitializationEvent: + if (InitializationEvent == null) { + InitializationEvent = new global::Niantic.ARDK.AR.Protobuf.InitializationEvent(); + } + InitializationEvent.MergeFrom(other.InitializationEvent); + break; + case TelemetryEventOneofCase.ArSessionEvent: + if (ArSessionEvent == null) { + ArSessionEvent = new global::Niantic.ARDK.AR.Protobuf.ARSessionEvent(); + } + ArSessionEvent.MergeFrom(other.ArSessionEvent); + break; + case TelemetryEventOneofCase.LightshipServiceEvent: + if (LightshipServiceEvent == null) { + LightshipServiceEvent = new global::Niantic.ARDK.AR.Protobuf.LightshipServiceEvent(); + } + LightshipServiceEvent.MergeFrom(other.LightshipServiceEvent); + break; + case TelemetryEventOneofCase.MultiplayerConnectionEvent: + if (MultiplayerConnectionEvent == null) { + MultiplayerConnectionEvent = new global::Niantic.ARDK.AR.Protobuf.MultiplayerConnectionEvent(); + } + MultiplayerConnectionEvent.MergeFrom(other.MultiplayerConnectionEvent); + break; + case TelemetryEventOneofCase.EnableContextualAwarenessEvent: + if (EnableContextualAwarenessEvent == null) { + EnableContextualAwarenessEvent = new global::Niantic.ARDK.AR.Protobuf.EnabledContextualAwarenessEvent(); + } + EnableContextualAwarenessEvent.MergeFrom(other.EnableContextualAwarenessEvent); + break; + } + + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + global::Niantic.ARDK.AR.Protobuf.InitializationEvent subBuilder = new global::Niantic.ARDK.AR.Protobuf.InitializationEvent(); + if (telemetryEventCase_ == TelemetryEventOneofCase.InitializationEvent) { + subBuilder.MergeFrom(InitializationEvent); + } + input.ReadMessage(subBuilder); + InitializationEvent = subBuilder; + break; + } + case 18: { + global::Niantic.ARDK.AR.Protobuf.ARSessionEvent subBuilder = new global::Niantic.ARDK.AR.Protobuf.ARSessionEvent(); + if (telemetryEventCase_ == TelemetryEventOneofCase.ArSessionEvent) { + subBuilder.MergeFrom(ArSessionEvent); + } + input.ReadMessage(subBuilder); + ArSessionEvent = subBuilder; + break; + } + case 26: { + global::Niantic.ARDK.AR.Protobuf.LightshipServiceEvent subBuilder = new global::Niantic.ARDK.AR.Protobuf.LightshipServiceEvent(); + if (telemetryEventCase_ == TelemetryEventOneofCase.LightshipServiceEvent) { + subBuilder.MergeFrom(LightshipServiceEvent); + } + input.ReadMessage(subBuilder); + LightshipServiceEvent = subBuilder; + break; + } + case 34: { + global::Niantic.ARDK.AR.Protobuf.MultiplayerConnectionEvent subBuilder = new global::Niantic.ARDK.AR.Protobuf.MultiplayerConnectionEvent(); + if (telemetryEventCase_ == TelemetryEventOneofCase.MultiplayerConnectionEvent) { + subBuilder.MergeFrom(MultiplayerConnectionEvent); + } + input.ReadMessage(subBuilder); + MultiplayerConnectionEvent = subBuilder; + break; + } + case 42: { + global::Niantic.ARDK.AR.Protobuf.EnabledContextualAwarenessEvent subBuilder = new global::Niantic.ARDK.AR.Protobuf.EnabledContextualAwarenessEvent(); + if (telemetryEventCase_ == TelemetryEventOneofCase.EnableContextualAwarenessEvent) { + subBuilder.MergeFrom(EnableContextualAwarenessEvent); + } + input.ReadMessage(subBuilder); + EnableContextualAwarenessEvent = subBuilder; + break; + } + case 8002: { + if (commonMetaData_ == null) { + CommonMetaData = new global::Niantic.ARDK.AR.Protobuf.ARCommonMetadata(); + } + input.ReadMessage(CommonMetaData); + break; + } + case 8010: { + DeveloperKey = input.ReadString(); + break; + } + case 8018: { + if (timestamp_ == null) { + Timestamp = new global::Google.Protobuf.WellKnownTypes.Timestamp(); + } + input.ReadMessage(Timestamp); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + global::Niantic.ARDK.AR.Protobuf.InitializationEvent subBuilder = new global::Niantic.ARDK.AR.Protobuf.InitializationEvent(); + if (telemetryEventCase_ == TelemetryEventOneofCase.InitializationEvent) { + subBuilder.MergeFrom(InitializationEvent); + } + input.ReadMessage(subBuilder); + InitializationEvent = subBuilder; + break; + } + case 18: { + global::Niantic.ARDK.AR.Protobuf.ARSessionEvent subBuilder = new global::Niantic.ARDK.AR.Protobuf.ARSessionEvent(); + if (telemetryEventCase_ == TelemetryEventOneofCase.ArSessionEvent) { + subBuilder.MergeFrom(ArSessionEvent); + } + input.ReadMessage(subBuilder); + ArSessionEvent = subBuilder; + break; + } + case 26: { + global::Niantic.ARDK.AR.Protobuf.LightshipServiceEvent subBuilder = new global::Niantic.ARDK.AR.Protobuf.LightshipServiceEvent(); + if (telemetryEventCase_ == TelemetryEventOneofCase.LightshipServiceEvent) { + subBuilder.MergeFrom(LightshipServiceEvent); + } + input.ReadMessage(subBuilder); + LightshipServiceEvent = subBuilder; + break; + } + case 34: { + global::Niantic.ARDK.AR.Protobuf.MultiplayerConnectionEvent subBuilder = new global::Niantic.ARDK.AR.Protobuf.MultiplayerConnectionEvent(); + if (telemetryEventCase_ == TelemetryEventOneofCase.MultiplayerConnectionEvent) { + subBuilder.MergeFrom(MultiplayerConnectionEvent); + } + input.ReadMessage(subBuilder); + MultiplayerConnectionEvent = subBuilder; + break; + } + case 42: { + global::Niantic.ARDK.AR.Protobuf.EnabledContextualAwarenessEvent subBuilder = new global::Niantic.ARDK.AR.Protobuf.EnabledContextualAwarenessEvent(); + if (telemetryEventCase_ == TelemetryEventOneofCase.EnableContextualAwarenessEvent) { + subBuilder.MergeFrom(EnableContextualAwarenessEvent); + } + input.ReadMessage(subBuilder); + EnableContextualAwarenessEvent = subBuilder; + break; + } + case 8002: { + if (commonMetaData_ == null) { + CommonMetaData = new global::Niantic.ARDK.AR.Protobuf.ARCommonMetadata(); + } + input.ReadMessage(CommonMetaData); + break; + } + case 8010: { + DeveloperKey = input.ReadString(); + break; + } + case 8018: { + if (timestamp_ == null) { + Timestamp = new global::Google.Protobuf.WellKnownTypes.Timestamp(); + } + input.ReadMessage(Timestamp); + break; + } + } + } + } + #endif + + } + + /// + /// Protobuf provides a mutable_ function to access the message members while set_ function to other members. + /// They + /// Note, since we are using macros to implement the telemetry events at ARDK, so that developers do not need + /// to deal with constructing proto message. As Protobuf provides a mutable_ function to access the message members + /// while set_ function to other members. As limitation, all the telemetry message can't be nested by another message + /// for simplicity purpose.. + /// + public sealed partial class InitializationEvent : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new InitializationEvent()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Niantic.ARDK.AR.Protobuf.ArdkTelemetryReflection.Descriptor.MessageTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public InitializationEvent() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public InitializationEvent(InitializationEvent other) : this() { + installMode_ = other.installMode_; + localeRegion_ = other.localeRegion_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public InitializationEvent Clone() { + return new InitializationEvent(this); + } + + /// Field number for the "install_mode" field. + public const int InstallModeFieldNumber = 1; + private string installMode_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string InstallMode { + get { return installMode_; } + set { + installMode_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "locale_region" field. + public const int LocaleRegionFieldNumber = 2; + private string localeRegion_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string LocaleRegion { + get { return localeRegion_; } + set { + localeRegion_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as InitializationEvent); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(InitializationEvent other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (InstallMode != other.InstallMode) return false; + if (LocaleRegion != other.LocaleRegion) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (InstallMode.Length != 0) hash ^= InstallMode.GetHashCode(); + if (LocaleRegion.Length != 0) hash ^= LocaleRegion.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (InstallMode.Length != 0) { + output.WriteRawTag(10); + output.WriteString(InstallMode); + } + if (LocaleRegion.Length != 0) { + output.WriteRawTag(18); + output.WriteString(LocaleRegion); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (InstallMode.Length != 0) { + output.WriteRawTag(10); + output.WriteString(InstallMode); + } + if (LocaleRegion.Length != 0) { + output.WriteRawTag(18); + output.WriteString(LocaleRegion); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (InstallMode.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(InstallMode); + } + if (LocaleRegion.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(LocaleRegion); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(InitializationEvent other) { + if (other == null) { + return; + } + if (other.InstallMode.Length != 0) { + InstallMode = other.InstallMode; + } + if (other.LocaleRegion.Length != 0) { + LocaleRegion = other.LocaleRegion; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + InstallMode = input.ReadString(); + break; + } + case 18: { + LocaleRegion = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + InstallMode = input.ReadString(); + break; + } + case 18: { + LocaleRegion = input.ReadString(); + break; + } + } + } + } + #endif + + } + + public sealed partial class ARSessionEvent : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ARSessionEvent()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Niantic.ARDK.AR.Protobuf.ArdkTelemetryReflection.Descriptor.MessageTypes[2]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ARSessionEvent() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ARSessionEvent(ARSessionEvent other) : this() { + sessionState_ = other.sessionState_; + sessionId_ = other.sessionId_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ARSessionEvent Clone() { + return new ARSessionEvent(this); + } + + /// Field number for the "session_state" field. + public const int SessionStateFieldNumber = 1; + private global::Niantic.ARDK.AR.Protobuf.ARSessionEvent.Types.State sessionState_ = global::Niantic.ARDK.AR.Protobuf.ARSessionEvent.Types.State.Unknown; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Niantic.ARDK.AR.Protobuf.ARSessionEvent.Types.State SessionState { + get { return sessionState_; } + set { + sessionState_ = value; + } + } + + /// Field number for the "session_id" field. + public const int SessionIdFieldNumber = 2; + private string sessionId_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string SessionId { + get { return sessionId_; } + set { + sessionId_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ARSessionEvent); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ARSessionEvent other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (SessionState != other.SessionState) return false; + if (SessionId != other.SessionId) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (SessionState != global::Niantic.ARDK.AR.Protobuf.ARSessionEvent.Types.State.Unknown) hash ^= SessionState.GetHashCode(); + if (SessionId.Length != 0) hash ^= SessionId.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (SessionState != global::Niantic.ARDK.AR.Protobuf.ARSessionEvent.Types.State.Unknown) { + output.WriteRawTag(8); + output.WriteEnum((int) SessionState); + } + if (SessionId.Length != 0) { + output.WriteRawTag(18); + output.WriteString(SessionId); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (SessionState != global::Niantic.ARDK.AR.Protobuf.ARSessionEvent.Types.State.Unknown) { + output.WriteRawTag(8); + output.WriteEnum((int) SessionState); + } + if (SessionId.Length != 0) { + output.WriteRawTag(18); + output.WriteString(SessionId); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (SessionState != global::Niantic.ARDK.AR.Protobuf.ARSessionEvent.Types.State.Unknown) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) SessionState); + } + if (SessionId.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(SessionId); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ARSessionEvent other) { + if (other == null) { + return; + } + if (other.SessionState != global::Niantic.ARDK.AR.Protobuf.ARSessionEvent.Types.State.Unknown) { + SessionState = other.SessionState; + } + if (other.SessionId.Length != 0) { + SessionId = other.SessionId; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + SessionState = (global::Niantic.ARDK.AR.Protobuf.ARSessionEvent.Types.State) input.ReadEnum(); + break; + } + case 18: { + SessionId = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + SessionState = (global::Niantic.ARDK.AR.Protobuf.ARSessionEvent.Types.State) input.ReadEnum(); + break; + } + case 18: { + SessionId = input.ReadString(); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the ARSessionEvent message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static partial class Types { + public enum State { + [pbr::OriginalName("UNKNOWN")] Unknown = 0, + [pbr::OriginalName("CREATED")] Created = 1, + [pbr::OriginalName("RUN")] Run = 2, + [pbr::OriginalName("PAUSE")] Pause = 3, + [pbr::OriginalName("DISPOSED")] Disposed = 4, + } + + } + #endregion + + } + + public sealed partial class LightshipServiceEvent : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new LightshipServiceEvent()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Niantic.ARDK.AR.Protobuf.ArdkTelemetryReflection.Descriptor.MessageTypes[3]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public LightshipServiceEvent() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public LightshipServiceEvent(LightshipServiceEvent other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public LightshipServiceEvent Clone() { + return new LightshipServiceEvent(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as LightshipServiceEvent); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(LightshipServiceEvent other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(LightshipServiceEvent other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + } + } + } + #endif + + } + + public sealed partial class MultiplayerConnectionEvent : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MultiplayerConnectionEvent()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Niantic.ARDK.AR.Protobuf.ArdkTelemetryReflection.Descriptor.MessageTypes[4]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public MultiplayerConnectionEvent() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public MultiplayerConnectionEvent(MultiplayerConnectionEvent other) : this() { + connection_ = other.connection_; + arbeSesssionInstanceId_ = other.arbeSesssionInstanceId_; + sessionId_ = other.sessionId_; + peerState_ = other.peerState_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public MultiplayerConnectionEvent Clone() { + return new MultiplayerConnectionEvent(this); + } + + /// Field number for the "connection" field. + public const int ConnectionFieldNumber = 1; + private global::Niantic.ARDK.AR.Protobuf.MultiplayerConnectionEvent.Types.ConnectState connection_ = global::Niantic.ARDK.AR.Protobuf.MultiplayerConnectionEvent.Types.ConnectState.Unknown; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Niantic.ARDK.AR.Protobuf.MultiplayerConnectionEvent.Types.ConnectState Connection { + get { return connection_; } + set { + connection_ = value; + } + } + + /// Field number for the "arbe_sesssion_instance_id" field. + public const int ArbeSesssionInstanceIdFieldNumber = 2; + private string arbeSesssionInstanceId_ = ""; + /// + /// server generated session ID + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string ArbeSesssionInstanceId { + get { return arbeSesssionInstanceId_; } + set { + arbeSesssionInstanceId_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "session_id" field. + public const int SessionIdFieldNumber = 3; + private string sessionId_ = ""; + /// + /// client generated session ID for ARDK 1.0 + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string SessionId { + get { return sessionId_; } + set { + sessionId_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "peer_state" field. + public const int PeerStateFieldNumber = 4; + private global::Niantic.ARDK.AR.Protobuf.MultiplayerConnectionEvent.Types.PeerState peerState_ = global::Niantic.ARDK.AR.Protobuf.MultiplayerConnectionEvent.Types.PeerState.StateUnknown; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Niantic.ARDK.AR.Protobuf.MultiplayerConnectionEvent.Types.PeerState PeerState { + get { return peerState_; } + set { + peerState_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as MultiplayerConnectionEvent); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(MultiplayerConnectionEvent other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Connection != other.Connection) return false; + if (ArbeSesssionInstanceId != other.ArbeSesssionInstanceId) return false; + if (SessionId != other.SessionId) return false; + if (PeerState != other.PeerState) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Connection != global::Niantic.ARDK.AR.Protobuf.MultiplayerConnectionEvent.Types.ConnectState.Unknown) hash ^= Connection.GetHashCode(); + if (ArbeSesssionInstanceId.Length != 0) hash ^= ArbeSesssionInstanceId.GetHashCode(); + if (SessionId.Length != 0) hash ^= SessionId.GetHashCode(); + if (PeerState != global::Niantic.ARDK.AR.Protobuf.MultiplayerConnectionEvent.Types.PeerState.StateUnknown) hash ^= PeerState.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Connection != global::Niantic.ARDK.AR.Protobuf.MultiplayerConnectionEvent.Types.ConnectState.Unknown) { + output.WriteRawTag(8); + output.WriteEnum((int) Connection); + } + if (ArbeSesssionInstanceId.Length != 0) { + output.WriteRawTag(18); + output.WriteString(ArbeSesssionInstanceId); + } + if (SessionId.Length != 0) { + output.WriteRawTag(26); + output.WriteString(SessionId); + } + if (PeerState != global::Niantic.ARDK.AR.Protobuf.MultiplayerConnectionEvent.Types.PeerState.StateUnknown) { + output.WriteRawTag(32); + output.WriteEnum((int) PeerState); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Connection != global::Niantic.ARDK.AR.Protobuf.MultiplayerConnectionEvent.Types.ConnectState.Unknown) { + output.WriteRawTag(8); + output.WriteEnum((int) Connection); + } + if (ArbeSesssionInstanceId.Length != 0) { + output.WriteRawTag(18); + output.WriteString(ArbeSesssionInstanceId); + } + if (SessionId.Length != 0) { + output.WriteRawTag(26); + output.WriteString(SessionId); + } + if (PeerState != global::Niantic.ARDK.AR.Protobuf.MultiplayerConnectionEvent.Types.PeerState.StateUnknown) { + output.WriteRawTag(32); + output.WriteEnum((int) PeerState); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Connection != global::Niantic.ARDK.AR.Protobuf.MultiplayerConnectionEvent.Types.ConnectState.Unknown) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Connection); + } + if (ArbeSesssionInstanceId.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(ArbeSesssionInstanceId); + } + if (SessionId.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(SessionId); + } + if (PeerState != global::Niantic.ARDK.AR.Protobuf.MultiplayerConnectionEvent.Types.PeerState.StateUnknown) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) PeerState); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(MultiplayerConnectionEvent other) { + if (other == null) { + return; + } + if (other.Connection != global::Niantic.ARDK.AR.Protobuf.MultiplayerConnectionEvent.Types.ConnectState.Unknown) { + Connection = other.Connection; + } + if (other.ArbeSesssionInstanceId.Length != 0) { + ArbeSesssionInstanceId = other.ArbeSesssionInstanceId; + } + if (other.SessionId.Length != 0) { + SessionId = other.SessionId; + } + if (other.PeerState != global::Niantic.ARDK.AR.Protobuf.MultiplayerConnectionEvent.Types.PeerState.StateUnknown) { + PeerState = other.PeerState; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + Connection = (global::Niantic.ARDK.AR.Protobuf.MultiplayerConnectionEvent.Types.ConnectState) input.ReadEnum(); + break; + } + case 18: { + ArbeSesssionInstanceId = input.ReadString(); + break; + } + case 26: { + SessionId = input.ReadString(); + break; + } + case 32: { + PeerState = (global::Niantic.ARDK.AR.Protobuf.MultiplayerConnectionEvent.Types.PeerState) input.ReadEnum(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + Connection = (global::Niantic.ARDK.AR.Protobuf.MultiplayerConnectionEvent.Types.ConnectState) input.ReadEnum(); + break; + } + case 18: { + ArbeSesssionInstanceId = input.ReadString(); + break; + } + case 26: { + SessionId = input.ReadString(); + break; + } + case 32: { + PeerState = (global::Niantic.ARDK.AR.Protobuf.MultiplayerConnectionEvent.Types.PeerState) input.ReadEnum(); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the MultiplayerConnectionEvent message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static partial class Types { + public enum ConnectState { + [pbr::OriginalName("UNKNOWN")] Unknown = 0, + [pbr::OriginalName("START")] Start = 1, + [pbr::OriginalName("JOIN")] Join = 2, + [pbr::OriginalName("CONNECTED")] Connected = 3, + [pbr::OriginalName("LEAVE")] Leave = 4, + [pbr::OriginalName("END")] End = 5, + } + + public enum PeerState { + [pbr::OriginalName("STATE_UNKNOWN")] StateUnknown = 0, + [pbr::OriginalName("INITIALIZING")] Initializing = 1, + [pbr::OriginalName("WAITING_FOR_LOCALIZATION_DATA")] WaitingForLocalizationData = 2, + [pbr::OriginalName("LOCALIZING")] Localizing = 3, + [pbr::OriginalName("STABILIZING")] Stabilizing = 4, + [pbr::OriginalName("STABLE")] Stable = 5, + [pbr::OriginalName("LIMITED")] Limited = 6, + [pbr::OriginalName("FAILED")] Failed = 7, + } + + } + #endregion + + } + + public sealed partial class EnabledContextualAwarenessEvent : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new EnabledContextualAwarenessEvent()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Niantic.ARDK.AR.Protobuf.ArdkTelemetryReflection.Descriptor.MessageTypes[5]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public EnabledContextualAwarenessEvent() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public EnabledContextualAwarenessEvent(EnabledContextualAwarenessEvent other) : this() { + meshing_ = other.meshing_; + fusion_ = other.fusion_; + depth_ = other.depth_; + semantics_ = other.semantics_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public EnabledContextualAwarenessEvent Clone() { + return new EnabledContextualAwarenessEvent(this); + } + + /// Field number for the "meshing" field. + public const int MeshingFieldNumber = 1; + private bool meshing_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Meshing { + get { return meshing_; } + set { + meshing_ = value; + } + } + + /// Field number for the "fusion" field. + public const int FusionFieldNumber = 2; + private bool fusion_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Fusion { + get { return fusion_; } + set { + fusion_ = value; + } + } + + /// Field number for the "depth" field. + public const int DepthFieldNumber = 3; + private bool depth_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Depth { + get { return depth_; } + set { + depth_ = value; + } + } + + /// Field number for the "semantics" field. + public const int SemanticsFieldNumber = 4; + private bool semantics_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Semantics { + get { return semantics_; } + set { + semantics_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as EnabledContextualAwarenessEvent); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(EnabledContextualAwarenessEvent other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Meshing != other.Meshing) return false; + if (Fusion != other.Fusion) return false; + if (Depth != other.Depth) return false; + if (Semantics != other.Semantics) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Meshing != false) hash ^= Meshing.GetHashCode(); + if (Fusion != false) hash ^= Fusion.GetHashCode(); + if (Depth != false) hash ^= Depth.GetHashCode(); + if (Semantics != false) hash ^= Semantics.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Meshing != false) { + output.WriteRawTag(8); + output.WriteBool(Meshing); + } + if (Fusion != false) { + output.WriteRawTag(16); + output.WriteBool(Fusion); + } + if (Depth != false) { + output.WriteRawTag(24); + output.WriteBool(Depth); + } + if (Semantics != false) { + output.WriteRawTag(32); + output.WriteBool(Semantics); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Meshing != false) { + output.WriteRawTag(8); + output.WriteBool(Meshing); + } + if (Fusion != false) { + output.WriteRawTag(16); + output.WriteBool(Fusion); + } + if (Depth != false) { + output.WriteRawTag(24); + output.WriteBool(Depth); + } + if (Semantics != false) { + output.WriteRawTag(32); + output.WriteBool(Semantics); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Meshing != false) { + size += 1 + 1; + } + if (Fusion != false) { + size += 1 + 1; + } + if (Depth != false) { + size += 1 + 1; + } + if (Semantics != false) { + size += 1 + 1; + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(EnabledContextualAwarenessEvent other) { + if (other == null) { + return; + } + if (other.Meshing != false) { + Meshing = other.Meshing; + } + if (other.Fusion != false) { + Fusion = other.Fusion; + } + if (other.Depth != false) { + Depth = other.Depth; + } + if (other.Semantics != false) { + Semantics = other.Semantics; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + Meshing = input.ReadBool(); + break; + } + case 16: { + Fusion = input.ReadBool(); + break; + } + case 24: { + Depth = input.ReadBool(); + break; + } + case 32: { + Semantics = input.ReadBool(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + Meshing = input.ReadBool(); + break; + } + case 16: { + Fusion = input.ReadBool(); + break; + } + case 24: { + Depth = input.ReadBool(); + break; + } + case 32: { + Semantics = input.ReadBool(); + break; + } + } + } + } + #endif + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/ArdkTelemetry.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/ArdkTelemetry.cs.meta new file mode 100644 index 0000000..cce821c --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/ArdkTelemetry.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 1a27aaa1f26d4e85c3d4e743295f0a19 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles.meta new file mode 100644 index 0000000..83d2296 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1e3caa3259a6841158318757227a878d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/CMakeDirectoryInformation.cmake b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/CMakeDirectoryInformation.cmake new file mode 100644 index 0000000..44e9897 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/CMakeDirectoryInformation.cmake @@ -0,0 +1,16 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.16 + +# Relative path conversion top directories. +set(CMAKE_RELATIVE_PATH_TOP_SOURCE "/private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar") +set(CMAKE_RELATIVE_PATH_TOP_BINARY "/private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/_cmake_build/macos-Release") + +# Force unix paths in dependencies. +set(CMAKE_FORCE_UNIX_PATHS 1) + + +# The C and CXX include file regular expressions for this directory. +set(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") +set(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") +set(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) +set(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/CMakeDirectoryInformation.cmake.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/CMakeDirectoryInformation.cmake.meta new file mode 100644 index 0000000..6f3b830 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/CMakeDirectoryInformation.cmake.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: ce9291a7b4ca0df7af6b0a3f6da469af diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir.meta new file mode 100644 index 0000000..a9ae58b --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5ab07ca55c9ce4fb0b87e5451a7d247b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/DependInfo.cmake b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/DependInfo.cmake new file mode 100644 index 0000000..19fab21 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/DependInfo.cmake @@ -0,0 +1,11 @@ +# The set of languages for which implicit dependencies are needed: +set(CMAKE_DEPENDS_LANGUAGES + ) +# The set of files for implicit dependencies of each language: + +# Targets to which this target links. +set(CMAKE_TARGET_LINKED_INFO_FILES + ) + +# Fortran module output directory. +set(CMAKE_Fortran_TARGET_MODULE_DIR "") diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/DependInfo.cmake.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/DependInfo.cmake.meta new file mode 100644 index 0000000..31a9b02 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/DependInfo.cmake.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: b607e1fb5c6261888000a6589b8510c0 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/build.make b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/build.make new file mode 100644 index 0000000..b7690b7 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/build.make @@ -0,0 +1,89 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.16 + +# Delete rule output on recipe failure. +.DELETE_ON_ERROR: + + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Remove some rules from gmake that .SUFFIXES does not remove. +SUFFIXES = + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Suppress display of executed commands. +$(VERBOSE).SILENT: + + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /Users/buildbot2/.gradle/niantic/cmake/macosx/3.16.3/files/cmake-3.16.3-Darwin-x86_64/CMake.app/Contents/bin/cmake + +# The command to remove a file. +RM = /Users/buildbot2/.gradle/niantic/cmake/macosx/3.16.3/files/cmake-3.16.3-Darwin-x86_64/CMake.app/Contents/bin/cmake -E remove -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/_cmake_build/macos-Release + +# Utility rule file for nar_csharp_proto_cs. + +# Include the progress variables for this target. +include nar-base/proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/progress.make + +nar-base/proto/csharp/CMakeFiles/nar_csharp_proto_cs: nar-base/proto/csharp/common/ar_common_metadata.cs +nar-base/proto/csharp/CMakeFiles/nar_csharp_proto_cs: nar-base/proto/csharp/common/telemetry/ardk_telemetry.cs + + +nar-base/proto/csharp/common/ar_common_metadata.cs: ../../nar-base/proto/common/ar_common_metadata.proto +nar-base/proto/csharp/common/ar_common_metadata.cs: protoc/v3.19.4/osx/bin/protoc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --blue --bold --progress-dir=/private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/_cmake_build/macos-Release/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Running protoc compiler on /private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/nar-base/proto/common/ar_common_metadata.proto to convert to C#" + cd /private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/_cmake_build/macos-Release/nar-base/proto/csharp && ../../../protoc/v3.19.4/osx/bin/protoc --csharp_out /private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/_cmake_build/macos-Release/nar-base/proto/csharp --csharp_opt=file_extension=.cs --proto_path=/private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/nar-base/proto/csharp --proto_path=/private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/nar-base/proto --proto_path=/private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/nar-base/proto/common /private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/nar-base/proto/common/ar_common_metadata.proto + +nar-base/proto/csharp/common/telemetry/ardk_telemetry.cs: ../../nar-base/proto/common/telemetry/ardk_telemetry.proto +nar-base/proto/csharp/common/telemetry/ardk_telemetry.cs: protoc/v3.19.4/osx/bin/protoc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --blue --bold --progress-dir=/private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/_cmake_build/macos-Release/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Running protoc compiler on /private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/nar-base/proto/common/telemetry/ardk_telemetry.proto to convert to C#" + cd /private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/_cmake_build/macos-Release/nar-base/proto/csharp && ../../../protoc/v3.19.4/osx/bin/protoc --csharp_out /private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/_cmake_build/macos-Release/nar-base/proto/csharp --csharp_opt=file_extension=.cs --proto_path=/private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/nar-base/proto/csharp --proto_path=/private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/nar-base/proto --proto_path=/private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/nar-base/proto/common /private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/nar-base/proto/common/telemetry/ardk_telemetry.proto + +nar_csharp_proto_cs: nar-base/proto/csharp/CMakeFiles/nar_csharp_proto_cs +nar_csharp_proto_cs: nar-base/proto/csharp/common/ar_common_metadata.cs +nar_csharp_proto_cs: nar-base/proto/csharp/common/telemetry/ardk_telemetry.cs +nar_csharp_proto_cs: nar-base/proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/build.make + +.PHONY : nar_csharp_proto_cs + +# Rule to build all files generated by this target. +nar-base/proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/build: nar_csharp_proto_cs + +.PHONY : nar-base/proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/build + +nar-base/proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/clean: + cd /private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/_cmake_build/macos-Release/nar-base/proto/csharp && $(CMAKE_COMMAND) -P CMakeFiles/nar_csharp_proto_cs.dir/cmake_clean.cmake +.PHONY : nar-base/proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/clean + +nar-base/proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/depend: + cd /private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/_cmake_build/macos-Release && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar /private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/nar-base/proto/csharp /private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/_cmake_build/macos-Release /private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/_cmake_build/macos-Release/nar-base/proto/csharp /private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/_cmake_build/macos-Release/nar-base/proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/DependInfo.cmake --color=$(COLOR) +.PHONY : nar-base/proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/depend + diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/build.make.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/build.make.meta new file mode 100644 index 0000000..ee95b32 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/build.make.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 47449df335fc0df11cf942ad10aecb63 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/cmake_clean.cmake b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/cmake_clean.cmake new file mode 100644 index 0000000..9597b08 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/cmake_clean.cmake @@ -0,0 +1,10 @@ +file(REMOVE_RECURSE + "CMakeFiles/nar_csharp_proto_cs" + "common/ar_common_metadata.cs" + "common/telemetry/ardk_telemetry.cs" +) + +# Per-language clean rules from dependency scanning. +foreach(lang ) + include(CMakeFiles/nar_csharp_proto_cs.dir/cmake_clean_${lang}.cmake OPTIONAL) +endforeach() diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/cmake_clean.cmake.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/cmake_clean.cmake.meta new file mode 100644 index 0000000..e460174 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/cmake_clean.cmake.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: a995967585542287c69e00c5adfdf152 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/depend.internal b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/depend.internal new file mode 100644 index 0000000..f647855 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/depend.internal @@ -0,0 +1,3 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.16 + diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/depend.internal.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/depend.internal.meta new file mode 100644 index 0000000..06fa18c --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/depend.internal.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: c5dfe098363f04b7071915e9f2070e3e diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/depend.make b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/depend.make new file mode 100644 index 0000000..f647855 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/depend.make @@ -0,0 +1,3 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.16 + diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/depend.make.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/depend.make.meta new file mode 100644 index 0000000..052af46 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/depend.make.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: c140a0e8a78c071adbd08c7339db0747 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/progress.make b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/progress.make new file mode 100644 index 0000000..6c287f1 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/progress.make @@ -0,0 +1,3 @@ +CMAKE_PROGRESS_1 = +CMAKE_PROGRESS_2 = + diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/progress.make.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/progress.make.meta new file mode 100644 index 0000000..a2afb51 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/progress.make.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: e956407d6afcfd81517906f62f9a0702 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/progress.marks b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/progress.marks new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/progress.marks @@ -0,0 +1 @@ +0 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/progress.marks.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/progress.marks.meta new file mode 100644 index 0000000..4086b37 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/CMakeFiles/progress.marks.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 2a71184e1a7135e01ca15cc77e96b8f4 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/Makefile b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/Makefile new file mode 100644 index 0000000..e806306 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/Makefile @@ -0,0 +1,200 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.16 + +# Default target executed when no arguments are given to make. +default_target: all + +.PHONY : default_target + +# Allow only one "make -f Makefile2" at a time, but pass parallelism. +.NOTPARALLEL: + + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Remove some rules from gmake that .SUFFIXES does not remove. +SUFFIXES = + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Suppress display of executed commands. +$(VERBOSE).SILENT: + + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /Users/buildbot2/.gradle/niantic/cmake/macosx/3.16.3/files/cmake-3.16.3-Darwin-x86_64/CMake.app/Contents/bin/cmake + +# The command to remove a file. +RM = /Users/buildbot2/.gradle/niantic/cmake/macosx/3.16.3/files/cmake-3.16.3-Darwin-x86_64/CMake.app/Contents/bin/cmake -E remove -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/_cmake_build/macos-Release + +#============================================================================= +# Targets provided globally by CMake. + +# Special rule for the target install/local +install/local: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..." + /Users/buildbot2/.gradle/niantic/cmake/macosx/3.16.3/files/cmake-3.16.3-Darwin-x86_64/CMake.app/Contents/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake +.PHONY : install/local + +# Special rule for the target install/local +install/local/fast: preinstall/fast + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..." + /Users/buildbot2/.gradle/niantic/cmake/macosx/3.16.3/files/cmake-3.16.3-Darwin-x86_64/CMake.app/Contents/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake +.PHONY : install/local/fast + +# Special rule for the target install/strip +install/strip: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..." + /Users/buildbot2/.gradle/niantic/cmake/macosx/3.16.3/files/cmake-3.16.3-Darwin-x86_64/CMake.app/Contents/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake +.PHONY : install/strip + +# Special rule for the target install/strip +install/strip/fast: preinstall/fast + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..." + /Users/buildbot2/.gradle/niantic/cmake/macosx/3.16.3/files/cmake-3.16.3-Darwin-x86_64/CMake.app/Contents/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake +.PHONY : install/strip/fast + +# Special rule for the target install +install: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." + /Users/buildbot2/.gradle/niantic/cmake/macosx/3.16.3/files/cmake-3.16.3-Darwin-x86_64/CMake.app/Contents/bin/cmake -P cmake_install.cmake +.PHONY : install + +# Special rule for the target install +install/fast: preinstall/fast + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." + /Users/buildbot2/.gradle/niantic/cmake/macosx/3.16.3/files/cmake-3.16.3-Darwin-x86_64/CMake.app/Contents/bin/cmake -P cmake_install.cmake +.PHONY : install/fast + +# Special rule for the target list_install_components +list_install_components: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Available install components are: \"Runtime\" \"Unspecified\" \"libprotobuf\" \"libprotobuf-lite\" \"libprotoc\" \"protobuf-export\" \"protobuf-headers\" \"protobuf-protos\" \"protoc\"" +.PHONY : list_install_components + +# Special rule for the target list_install_components +list_install_components/fast: list_install_components + +.PHONY : list_install_components/fast + +# Special rule for the target rebuild_cache +rebuild_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." + /Users/buildbot2/.gradle/niantic/cmake/macosx/3.16.3/files/cmake-3.16.3-Darwin-x86_64/CMake.app/Contents/bin/cmake -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : rebuild_cache + +# Special rule for the target rebuild_cache +rebuild_cache/fast: rebuild_cache + +.PHONY : rebuild_cache/fast + +# Special rule for the target edit_cache +edit_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..." + /Users/buildbot2/.gradle/niantic/cmake/macosx/3.16.3/files/cmake-3.16.3-Darwin-x86_64/CMake.app/Contents/bin/ccmake -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : edit_cache + +# Special rule for the target edit_cache +edit_cache/fast: edit_cache + +.PHONY : edit_cache/fast + +# The main all target +all: cmake_check_build_system + cd /private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/_cmake_build/macos-Release && $(CMAKE_COMMAND) -E cmake_progress_start /private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/_cmake_build/macos-Release/CMakeFiles /private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/_cmake_build/macos-Release/nar-base/proto/csharp/CMakeFiles/progress.marks + cd /private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/_cmake_build/macos-Release && $(MAKE) -f CMakeFiles/Makefile2 nar-base/proto/csharp/all + $(CMAKE_COMMAND) -E cmake_progress_start /private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/_cmake_build/macos-Release/CMakeFiles 0 +.PHONY : all + +# The main clean target +clean: + cd /private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/_cmake_build/macos-Release && $(MAKE) -f CMakeFiles/Makefile2 nar-base/proto/csharp/clean +.PHONY : clean + +# The main clean target +clean/fast: clean + +.PHONY : clean/fast + +# Prepare targets for installation. +preinstall: all + cd /private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/_cmake_build/macos-Release && $(MAKE) -f CMakeFiles/Makefile2 nar-base/proto/csharp/preinstall +.PHONY : preinstall + +# Prepare targets for installation. +preinstall/fast: + cd /private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/_cmake_build/macos-Release && $(MAKE) -f CMakeFiles/Makefile2 nar-base/proto/csharp/preinstall +.PHONY : preinstall/fast + +# clear depends +depend: + cd /private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/_cmake_build/macos-Release && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 +.PHONY : depend + +# Convenience name for target. +nar-base/proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/rule: + cd /private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/_cmake_build/macos-Release && $(MAKE) -f CMakeFiles/Makefile2 nar-base/proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/rule +.PHONY : nar-base/proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/rule + +# Convenience name for target. +nar_csharp_proto_cs: nar-base/proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/rule + +.PHONY : nar_csharp_proto_cs + +# fast build rule for target. +nar_csharp_proto_cs/fast: + cd /private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/_cmake_build/macos-Release && $(MAKE) -f nar-base/proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/build.make nar-base/proto/csharp/CMakeFiles/nar_csharp_proto_cs.dir/build +.PHONY : nar_csharp_proto_cs/fast + +# Help Target +help: + @echo "The following are some of the valid targets for this Makefile:" + @echo "... all (the default if no target is provided)" + @echo "... clean" + @echo "... depend" + @echo "... install/local" + @echo "... install/strip" + @echo "... install" + @echo "... list_install_components" + @echo "... rebuild_cache" + @echo "... edit_cache" + @echo "... nar_csharp_proto_cs" +.PHONY : help + + + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + cd /private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/_cmake_build/macos-Release && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/Makefile.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/Makefile.meta new file mode 100644 index 0000000..ae4cf99 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/Makefile.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 0cc9cda65c9c7df0cadb238e9e10f53d diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/cmake_install.cmake b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/cmake_install.cmake new file mode 100644 index 0000000..73f8dbe --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/cmake_install.cmake @@ -0,0 +1,34 @@ +# Install script for directory: /private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/nar-base/proto/csharp + +# Set the install prefix +if(NOT DEFINED CMAKE_INSTALL_PREFIX) + set(CMAKE_INSTALL_PREFIX "/private/var/gitlabrunner/buildbot2/workspace/builds/Rcta8Py6/0/niantic-ar/escher-reality/Narwhal/nar/../_build/nar/macos/Release") +endif() +string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + if(BUILD_TYPE) + string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + else() + set(CMAKE_INSTALL_CONFIG_NAME "Release") + endif() + message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +endif() + +# Set the component getting installed. +if(NOT CMAKE_INSTALL_COMPONENT) + if(COMPONENT) + message(STATUS "Install component: \"${COMPONENT}\"") + set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + else() + set(CMAKE_INSTALL_COMPONENT) + endif() +endif() + +# Is this installation the result of a crosscompile? +if(NOT DEFINED CMAKE_CROSSCOMPILING) + set(CMAKE_CROSSCOMPILING "FALSE") +endif() + diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/cmake_install.cmake.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/cmake_install.cmake.meta new file mode 100644 index 0000000..c61afde --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/nar_csharp_proto/csharp/cmake_install.cmake.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 40f4c82d68646a56cdd9ce3df444a676 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity.meta new file mode 100644 index 0000000..cec2191 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e67e24b7a0f544347aad0880df8f68fb +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity.meta new file mode 100644 index 0000000..6491869 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f076efd9c82be49629c50e606cfc6a72 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema.meta new file mode 100644 index 0000000..b311d83 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2d8c9a20e6d47407b88bd475c069e673 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/ror.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/ror.meta new file mode 100644 index 0000000..fa4805a --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/ror.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 58f078ed1331c4a10bbc59bd437d2938 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/ror/schema.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/ror/schema.meta new file mode 100644 index 0000000..8c923ba --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/ror/schema.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e33fa773b1839419ab9c5e82745c01f5 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/ror/schema/UUID.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/ror/schema/UUID.cs new file mode 100644 index 0000000..a6517bf --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/ror/schema/UUID.cs @@ -0,0 +1,60 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ror.schema +{ + +using global::System; +using global::System.Collections.Generic; +using global::FlatBuffers; + +public struct UUID : IFlatbufferObject +{ + private Struct __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteBuffer _bb) { __p = new Struct(_i, _bb); } + public UUID __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public ulong Upper { get { return __p.bb.GetUlong(__p.bb_pos + 0); } } + public void MutateUpper(ulong upper) { __p.bb.PutUlong(__p.bb_pos + 0, upper); } + public ulong Lower { get { return __p.bb.GetUlong(__p.bb_pos + 8); } } + public void MutateLower(ulong lower) { __p.bb.PutUlong(__p.bb_pos + 8, lower); } + + public static Offset CreateUUID(FlatBufferBuilder builder, ulong Upper, ulong Lower) { + builder.Prep(8, 16); + builder.PutUlong(Lower); + builder.PutUlong(Upper); + return new Offset(builder.Offset); + } + public UUIDT UnPack() { + var _o = new UUIDT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(UUIDT _o) { + _o.Upper = this.Upper; + _o.Lower = this.Lower; + } + public static Offset Pack(FlatBufferBuilder builder, UUIDT _o) { + if (_o == null) return default(Offset); + return CreateUUID( + builder, + _o.Upper, + _o.Lower); + } +}; + +public class UUIDT +{ + public ulong Upper { get; set; } + public ulong Lower { get; set; } + + public UUIDT() { + this.Upper = 0; + this.Lower = 0; + } +} + + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/ror/schema/UUID.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/ror/schema/UUID.cs.meta new file mode 100644 index 0000000..d9be919 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/ror/schema/UUID.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: edfe50f992b7c8f5eccc63d58488a26b diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload.meta new file mode 100644 index 0000000..3eb8faf --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7808aa33d02e244f09b4d752d3c05448 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror.meta new file mode 100644 index 0000000..fa2ca9d --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6ee190d61c4c34530b97e39725a86f86 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema.meta new file mode 100644 index 0000000..c328f94 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9aa59c40717a5465baecb3ae44928ef9 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload.meta new file mode 100644 index 0000000..f5ea40b --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3239fa658ed6f41a082180cfb41be174 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/Anonymous.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/Anonymous.cs new file mode 100644 index 0000000..471eac9 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/Anonymous.cs @@ -0,0 +1,50 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ror.schema.upload +{ + +using global::System; +using global::System.Collections.Generic; +using global::FlatBuffers; + +public struct Anonymous : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_1_12_0(); } + public static Anonymous GetRootAsAnonymous(ByteBuffer _bb) { return GetRootAsAnonymous(_bb, new Anonymous()); } + public static Anonymous GetRootAsAnonymous(ByteBuffer _bb, Anonymous obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public Anonymous __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + + public static void StartAnonymous(FlatBufferBuilder builder) { builder.StartTable(0); } + public static Offset EndAnonymous(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public AnonymousT UnPack() { + var _o = new AnonymousT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(AnonymousT _o) { + } + public static Offset Pack(FlatBufferBuilder builder, AnonymousT _o) { + if (_o == null) return default(Offset); + StartAnonymous(builder); + return EndAnonymous(builder); + } +}; + +public class AnonymousT +{ + + public AnonymousT() { + } +} + + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/Anonymous.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/Anonymous.cs.meta new file mode 100644 index 0000000..bb07f75 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/Anonymous.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: ac766e3fab84f1a0ebbfffcfdcb917ed diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/ChunkStatus.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/ChunkStatus.cs new file mode 100644 index 0000000..9056e19 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/ChunkStatus.cs @@ -0,0 +1,18 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ror.schema.upload +{ + +public enum ChunkStatus : sbyte +{ + none = 0, + received = 1, + stored = 2, + rejected = 3, + bad_state = 4, +}; + + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/ChunkStatus.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/ChunkStatus.cs.meta new file mode 100644 index 0000000..0ed196e --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/ChunkStatus.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 9be9f81b0ff29e4bb411e5bcf9f08618 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/GCSServiceAccount.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/GCSServiceAccount.cs new file mode 100644 index 0000000..66f46d1 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/GCSServiceAccount.cs @@ -0,0 +1,153 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ror.schema.upload +{ + +using global::System; +using global::System.Collections.Generic; +using global::FlatBuffers; + +public struct GCSServiceAccount : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_1_12_0(); } + public static GCSServiceAccount GetRootAsGCSServiceAccount(ByteBuffer _bb) { return GetRootAsGCSServiceAccount(_bb, new GCSServiceAccount()); } + public static GCSServiceAccount GetRootAsGCSServiceAccount(ByteBuffer _bb, GCSServiceAccount obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public GCSServiceAccount __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public string ClientEmail { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } +#if ENABLE_SPAN_T + public Span GetClientEmailBytes() { return __p.__vector_as_span(4, 1); } +#else + public ArraySegment? GetClientEmailBytes() { return __p.__vector_as_arraysegment(4); } +#endif + public byte[] GetClientEmailArray() { return __p.__vector_as_array(4); } + public string PrivateKeyID { get { int o = __p.__offset(6); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } +#if ENABLE_SPAN_T + public Span GetPrivateKeyIDBytes() { return __p.__vector_as_span(6, 1); } +#else + public ArraySegment? GetPrivateKeyIDBytes() { return __p.__vector_as_arraysegment(6); } +#endif + public byte[] GetPrivateKeyIDArray() { return __p.__vector_as_array(6); } + public string PrivateKey { get { int o = __p.__offset(8); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } +#if ENABLE_SPAN_T + public Span GetPrivateKeyBytes() { return __p.__vector_as_span(8, 1); } +#else + public ArraySegment? GetPrivateKeyBytes() { return __p.__vector_as_arraysegment(8); } +#endif + public byte[] GetPrivateKeyArray() { return __p.__vector_as_array(8); } + public string TokenURI { get { int o = __p.__offset(10); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } +#if ENABLE_SPAN_T + public Span GetTokenURIBytes() { return __p.__vector_as_span(10, 1); } +#else + public ArraySegment? GetTokenURIBytes() { return __p.__vector_as_arraysegment(10); } +#endif + public byte[] GetTokenURIArray() { return __p.__vector_as_array(10); } + public string Scopes(int j) { int o = __p.__offset(12); return o != 0 ? __p.__string(__p.__vector(o) + j * 4) : null; } + public int ScopesLength { get { int o = __p.__offset(12); return o != 0 ? __p.__vector_len(o) : 0; } } + public string Subject { get { int o = __p.__offset(14); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } +#if ENABLE_SPAN_T + public Span GetSubjectBytes() { return __p.__vector_as_span(14, 1); } +#else + public ArraySegment? GetSubjectBytes() { return __p.__vector_as_arraysegment(14); } +#endif + public byte[] GetSubjectArray() { return __p.__vector_as_array(14); } + + public static Offset CreateGCSServiceAccount(FlatBufferBuilder builder, + StringOffset clientEmailOffset = default(StringOffset), + StringOffset privateKeyIDOffset = default(StringOffset), + StringOffset privateKeyOffset = default(StringOffset), + StringOffset tokenURIOffset = default(StringOffset), + VectorOffset scopesOffset = default(VectorOffset), + StringOffset subjectOffset = default(StringOffset)) { + builder.StartTable(6); + GCSServiceAccount.AddSubject(builder, subjectOffset); + GCSServiceAccount.AddScopes(builder, scopesOffset); + GCSServiceAccount.AddTokenURI(builder, tokenURIOffset); + GCSServiceAccount.AddPrivateKey(builder, privateKeyOffset); + GCSServiceAccount.AddPrivateKeyID(builder, privateKeyIDOffset); + GCSServiceAccount.AddClientEmail(builder, clientEmailOffset); + return GCSServiceAccount.EndGCSServiceAccount(builder); + } + + public static void StartGCSServiceAccount(FlatBufferBuilder builder) { builder.StartTable(6); } + public static void AddClientEmail(FlatBufferBuilder builder, StringOffset clientEmailOffset) { builder.AddOffset(0, clientEmailOffset.Value, 0); } + public static void AddPrivateKeyID(FlatBufferBuilder builder, StringOffset privateKeyIDOffset) { builder.AddOffset(1, privateKeyIDOffset.Value, 0); } + public static void AddPrivateKey(FlatBufferBuilder builder, StringOffset privateKeyOffset) { builder.AddOffset(2, privateKeyOffset.Value, 0); } + public static void AddTokenURI(FlatBufferBuilder builder, StringOffset tokenURIOffset) { builder.AddOffset(3, tokenURIOffset.Value, 0); } + public static void AddScopes(FlatBufferBuilder builder, VectorOffset scopesOffset) { builder.AddOffset(4, scopesOffset.Value, 0); } + public static VectorOffset CreateScopesVector(FlatBufferBuilder builder, StringOffset[] data) { builder.StartVector(4, data.Length, 4); for (int i = data.Length - 1; i >= 0; i--) builder.AddOffset(data[i].Value); return builder.EndVector(); } + public static VectorOffset CreateScopesVectorBlock(FlatBufferBuilder builder, StringOffset[] data) { builder.StartVector(4, data.Length, 4); builder.Add(data); return builder.EndVector(); } + public static void StartScopesVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddSubject(FlatBufferBuilder builder, StringOffset subjectOffset) { builder.AddOffset(5, subjectOffset.Value, 0); } + public static Offset EndGCSServiceAccount(FlatBufferBuilder builder) { + int o = builder.EndTable(); + builder.Required(o, 4); // clientEmail + builder.Required(o, 6); // privateKeyID + builder.Required(o, 8); // privateKey + builder.Required(o, 10); // tokenURI + return new Offset(o); + } + public GCSServiceAccountT UnPack() { + var _o = new GCSServiceAccountT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(GCSServiceAccountT _o) { + _o.ClientEmail = this.ClientEmail; + _o.PrivateKeyID = this.PrivateKeyID; + _o.PrivateKey = this.PrivateKey; + _o.TokenURI = this.TokenURI; + _o.Scopes = new List(); + for (var _j = 0; _j < this.ScopesLength; ++_j) {_o.Scopes.Add(this.Scopes(_j));} + _o.Subject = this.Subject; + } + public static Offset Pack(FlatBufferBuilder builder, GCSServiceAccountT _o) { + if (_o == null) return default(Offset); + var _clientEmail = _o.ClientEmail == null ? default(StringOffset) : builder.CreateString(_o.ClientEmail); + var _privateKeyID = _o.PrivateKeyID == null ? default(StringOffset) : builder.CreateString(_o.PrivateKeyID); + var _privateKey = _o.PrivateKey == null ? default(StringOffset) : builder.CreateString(_o.PrivateKey); + var _tokenURI = _o.TokenURI == null ? default(StringOffset) : builder.CreateString(_o.TokenURI); + var _scopes = default(VectorOffset); + if (_o.Scopes != null) { + var __scopes = new StringOffset[_o.Scopes.Count]; + for (var _j = 0; _j < __scopes.Length; ++_j) { __scopes[_j] = builder.CreateString(_o.Scopes[_j]); } + _scopes = CreateScopesVector(builder, __scopes); + } + var _subject = _o.Subject == null ? default(StringOffset) : builder.CreateString(_o.Subject); + return CreateGCSServiceAccount( + builder, + _clientEmail, + _privateKeyID, + _privateKey, + _tokenURI, + _scopes, + _subject); + } +}; + +public class GCSServiceAccountT +{ + public string ClientEmail { get; set; } + public string PrivateKeyID { get; set; } + public string PrivateKey { get; set; } + public string TokenURI { get; set; } + public List Scopes { get; set; } + public string Subject { get; set; } + + public GCSServiceAccountT() { + this.ClientEmail = null; + this.PrivateKeyID = null; + this.PrivateKey = null; + this.TokenURI = null; + this.Scopes = null; + this.Subject = null; + } +} + + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/GCSServiceAccount.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/GCSServiceAccount.cs.meta new file mode 100644 index 0000000..8ea53a5 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/GCSServiceAccount.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 832cdde30ddc3188ae1d78339b9ec9cd diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/GCSServiceInfo.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/GCSServiceInfo.cs new file mode 100644 index 0000000..91bee14 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/GCSServiceInfo.cs @@ -0,0 +1,85 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ror.schema.upload +{ + +using global::System; +using global::System.Collections.Generic; +using global::FlatBuffers; + +public struct GCSServiceInfo : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_1_12_0(); } + public static GCSServiceInfo GetRootAsGCSServiceInfo(ByteBuffer _bb) { return GetRootAsGCSServiceInfo(_bb, new GCSServiceInfo()); } + public static GCSServiceInfo GetRootAsGCSServiceInfo(ByteBuffer _bb, GCSServiceInfo obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public GCSServiceInfo __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public string Object { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } +#if ENABLE_SPAN_T + public Span GetObjectBytes() { return __p.__vector_as_span(4, 1); } +#else + public ArraySegment? GetObjectBytes() { return __p.__vector_as_arraysegment(4); } +#endif + public byte[] GetObjectArray() { return __p.__vector_as_array(4); } + public string Bucket { get { int o = __p.__offset(6); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } +#if ENABLE_SPAN_T + public Span GetBucketBytes() { return __p.__vector_as_span(6, 1); } +#else + public ArraySegment? GetBucketBytes() { return __p.__vector_as_arraysegment(6); } +#endif + public byte[] GetBucketArray() { return __p.__vector_as_array(6); } + + public static Offset CreateGCSServiceInfo(FlatBufferBuilder builder, + StringOffset objectOffset = default(StringOffset), + StringOffset bucketOffset = default(StringOffset)) { + builder.StartTable(2); + GCSServiceInfo.AddBucket(builder, bucketOffset); + GCSServiceInfo.AddObject(builder, objectOffset); + return GCSServiceInfo.EndGCSServiceInfo(builder); + } + + public static void StartGCSServiceInfo(FlatBufferBuilder builder) { builder.StartTable(2); } + public static void AddObject(FlatBufferBuilder builder, StringOffset objectOffset) { builder.AddOffset(0, objectOffset.Value, 0); } + public static void AddBucket(FlatBufferBuilder builder, StringOffset bucketOffset) { builder.AddOffset(1, bucketOffset.Value, 0); } + public static Offset EndGCSServiceInfo(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public GCSServiceInfoT UnPack() { + var _o = new GCSServiceInfoT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(GCSServiceInfoT _o) { + _o.Object = this.Object; + _o.Bucket = this.Bucket; + } + public static Offset Pack(FlatBufferBuilder builder, GCSServiceInfoT _o) { + if (_o == null) return default(Offset); + var _object = _o.Object == null ? default(StringOffset) : builder.CreateString(_o.Object); + var _bucket = _o.Bucket == null ? default(StringOffset) : builder.CreateString(_o.Bucket); + return CreateGCSServiceInfo( + builder, + _object, + _bucket); + } +}; + +public class GCSServiceInfoT +{ + public string Object { get; set; } + public string Bucket { get; set; } + + public GCSServiceInfoT() { + this.Object = null; + this.Bucket = null; + } +} + + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/GCSServiceInfo.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/GCSServiceInfo.cs.meta new file mode 100644 index 0000000..8fce713 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/GCSServiceInfo.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 0a32114f10ec076e043f654c13e07e03 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/GCSSignedAuth.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/GCSSignedAuth.cs new file mode 100644 index 0000000..6bb4ce5 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/GCSSignedAuth.cs @@ -0,0 +1,100 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ror.schema.upload +{ + +using global::System; +using global::System.Collections.Generic; +using global::FlatBuffers; + +public struct GCSSignedAuth : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_1_12_0(); } + public static GCSSignedAuth GetRootAsGCSSignedAuth(ByteBuffer _bb) { return GetRootAsGCSSignedAuth(_bb, new GCSSignedAuth()); } + public static GCSSignedAuth GetRootAsGCSSignedAuth(ByteBuffer _bb, GCSSignedAuth obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public GCSSignedAuth __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public string Authorization { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } +#if ENABLE_SPAN_T + public Span GetAuthorizationBytes() { return __p.__vector_as_span(4, 1); } +#else + public ArraySegment? GetAuthorizationBytes() { return __p.__vector_as_arraysegment(4); } +#endif + public byte[] GetAuthorizationArray() { return __p.__vector_as_array(4); } + public string Date { get { int o = __p.__offset(6); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } +#if ENABLE_SPAN_T + public Span GetDateBytes() { return __p.__vector_as_span(6, 1); } +#else + public ArraySegment? GetDateBytes() { return __p.__vector_as_arraysegment(6); } +#endif + public byte[] GetDateArray() { return __p.__vector_as_array(6); } + public string SignedPayload { get { int o = __p.__offset(8); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } +#if ENABLE_SPAN_T + public Span GetSignedPayloadBytes() { return __p.__vector_as_span(8, 1); } +#else + public ArraySegment? GetSignedPayloadBytes() { return __p.__vector_as_arraysegment(8); } +#endif + public byte[] GetSignedPayloadArray() { return __p.__vector_as_array(8); } + + public static Offset CreateGCSSignedAuth(FlatBufferBuilder builder, + StringOffset authorizationOffset = default(StringOffset), + StringOffset dateOffset = default(StringOffset), + StringOffset signed_payloadOffset = default(StringOffset)) { + builder.StartTable(3); + GCSSignedAuth.AddSignedPayload(builder, signed_payloadOffset); + GCSSignedAuth.AddDate(builder, dateOffset); + GCSSignedAuth.AddAuthorization(builder, authorizationOffset); + return GCSSignedAuth.EndGCSSignedAuth(builder); + } + + public static void StartGCSSignedAuth(FlatBufferBuilder builder) { builder.StartTable(3); } + public static void AddAuthorization(FlatBufferBuilder builder, StringOffset authorizationOffset) { builder.AddOffset(0, authorizationOffset.Value, 0); } + public static void AddDate(FlatBufferBuilder builder, StringOffset dateOffset) { builder.AddOffset(1, dateOffset.Value, 0); } + public static void AddSignedPayload(FlatBufferBuilder builder, StringOffset signedPayloadOffset) { builder.AddOffset(2, signedPayloadOffset.Value, 0); } + public static Offset EndGCSSignedAuth(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public GCSSignedAuthT UnPack() { + var _o = new GCSSignedAuthT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(GCSSignedAuthT _o) { + _o.Authorization = this.Authorization; + _o.Date = this.Date; + _o.SignedPayload = this.SignedPayload; + } + public static Offset Pack(FlatBufferBuilder builder, GCSSignedAuthT _o) { + if (_o == null) return default(Offset); + var _authorization = _o.Authorization == null ? default(StringOffset) : builder.CreateString(_o.Authorization); + var _date = _o.Date == null ? default(StringOffset) : builder.CreateString(_o.Date); + var _signed_payload = _o.SignedPayload == null ? default(StringOffset) : builder.CreateString(_o.SignedPayload); + return CreateGCSSignedAuth( + builder, + _authorization, + _date, + _signed_payload); + } +}; + +public class GCSSignedAuthT +{ + public string Authorization { get; set; } + public string Date { get; set; } + public string SignedPayload { get; set; } + + public GCSSignedAuthT() { + this.Authorization = null; + this.Date = null; + this.SignedPayload = null; + } +} + + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/GCSSignedAuth.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/GCSSignedAuth.cs.meta new file mode 100644 index 0000000..fff2b09 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/GCSSignedAuth.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 835b5863e46af1e42c67edf1acad8792 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/GCSSignedComposeURL.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/GCSSignedComposeURL.cs new file mode 100644 index 0000000..55dc932 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/GCSSignedComposeURL.cs @@ -0,0 +1,64 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ror.schema.upload +{ + +using global::System; +using global::System.Collections.Generic; +using global::FlatBuffers; + +public struct GCSSignedComposeURL : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_1_12_0(); } + public static GCSSignedComposeURL GetRootAsGCSSignedComposeURL(ByteBuffer _bb) { return GetRootAsGCSSignedComposeURL(_bb, new GCSSignedComposeURL()); } + public static GCSSignedComposeURL GetRootAsGCSSignedComposeURL(ByteBuffer _bb, GCSSignedComposeURL obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public GCSSignedComposeURL __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public ror.schema.upload.GCSSignedAuth? ComposeAuth { get { int o = __p.__offset(4); return o != 0 ? (ror.schema.upload.GCSSignedAuth?)(new ror.schema.upload.GCSSignedAuth()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } } + + public static Offset CreateGCSSignedComposeURL(FlatBufferBuilder builder, + Offset composeAuthOffset = default(Offset)) { + builder.StartTable(1); + GCSSignedComposeURL.AddComposeAuth(builder, composeAuthOffset); + return GCSSignedComposeURL.EndGCSSignedComposeURL(builder); + } + + public static void StartGCSSignedComposeURL(FlatBufferBuilder builder) { builder.StartTable(1); } + public static void AddComposeAuth(FlatBufferBuilder builder, Offset composeAuthOffset) { builder.AddOffset(0, composeAuthOffset.Value, 0); } + public static Offset EndGCSSignedComposeURL(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public GCSSignedComposeURLT UnPack() { + var _o = new GCSSignedComposeURLT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(GCSSignedComposeURLT _o) { + _o.ComposeAuth = this.ComposeAuth.HasValue ? this.ComposeAuth.Value.UnPack() : null; + } + public static Offset Pack(FlatBufferBuilder builder, GCSSignedComposeURLT _o) { + if (_o == null) return default(Offset); + var _composeAuth = _o.ComposeAuth == null ? default(Offset) : ror.schema.upload.GCSSignedAuth.Pack(builder, _o.ComposeAuth); + return CreateGCSSignedComposeURL( + builder, + _composeAuth); + } +}; + +public class GCSSignedComposeURLT +{ + public ror.schema.upload.GCSSignedAuthT ComposeAuth { get; set; } + + public GCSSignedComposeURLT() { + this.ComposeAuth = null; + } +} + + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/GCSSignedComposeURL.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/GCSSignedComposeURL.cs.meta new file mode 100644 index 0000000..24639cf --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/GCSSignedComposeURL.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 868c7c5ec42fd4d234afc344abdc9842 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/GCSSignedWriteURL.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/GCSSignedWriteURL.cs new file mode 100644 index 0000000..0520bd6 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/GCSSignedWriteURL.cs @@ -0,0 +1,73 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ror.schema.upload +{ + +using global::System; +using global::System.Collections.Generic; +using global::FlatBuffers; + +public struct GCSSignedWriteURL : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_1_12_0(); } + public static GCSSignedWriteURL GetRootAsGCSSignedWriteURL(ByteBuffer _bb) { return GetRootAsGCSSignedWriteURL(_bb, new GCSSignedWriteURL()); } + public static GCSSignedWriteURL GetRootAsGCSSignedWriteURL(ByteBuffer _bb, GCSSignedWriteURL obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public GCSSignedWriteURL __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public ror.schema.upload.GCSSignedAuth? WriteAuth { get { int o = __p.__offset(4); return o != 0 ? (ror.schema.upload.GCSSignedAuth?)(new ror.schema.upload.GCSSignedAuth()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } } + public ror.schema.upload.GCSSignedAuth? DeleteAuth { get { int o = __p.__offset(6); return o != 0 ? (ror.schema.upload.GCSSignedAuth?)(new ror.schema.upload.GCSSignedAuth()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } } + + public static Offset CreateGCSSignedWriteURL(FlatBufferBuilder builder, + Offset writeAuthOffset = default(Offset), + Offset deleteAuthOffset = default(Offset)) { + builder.StartTable(2); + GCSSignedWriteURL.AddDeleteAuth(builder, deleteAuthOffset); + GCSSignedWriteURL.AddWriteAuth(builder, writeAuthOffset); + return GCSSignedWriteURL.EndGCSSignedWriteURL(builder); + } + + public static void StartGCSSignedWriteURL(FlatBufferBuilder builder) { builder.StartTable(2); } + public static void AddWriteAuth(FlatBufferBuilder builder, Offset writeAuthOffset) { builder.AddOffset(0, writeAuthOffset.Value, 0); } + public static void AddDeleteAuth(FlatBufferBuilder builder, Offset deleteAuthOffset) { builder.AddOffset(1, deleteAuthOffset.Value, 0); } + public static Offset EndGCSSignedWriteURL(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public GCSSignedWriteURLT UnPack() { + var _o = new GCSSignedWriteURLT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(GCSSignedWriteURLT _o) { + _o.WriteAuth = this.WriteAuth.HasValue ? this.WriteAuth.Value.UnPack() : null; + _o.DeleteAuth = this.DeleteAuth.HasValue ? this.DeleteAuth.Value.UnPack() : null; + } + public static Offset Pack(FlatBufferBuilder builder, GCSSignedWriteURLT _o) { + if (_o == null) return default(Offset); + var _writeAuth = _o.WriteAuth == null ? default(Offset) : ror.schema.upload.GCSSignedAuth.Pack(builder, _o.WriteAuth); + var _deleteAuth = _o.DeleteAuth == null ? default(Offset) : ror.schema.upload.GCSSignedAuth.Pack(builder, _o.DeleteAuth); + return CreateGCSSignedWriteURL( + builder, + _writeAuth, + _deleteAuth); + } +}; + +public class GCSSignedWriteURLT +{ + public ror.schema.upload.GCSSignedAuthT WriteAuth { get; set; } + public ror.schema.upload.GCSSignedAuthT DeleteAuth { get; set; } + + public GCSSignedWriteURLT() { + this.WriteAuth = null; + this.DeleteAuth = null; + } +} + + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/GCSSignedWriteURL.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/GCSSignedWriteURL.cs.meta new file mode 100644 index 0000000..8027e6f --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/GCSSignedWriteURL.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: cdca49f16f93aa1d713b67e23b88865f diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/ServiceAuths.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/ServiceAuths.cs new file mode 100644 index 0000000..b25eefa --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/ServiceAuths.cs @@ -0,0 +1,44 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ror.schema.upload +{ + +public enum ServiceAuths : byte +{ + NONE = 0, + Anonymous = 1, + GCSServiceAccount = 2, + GCSSignedWriteURL = 3, + GCSSignedComposeURL = 4, +}; + +public class ServiceAuthsUnion { + public ServiceAuths Type { get; set; } + public object Value { get; set; } + + public ServiceAuthsUnion() { + this.Type = ServiceAuths.NONE; + this.Value = null; + } + + public T As() where T : class { return this.Value as T; } + public ror.schema.upload.AnonymousT AsAnonymous() { return this.As(); } + public ror.schema.upload.GCSServiceAccountT AsGCSServiceAccount() { return this.As(); } + public ror.schema.upload.GCSSignedWriteURLT AsGCSSignedWriteURL() { return this.As(); } + public ror.schema.upload.GCSSignedComposeURLT AsGCSSignedComposeURL() { return this.As(); } + + public static int Pack(FlatBuffers.FlatBufferBuilder builder, ServiceAuthsUnion _o) { + switch (_o.Type) { + default: return 0; + case ServiceAuths.Anonymous: return ror.schema.upload.Anonymous.Pack(builder, _o.AsAnonymous()).Value; + case ServiceAuths.GCSServiceAccount: return ror.schema.upload.GCSServiceAccount.Pack(builder, _o.AsGCSServiceAccount()).Value; + case ServiceAuths.GCSSignedWriteURL: return ror.schema.upload.GCSSignedWriteURL.Pack(builder, _o.AsGCSSignedWriteURL()).Value; + case ServiceAuths.GCSSignedComposeURL: return ror.schema.upload.GCSSignedComposeURL.Pack(builder, _o.AsGCSSignedComposeURL()).Value; + } + } +} + + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/ServiceAuths.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/ServiceAuths.cs.meta new file mode 100644 index 0000000..ca217e1 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/ServiceAuths.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 6d50b5433a1be9d8d07b2c7a8b7d3789 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/ServiceInfos.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/ServiceInfos.cs new file mode 100644 index 0000000..c6fee36 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/ServiceInfos.cs @@ -0,0 +1,35 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ror.schema.upload +{ + +public enum ServiceInfos : byte +{ + NONE = 0, + GCSServiceInfo = 1, +}; + +public class ServiceInfosUnion { + public ServiceInfos Type { get; set; } + public object Value { get; set; } + + public ServiceInfosUnion() { + this.Type = ServiceInfos.NONE; + this.Value = null; + } + + public T As() where T : class { return this.Value as T; } + public ror.schema.upload.GCSServiceInfoT AsGCSServiceInfo() { return this.As(); } + + public static int Pack(FlatBuffers.FlatBufferBuilder builder, ServiceInfosUnion _o) { + switch (_o.Type) { + default: return 0; + case ServiceInfos.GCSServiceInfo: return ror.schema.upload.GCSServiceInfo.Pack(builder, _o.AsGCSServiceInfo()).Value; + } + } +} + + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/ServiceInfos.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/ServiceInfos.cs.meta new file mode 100644 index 0000000..ecff491 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/ServiceInfos.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: ffc7cd108010b978c075dba70e269e5c diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/SessionStatus.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/SessionStatus.cs new file mode 100644 index 0000000..9a428de --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/SessionStatus.cs @@ -0,0 +1,16 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ror.schema.upload +{ + +public enum SessionStatus : sbyte +{ + uploading = 0, + shutting_down = 1, + shutdown = 2, +}; + + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/SessionStatus.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/SessionStatus.cs.meta new file mode 100644 index 0000000..26e3ada --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/SessionStatus.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 7792c463d551ff0e1d08e8e9aa2150d4 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadAuth.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadAuth.cs new file mode 100644 index 0000000..ffe262f --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadAuth.cs @@ -0,0 +1,86 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ror.schema.upload +{ + +using global::System; +using global::System.Collections.Generic; +using global::FlatBuffers; + +public struct UploadAuth : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_1_12_0(); } + public static UploadAuth GetRootAsUploadAuth(ByteBuffer _bb) { return GetRootAsUploadAuth(_bb, new UploadAuth()); } + public static UploadAuth GetRootAsUploadAuth(ByteBuffer _bb, UploadAuth obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public UploadAuth __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public ror.schema.upload.ServiceAuths ServiceAuthType { get { int o = __p.__offset(4); return o != 0 ? (ror.schema.upload.ServiceAuths)__p.bb.Get(o + __p.bb_pos) : ror.schema.upload.ServiceAuths.NONE; } } + public TTable? ServiceAuth() where TTable : struct, IFlatbufferObject { int o = __p.__offset(6); return o != 0 ? (TTable?)__p.__union(o + __p.bb_pos) : null; } + + public static Offset CreateUploadAuth(FlatBufferBuilder builder, + ror.schema.upload.ServiceAuths serviceAuth_type = ror.schema.upload.ServiceAuths.NONE, + int serviceAuthOffset = 0) { + builder.StartTable(2); + UploadAuth.AddServiceAuth(builder, serviceAuthOffset); + UploadAuth.AddServiceAuthType(builder, serviceAuth_type); + return UploadAuth.EndUploadAuth(builder); + } + + public static void StartUploadAuth(FlatBufferBuilder builder) { builder.StartTable(2); } + public static void AddServiceAuthType(FlatBufferBuilder builder, ror.schema.upload.ServiceAuths serviceAuthType) { builder.AddByte(0, (byte)serviceAuthType, 0); } + public static void AddServiceAuth(FlatBufferBuilder builder, int serviceAuthOffset) { builder.AddOffset(1, serviceAuthOffset, 0); } + public static Offset EndUploadAuth(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public UploadAuthT UnPack() { + var _o = new UploadAuthT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(UploadAuthT _o) { + _o.ServiceAuth = new ror.schema.upload.ServiceAuthsUnion(); + _o.ServiceAuth.Type = this.ServiceAuthType; + switch (this.ServiceAuthType) { + default: break; + case ror.schema.upload.ServiceAuths.Anonymous: + _o.ServiceAuth.Value = this.ServiceAuth().HasValue ? this.ServiceAuth().Value.UnPack() : null; + break; + case ror.schema.upload.ServiceAuths.GCSServiceAccount: + _o.ServiceAuth.Value = this.ServiceAuth().HasValue ? this.ServiceAuth().Value.UnPack() : null; + break; + case ror.schema.upload.ServiceAuths.GCSSignedWriteURL: + _o.ServiceAuth.Value = this.ServiceAuth().HasValue ? this.ServiceAuth().Value.UnPack() : null; + break; + case ror.schema.upload.ServiceAuths.GCSSignedComposeURL: + _o.ServiceAuth.Value = this.ServiceAuth().HasValue ? this.ServiceAuth().Value.UnPack() : null; + break; + } + } + public static Offset Pack(FlatBufferBuilder builder, UploadAuthT _o) { + if (_o == null) return default(Offset); + var _serviceAuth_type = _o.ServiceAuth == null ? ror.schema.upload.ServiceAuths.NONE : _o.ServiceAuth.Type; + var _serviceAuth = _o.ServiceAuth == null ? 0 : ror.schema.upload.ServiceAuthsUnion.Pack(builder, _o.ServiceAuth); + return CreateUploadAuth( + builder, + _serviceAuth_type, + _serviceAuth); + } +}; + +public class UploadAuthT +{ + public ror.schema.upload.ServiceAuthsUnion ServiceAuth { get; set; } + + public UploadAuthT() { + this.ServiceAuth = null; + } +} + + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadAuth.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadAuth.cs.meta new file mode 100644 index 0000000..1982d23 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadAuth.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: f61b558a0bbcb99e032d6d7eb028f557 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadChunkBody.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadChunkBody.cs new file mode 100644 index 0000000..6ea29fc --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadChunkBody.cs @@ -0,0 +1,80 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ror.schema.upload +{ + +using global::System; +using global::System.Collections.Generic; +using global::FlatBuffers; + +public struct UploadChunkBody : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_1_12_0(); } + public static UploadChunkBody GetRootAsUploadChunkBody(ByteBuffer _bb) { return GetRootAsUploadChunkBody(_bb, new UploadChunkBody()); } + public static UploadChunkBody GetRootAsUploadChunkBody(ByteBuffer _bb, UploadChunkBody obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public UploadChunkBody __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public byte Data(int j) { int o = __p.__offset(4); return o != 0 ? __p.bb.Get(__p.__vector(o) + j * 1) : (byte)0; } + public int DataLength { get { int o = __p.__offset(4); return o != 0 ? __p.__vector_len(o) : 0; } } +#if ENABLE_SPAN_T + public Span GetDataBytes() { return __p.__vector_as_span(4, 1); } +#else + public ArraySegment? GetDataBytes() { return __p.__vector_as_arraysegment(4); } +#endif + public byte[] GetDataArray() { return __p.__vector_as_array(4); } + public bool MutateData(int j, byte data) { int o = __p.__offset(4); if (o != 0) { __p.bb.Put(__p.__vector(o) + j * 1, data); return true; } else { return false; } } + + public static Offset CreateUploadChunkBody(FlatBufferBuilder builder, + VectorOffset dataOffset = default(VectorOffset)) { + builder.StartTable(1); + UploadChunkBody.AddData(builder, dataOffset); + return UploadChunkBody.EndUploadChunkBody(builder); + } + + public static void StartUploadChunkBody(FlatBufferBuilder builder) { builder.StartTable(1); } + public static void AddData(FlatBufferBuilder builder, VectorOffset dataOffset) { builder.AddOffset(0, dataOffset.Value, 0); } + public static VectorOffset CreateDataVector(FlatBufferBuilder builder, byte[] data) { builder.StartVector(1, data.Length, 1); for (int i = data.Length - 1; i >= 0; i--) builder.AddByte(data[i]); return builder.EndVector(); } + public static VectorOffset CreateDataVectorBlock(FlatBufferBuilder builder, byte[] data) { builder.StartVector(1, data.Length, 1); builder.Add(data); return builder.EndVector(); } + public static void StartDataVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } + public static Offset EndUploadChunkBody(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public UploadChunkBodyT UnPack() { + var _o = new UploadChunkBodyT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(UploadChunkBodyT _o) { + _o.Data = new List(); + for (var _j = 0; _j < this.DataLength; ++_j) {_o.Data.Add(this.Data(_j));} + } + public static Offset Pack(FlatBufferBuilder builder, UploadChunkBodyT _o) { + if (_o == null) return default(Offset); + var _data = default(VectorOffset); + if (_o.Data != null) { + var __data = _o.Data.ToArray(); + _data = CreateDataVector(builder, __data); + } + return CreateUploadChunkBody( + builder, + _data); + } +}; + +public class UploadChunkBodyT +{ + public List Data { get; set; } + + public UploadChunkBodyT() { + this.Data = null; + } +} + + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadChunkBody.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadChunkBody.cs.meta new file mode 100644 index 0000000..a22235e --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadChunkBody.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 0399260dce52e6373257102ec5b935c0 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadChunkInfo.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadChunkInfo.cs new file mode 100644 index 0000000..2dda6ef --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadChunkInfo.cs @@ -0,0 +1,82 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ror.schema.upload +{ + +using global::System; +using global::System.Collections.Generic; +using global::FlatBuffers; + +public struct UploadChunkInfo : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_1_12_0(); } + public static UploadChunkInfo GetRootAsUploadChunkInfo(ByteBuffer _bb) { return GetRootAsUploadChunkInfo(_bb, new UploadChunkInfo()); } + public static UploadChunkInfo GetRootAsUploadChunkInfo(ByteBuffer _bb, UploadChunkInfo obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public UploadChunkInfo __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public ulong ChunkIndex { get { int o = __p.__offset(4); return o != 0 ? __p.bb.GetUlong(o + __p.bb_pos) : (ulong)0; } } + public bool MutateChunkIndex(ulong chunkIndex) { int o = __p.__offset(4); if (o != 0) { __p.bb.PutUlong(o + __p.bb_pos, chunkIndex); return true; } else { return false; } } + public ror.schema.upload.UploadServiceInfo? ServiceInfo { get { int o = __p.__offset(6); return o != 0 ? (ror.schema.upload.UploadServiceInfo?)(new ror.schema.upload.UploadServiceInfo()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } } + public ror.schema.upload.UploadAuth? Auth { get { int o = __p.__offset(8); return o != 0 ? (ror.schema.upload.UploadAuth?)(new ror.schema.upload.UploadAuth()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } } + + public static Offset CreateUploadChunkInfo(FlatBufferBuilder builder, + ulong chunkIndex = 0, + Offset serviceInfoOffset = default(Offset), + Offset authOffset = default(Offset)) { + builder.StartTable(3); + UploadChunkInfo.AddChunkIndex(builder, chunkIndex); + UploadChunkInfo.AddAuth(builder, authOffset); + UploadChunkInfo.AddServiceInfo(builder, serviceInfoOffset); + return UploadChunkInfo.EndUploadChunkInfo(builder); + } + + public static void StartUploadChunkInfo(FlatBufferBuilder builder) { builder.StartTable(3); } + public static void AddChunkIndex(FlatBufferBuilder builder, ulong chunkIndex) { builder.AddUlong(0, chunkIndex, 0); } + public static void AddServiceInfo(FlatBufferBuilder builder, Offset serviceInfoOffset) { builder.AddOffset(1, serviceInfoOffset.Value, 0); } + public static void AddAuth(FlatBufferBuilder builder, Offset authOffset) { builder.AddOffset(2, authOffset.Value, 0); } + public static Offset EndUploadChunkInfo(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public UploadChunkInfoT UnPack() { + var _o = new UploadChunkInfoT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(UploadChunkInfoT _o) { + _o.ChunkIndex = this.ChunkIndex; + _o.ServiceInfo = this.ServiceInfo.HasValue ? this.ServiceInfo.Value.UnPack() : null; + _o.Auth = this.Auth.HasValue ? this.Auth.Value.UnPack() : null; + } + public static Offset Pack(FlatBufferBuilder builder, UploadChunkInfoT _o) { + if (_o == null) return default(Offset); + var _serviceInfo = _o.ServiceInfo == null ? default(Offset) : ror.schema.upload.UploadServiceInfo.Pack(builder, _o.ServiceInfo); + var _auth = _o.Auth == null ? default(Offset) : ror.schema.upload.UploadAuth.Pack(builder, _o.Auth); + return CreateUploadChunkInfo( + builder, + _o.ChunkIndex, + _serviceInfo, + _auth); + } +}; + +public class UploadChunkInfoT +{ + public ulong ChunkIndex { get; set; } + public ror.schema.upload.UploadServiceInfoT ServiceInfo { get; set; } + public ror.schema.upload.UploadAuthT Auth { get; set; } + + public UploadChunkInfoT() { + this.ChunkIndex = 0; + this.ServiceInfo = null; + this.Auth = null; + } +} + + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadChunkInfo.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadChunkInfo.cs.meta new file mode 100644 index 0000000..a27dbcb --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadChunkInfo.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 1a7bd29c8108403bc00126184e72411c diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadChunkRequest.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadChunkRequest.cs new file mode 100644 index 0000000..af62746 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadChunkRequest.cs @@ -0,0 +1,101 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ror.schema.upload +{ + +using global::System; +using global::System.Collections.Generic; +using global::FlatBuffers; + +public struct UploadChunkRequest : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_1_12_0(); } + public static UploadChunkRequest GetRootAsUploadChunkRequest(ByteBuffer _bb) { return GetRootAsUploadChunkRequest(_bb, new UploadChunkRequest()); } + public static UploadChunkRequest GetRootAsUploadChunkRequest(ByteBuffer _bb, UploadChunkRequest obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public UploadChunkRequest __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public ror.schema.upload.UploadSessionInfo? SessionInfo { get { int o = __p.__offset(4); return o != 0 ? (ror.schema.upload.UploadSessionInfo?)(new ror.schema.upload.UploadSessionInfo()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } } + public ror.schema.upload.UploadChunkInfo? ChunkInfo { get { int o = __p.__offset(6); return o != 0 ? (ror.schema.upload.UploadChunkInfo?)(new ror.schema.upload.UploadChunkInfo()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } } + public ror.schema.upload.UploadAuth? Auth { get { int o = __p.__offset(8); return o != 0 ? (ror.schema.upload.UploadAuth?)(new ror.schema.upload.UploadAuth()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } } + public ror.schema.upload.UploadChunkBody? Body { get { int o = __p.__offset(10); return o != 0 ? (ror.schema.upload.UploadChunkBody?)(new ror.schema.upload.UploadChunkBody()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } } + + public static Offset CreateUploadChunkRequest(FlatBufferBuilder builder, + Offset sessionInfoOffset = default(Offset), + Offset chunkInfoOffset = default(Offset), + Offset authOffset = default(Offset), + Offset bodyOffset = default(Offset)) { + builder.StartTable(4); + UploadChunkRequest.AddBody(builder, bodyOffset); + UploadChunkRequest.AddAuth(builder, authOffset); + UploadChunkRequest.AddChunkInfo(builder, chunkInfoOffset); + UploadChunkRequest.AddSessionInfo(builder, sessionInfoOffset); + return UploadChunkRequest.EndUploadChunkRequest(builder); + } + + public static void StartUploadChunkRequest(FlatBufferBuilder builder) { builder.StartTable(4); } + public static void AddSessionInfo(FlatBufferBuilder builder, Offset sessionInfoOffset) { builder.AddOffset(0, sessionInfoOffset.Value, 0); } + public static void AddChunkInfo(FlatBufferBuilder builder, Offset chunkInfoOffset) { builder.AddOffset(1, chunkInfoOffset.Value, 0); } + public static void AddAuth(FlatBufferBuilder builder, Offset authOffset) { builder.AddOffset(2, authOffset.Value, 0); } + public static void AddBody(FlatBufferBuilder builder, Offset bodyOffset) { builder.AddOffset(3, bodyOffset.Value, 0); } + public static Offset EndUploadChunkRequest(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public static void FinishUploadChunkRequestBuffer(FlatBufferBuilder builder, Offset offset) { builder.Finish(offset.Value); } + public static void FinishSizePrefixedUploadChunkRequestBuffer(FlatBufferBuilder builder, Offset offset) { builder.FinishSizePrefixed(offset.Value); } + public UploadChunkRequestT UnPack() { + var _o = new UploadChunkRequestT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(UploadChunkRequestT _o) { + _o.SessionInfo = this.SessionInfo.HasValue ? this.SessionInfo.Value.UnPack() : null; + _o.ChunkInfo = this.ChunkInfo.HasValue ? this.ChunkInfo.Value.UnPack() : null; + _o.Auth = this.Auth.HasValue ? this.Auth.Value.UnPack() : null; + _o.Body = this.Body.HasValue ? this.Body.Value.UnPack() : null; + } + public static Offset Pack(FlatBufferBuilder builder, UploadChunkRequestT _o) { + if (_o == null) return default(Offset); + var _sessionInfo = _o.SessionInfo == null ? default(Offset) : ror.schema.upload.UploadSessionInfo.Pack(builder, _o.SessionInfo); + var _chunkInfo = _o.ChunkInfo == null ? default(Offset) : ror.schema.upload.UploadChunkInfo.Pack(builder, _o.ChunkInfo); + var _auth = _o.Auth == null ? default(Offset) : ror.schema.upload.UploadAuth.Pack(builder, _o.Auth); + var _body = _o.Body == null ? default(Offset) : ror.schema.upload.UploadChunkBody.Pack(builder, _o.Body); + return CreateUploadChunkRequest( + builder, + _sessionInfo, + _chunkInfo, + _auth, + _body); + } +}; + +public class UploadChunkRequestT +{ + public ror.schema.upload.UploadSessionInfoT SessionInfo { get; set; } + public ror.schema.upload.UploadChunkInfoT ChunkInfo { get; set; } + public ror.schema.upload.UploadAuthT Auth { get; set; } + public ror.schema.upload.UploadChunkBodyT Body { get; set; } + + public UploadChunkRequestT() { + this.SessionInfo = null; + this.ChunkInfo = null; + this.Auth = null; + this.Body = null; + } + public static UploadChunkRequestT DeserializeFromBinary(byte[] fbBuffer) { + return UploadChunkRequest.GetRootAsUploadChunkRequest(new ByteBuffer(fbBuffer)).UnPack(); + } + public byte[] SerializeToBinary() { + var fbb = new FlatBufferBuilder(0x10000); + fbb.Finish(UploadChunkRequest.Pack(fbb, this).Value); + return fbb.DataBuffer.ToSizedArray(); + } +} + + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadChunkRequest.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadChunkRequest.cs.meta new file mode 100644 index 0000000..8ef62d6 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadChunkRequest.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 3cfbb7c5d5bccd461e3c4540cf21ad82 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadChunkResponse.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadChunkResponse.cs new file mode 100644 index 0000000..efb6d42 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadChunkResponse.cs @@ -0,0 +1,107 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ror.schema.upload +{ + +using global::System; +using global::System.Collections.Generic; +using global::FlatBuffers; + +public struct UploadChunkResponse : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_1_12_0(); } + public static UploadChunkResponse GetRootAsUploadChunkResponse(ByteBuffer _bb) { return GetRootAsUploadChunkResponse(_bb, new UploadChunkResponse()); } + public static UploadChunkResponse GetRootAsUploadChunkResponse(ByteBuffer _bb, UploadChunkResponse obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public UploadChunkResponse __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public ror.schema.upload.UploadSessionInfo? SessionInfo { get { int o = __p.__offset(4); return o != 0 ? (ror.schema.upload.UploadSessionInfo?)(new ror.schema.upload.UploadSessionInfo()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } } + public ror.schema.upload.UploadChunkInfo? ChunkInfo { get { int o = __p.__offset(6); return o != 0 ? (ror.schema.upload.UploadChunkInfo?)(new ror.schema.upload.UploadChunkInfo()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } } + public ror.schema.upload.ChunkStatus Status { get { int o = __p.__offset(8); return o != 0 ? (ror.schema.upload.ChunkStatus)__p.bb.GetSbyte(o + __p.bb_pos) : ror.schema.upload.ChunkStatus.none; } } + public bool MutateStatus(ror.schema.upload.ChunkStatus status) { int o = __p.__offset(8); if (o != 0) { __p.bb.PutSbyte(o + __p.bb_pos, (sbyte)status); return true; } else { return false; } } + public string StatusMessage { get { int o = __p.__offset(10); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } +#if ENABLE_SPAN_T + public Span GetStatusMessageBytes() { return __p.__vector_as_span(10, 1); } +#else + public ArraySegment? GetStatusMessageBytes() { return __p.__vector_as_arraysegment(10); } +#endif + public byte[] GetStatusMessageArray() { return __p.__vector_as_array(10); } + + public static Offset CreateUploadChunkResponse(FlatBufferBuilder builder, + Offset sessionInfoOffset = default(Offset), + Offset chunkInfoOffset = default(Offset), + ror.schema.upload.ChunkStatus status = ror.schema.upload.ChunkStatus.none, + StringOffset statusMessageOffset = default(StringOffset)) { + builder.StartTable(4); + UploadChunkResponse.AddStatusMessage(builder, statusMessageOffset); + UploadChunkResponse.AddChunkInfo(builder, chunkInfoOffset); + UploadChunkResponse.AddSessionInfo(builder, sessionInfoOffset); + UploadChunkResponse.AddStatus(builder, status); + return UploadChunkResponse.EndUploadChunkResponse(builder); + } + + public static void StartUploadChunkResponse(FlatBufferBuilder builder) { builder.StartTable(4); } + public static void AddSessionInfo(FlatBufferBuilder builder, Offset sessionInfoOffset) { builder.AddOffset(0, sessionInfoOffset.Value, 0); } + public static void AddChunkInfo(FlatBufferBuilder builder, Offset chunkInfoOffset) { builder.AddOffset(1, chunkInfoOffset.Value, 0); } + public static void AddStatus(FlatBufferBuilder builder, ror.schema.upload.ChunkStatus status) { builder.AddSbyte(2, (sbyte)status, 0); } + public static void AddStatusMessage(FlatBufferBuilder builder, StringOffset statusMessageOffset) { builder.AddOffset(3, statusMessageOffset.Value, 0); } + public static Offset EndUploadChunkResponse(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public static void FinishUploadChunkResponseBuffer(FlatBufferBuilder builder, Offset offset) { builder.Finish(offset.Value); } + public static void FinishSizePrefixedUploadChunkResponseBuffer(FlatBufferBuilder builder, Offset offset) { builder.FinishSizePrefixed(offset.Value); } + public UploadChunkResponseT UnPack() { + var _o = new UploadChunkResponseT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(UploadChunkResponseT _o) { + _o.SessionInfo = this.SessionInfo.HasValue ? this.SessionInfo.Value.UnPack() : null; + _o.ChunkInfo = this.ChunkInfo.HasValue ? this.ChunkInfo.Value.UnPack() : null; + _o.Status = this.Status; + _o.StatusMessage = this.StatusMessage; + } + public static Offset Pack(FlatBufferBuilder builder, UploadChunkResponseT _o) { + if (_o == null) return default(Offset); + var _sessionInfo = _o.SessionInfo == null ? default(Offset) : ror.schema.upload.UploadSessionInfo.Pack(builder, _o.SessionInfo); + var _chunkInfo = _o.ChunkInfo == null ? default(Offset) : ror.schema.upload.UploadChunkInfo.Pack(builder, _o.ChunkInfo); + var _statusMessage = _o.StatusMessage == null ? default(StringOffset) : builder.CreateString(_o.StatusMessage); + return CreateUploadChunkResponse( + builder, + _sessionInfo, + _chunkInfo, + _o.Status, + _statusMessage); + } +}; + +public class UploadChunkResponseT +{ + public ror.schema.upload.UploadSessionInfoT SessionInfo { get; set; } + public ror.schema.upload.UploadChunkInfoT ChunkInfo { get; set; } + public ror.schema.upload.ChunkStatus Status { get; set; } + public string StatusMessage { get; set; } + + public UploadChunkResponseT() { + this.SessionInfo = null; + this.ChunkInfo = null; + this.Status = ror.schema.upload.ChunkStatus.none; + this.StatusMessage = null; + } + public static UploadChunkResponseT DeserializeFromBinary(byte[] fbBuffer) { + return UploadChunkResponse.GetRootAsUploadChunkResponse(new ByteBuffer(fbBuffer)).UnPack(); + } + public byte[] SerializeToBinary() { + var fbb = new FlatBufferBuilder(0x10000); + fbb.Finish(UploadChunkResponse.Pack(fbb, this).Value); + return fbb.DataBuffer.ToSizedArray(); + } +} + + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadChunkResponse.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadChunkResponse.cs.meta new file mode 100644 index 0000000..1acfdf4 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadChunkResponse.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: eebe7055f384b74cfdcd9ea84ed6451f diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadServiceInfo.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadServiceInfo.cs new file mode 100644 index 0000000..7aed3d8 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadServiceInfo.cs @@ -0,0 +1,77 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ror.schema.upload +{ + +using global::System; +using global::System.Collections.Generic; +using global::FlatBuffers; + +public struct UploadServiceInfo : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_1_12_0(); } + public static UploadServiceInfo GetRootAsUploadServiceInfo(ByteBuffer _bb) { return GetRootAsUploadServiceInfo(_bb, new UploadServiceInfo()); } + public static UploadServiceInfo GetRootAsUploadServiceInfo(ByteBuffer _bb, UploadServiceInfo obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public UploadServiceInfo __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public ror.schema.upload.ServiceInfos ServiceInfoType { get { int o = __p.__offset(4); return o != 0 ? (ror.schema.upload.ServiceInfos)__p.bb.Get(o + __p.bb_pos) : ror.schema.upload.ServiceInfos.NONE; } } + public TTable? ServiceInfo() where TTable : struct, IFlatbufferObject { int o = __p.__offset(6); return o != 0 ? (TTable?)__p.__union(o + __p.bb_pos) : null; } + + public static Offset CreateUploadServiceInfo(FlatBufferBuilder builder, + ror.schema.upload.ServiceInfos serviceInfo_type = ror.schema.upload.ServiceInfos.NONE, + int serviceInfoOffset = 0) { + builder.StartTable(2); + UploadServiceInfo.AddServiceInfo(builder, serviceInfoOffset); + UploadServiceInfo.AddServiceInfoType(builder, serviceInfo_type); + return UploadServiceInfo.EndUploadServiceInfo(builder); + } + + public static void StartUploadServiceInfo(FlatBufferBuilder builder) { builder.StartTable(2); } + public static void AddServiceInfoType(FlatBufferBuilder builder, ror.schema.upload.ServiceInfos serviceInfoType) { builder.AddByte(0, (byte)serviceInfoType, 0); } + public static void AddServiceInfo(FlatBufferBuilder builder, int serviceInfoOffset) { builder.AddOffset(1, serviceInfoOffset, 0); } + public static Offset EndUploadServiceInfo(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public UploadServiceInfoT UnPack() { + var _o = new UploadServiceInfoT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(UploadServiceInfoT _o) { + _o.ServiceInfo = new ror.schema.upload.ServiceInfosUnion(); + _o.ServiceInfo.Type = this.ServiceInfoType; + switch (this.ServiceInfoType) { + default: break; + case ror.schema.upload.ServiceInfos.GCSServiceInfo: + _o.ServiceInfo.Value = this.ServiceInfo().HasValue ? this.ServiceInfo().Value.UnPack() : null; + break; + } + } + public static Offset Pack(FlatBufferBuilder builder, UploadServiceInfoT _o) { + if (_o == null) return default(Offset); + var _serviceInfo_type = _o.ServiceInfo == null ? ror.schema.upload.ServiceInfos.NONE : _o.ServiceInfo.Type; + var _serviceInfo = _o.ServiceInfo == null ? 0 : ror.schema.upload.ServiceInfosUnion.Pack(builder, _o.ServiceInfo); + return CreateUploadServiceInfo( + builder, + _serviceInfo_type, + _serviceInfo); + } +}; + +public class UploadServiceInfoT +{ + public ror.schema.upload.ServiceInfosUnion ServiceInfo { get; set; } + + public UploadServiceInfoT() { + this.ServiceInfo = null; + } +} + + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadServiceInfo.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadServiceInfo.cs.meta new file mode 100644 index 0000000..c671a27 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadServiceInfo.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: f4bb380a4cd9314df353501a82209755 diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadSessionInfo.cs b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadSessionInfo.cs new file mode 100644 index 0000000..5920cb2 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadSessionInfo.cs @@ -0,0 +1,88 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ror.schema.upload +{ + +using global::System; +using global::System.Collections.Generic; +using global::FlatBuffers; + +public struct UploadSessionInfo : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_1_12_0(); } + public static UploadSessionInfo GetRootAsUploadSessionInfo(ByteBuffer _bb) { return GetRootAsUploadSessionInfo(_bb, new UploadSessionInfo()); } + public static UploadSessionInfo GetRootAsUploadSessionInfo(ByteBuffer _bb, UploadSessionInfo obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public UploadSessionInfo __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public ror.schema.UUID? Session { get { int o = __p.__offset(4); return o != 0 ? (ror.schema.UUID?)(new ror.schema.UUID()).__assign(o + __p.bb_pos, __p.bb) : null; } } + public ulong OutOf { get { int o = __p.__offset(6); return o != 0 ? __p.bb.GetUlong(o + __p.bb_pos) : (ulong)0; } } + public bool MutateOutOf(ulong outOf) { int o = __p.__offset(6); if (o != 0) { __p.bb.PutUlong(o + __p.bb_pos, outOf); return true; } else { return false; } } + public ror.schema.upload.ServiceInfos ServiceInfoType { get { int o = __p.__offset(8); return o != 0 ? (ror.schema.upload.ServiceInfos)__p.bb.Get(o + __p.bb_pos) : ror.schema.upload.ServiceInfos.NONE; } } + public TTable? ServiceInfo() where TTable : struct, IFlatbufferObject { int o = __p.__offset(10); return o != 0 ? (TTable?)__p.__union(o + __p.bb_pos) : null; } + public ror.schema.upload.UploadAuth? SessionAuth { get { int o = __p.__offset(12); return o != 0 ? (ror.schema.upload.UploadAuth?)(new ror.schema.upload.UploadAuth()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } } + + public static void StartUploadSessionInfo(FlatBufferBuilder builder) { builder.StartTable(5); } + public static void AddSession(FlatBufferBuilder builder, Offset sessionOffset) { builder.AddStruct(0, sessionOffset.Value, 0); } + public static void AddOutOf(FlatBufferBuilder builder, ulong outOf) { builder.AddUlong(1, outOf, 0); } + public static void AddServiceInfoType(FlatBufferBuilder builder, ror.schema.upload.ServiceInfos serviceInfoType) { builder.AddByte(2, (byte)serviceInfoType, 0); } + public static void AddServiceInfo(FlatBufferBuilder builder, int serviceInfoOffset) { builder.AddOffset(3, serviceInfoOffset, 0); } + public static void AddSessionAuth(FlatBufferBuilder builder, Offset sessionAuthOffset) { builder.AddOffset(4, sessionAuthOffset.Value, 0); } + public static Offset EndUploadSessionInfo(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public UploadSessionInfoT UnPack() { + var _o = new UploadSessionInfoT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(UploadSessionInfoT _o) { + _o.Session = this.Session.HasValue ? this.Session.Value.UnPack() : null; + _o.OutOf = this.OutOf; + _o.ServiceInfo = new ror.schema.upload.ServiceInfosUnion(); + _o.ServiceInfo.Type = this.ServiceInfoType; + switch (this.ServiceInfoType) { + default: break; + case ror.schema.upload.ServiceInfos.GCSServiceInfo: + _o.ServiceInfo.Value = this.ServiceInfo().HasValue ? this.ServiceInfo().Value.UnPack() : null; + break; + } + _o.SessionAuth = this.SessionAuth.HasValue ? this.SessionAuth.Value.UnPack() : null; + } + public static Offset Pack(FlatBufferBuilder builder, UploadSessionInfoT _o) { + if (_o == null) return default(Offset); + var _serviceInfo_type = _o.ServiceInfo == null ? ror.schema.upload.ServiceInfos.NONE : _o.ServiceInfo.Type; + var _serviceInfo = _o.ServiceInfo == null ? 0 : ror.schema.upload.ServiceInfosUnion.Pack(builder, _o.ServiceInfo); + var _sessionAuth = _o.SessionAuth == null ? default(Offset) : ror.schema.upload.UploadAuth.Pack(builder, _o.SessionAuth); + StartUploadSessionInfo(builder); + AddSession(builder, ror.schema.UUID.Pack(builder, _o.Session)); + AddOutOf(builder, _o.OutOf); + AddServiceInfoType(builder, _serviceInfo_type); + AddServiceInfo(builder, _serviceInfo); + AddSessionAuth(builder, _sessionAuth); + return EndUploadSessionInfo(builder); + } +}; + +public class UploadSessionInfoT +{ + public ror.schema.UUIDT Session { get; set; } + public ulong OutOf { get; set; } + public ror.schema.upload.ServiceInfosUnion ServiceInfo { get; set; } + public ror.schema.upload.UploadAuthT SessionAuth { get; set; } + + public UploadSessionInfoT() { + this.Session = new ror.schema.UUIDT(); + this.OutOf = 0; + this.ServiceInfo = null; + this.SessionAuth = null; + } +} + + +} diff --git a/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadSessionInfo.cs.meta b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadSessionInfo.cs.meta new file mode 100644 index 0000000..c7674f5 --- /dev/null +++ b/Assets/ARDK/Plugins/unity_exports/ardk_client_platform/libs/ror_upload_schema_unity/ror_upload_schema_unity/schema/upload/ror/schema/upload/UploadSessionInfo.cs.meta @@ -0,0 +1,2 @@ +fileFormat: 2 +guid: 73e77836d25b95ef8e14d19b35f8fa20 diff --git a/Assets/ARDK/Properties.meta b/Assets/ARDK/Properties.meta new file mode 100644 index 0000000..451f1de --- /dev/null +++ b/Assets/ARDK/Properties.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 1382cd7d85234437a8e4f4ad0ea4c424 +folderAsset: yes +timeCreated: 1547224578 +licenseType: Pro +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Properties/AssemblyInfo.cs b/Assets/ARDK/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..cb841f2 --- /dev/null +++ b/Assets/ARDK/Properties/AssemblyInfo.cs @@ -0,0 +1,11 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.Runtime.CompilerServices; + +[assembly:InternalsVisibleTo("Grapeshot")] +[assembly:InternalsVisibleTo("ARDK-Editor")] +[assembly:InternalsVisibleTo("ARDKTests")] +[assembly:InternalsVisibleTo("ARDKPlayModeTests")] +[assembly: InternalsVisibleTo("ARDKTestTools")] +[assembly:InternalsVisibleTo("DynamicProxyGenAssembly2")] +[assembly:InternalsVisibleTo("ARDKTestScenes")] diff --git a/Assets/ARDK/Properties/AssemblyInfo.cs.meta b/Assets/ARDK/Properties/AssemblyInfo.cs.meta new file mode 100644 index 0000000..6d5b174 --- /dev/null +++ b/Assets/ARDK/Properties/AssemblyInfo.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: daa88cd342e694d35895ea1304cd4526 +timeCreated: 1547224601 +licenseType: Pro +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Recording.meta b/Assets/ARDK/Recording.meta new file mode 100644 index 0000000..3232369 --- /dev/null +++ b/Assets/ARDK/Recording.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e3d675c46dcdc4cec89e383a2fbf67e3 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Recording/ARCapture.cs b/Assets/ARDK/Recording/ARCapture.cs new file mode 100644 index 0000000..60b9c6f --- /dev/null +++ b/Assets/ARDK/Recording/ARCapture.cs @@ -0,0 +1,309 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +#if UNITY_STANDALONE_OSX || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_WIN +#define UNITY_STANDALONE_DESKTOP +#endif +#if (UNITY_IOS || UNITY_ANDROID || UNITY_STANDALONE_DESKTOP) && !UNITY_EDITOR +#define AR_NATIVE_SUPPORT +#endif + +using System; +using System.Security; +using System.Runtime.InteropServices; +using System.Text; + +using Niantic.ARDK.AR; +using Niantic.ARDK.Internals; + +using UnityEngine; + +namespace Niantic.ARDK.Recording +{ + /// + /// Native interface to the NAR POI AR Capture API (Recorder v2). + /// + public sealed class ARCapture: + IDisposable + { + private HandleRef _nativeHandle; + + public ARCapture(Guid stageIdentifier) + { + unsafe + { + var stageIdentifierBytes = stageIdentifier.ToByteArray(); + + fixed (byte* stageIdentifierPtr = stageIdentifierBytes) + { + var nativePtr = PInvoke.Ctor(stageIdentifierPtr); + _nativeHandle = new HandleRef(this, nativePtr); + } + } + } + + ~ARCapture() + { + ReleaseUnmanagedResources(); + } + + /// + /// Starts capturing an AR session. + /// + public void Start(ARCaptureConfig captureConfig) + { + PInvoke.Start(_nativeHandle, captureConfig); + } + + /// + /// Stops capturing a session. + /// + public void Stop() + { + PInvoke.Stop(_nativeHandle); + } + + /// + /// Returns the capture's recording status. + /// true if a recording session is active. + /// + public bool IsRecording() + { + return PInvoke.IsRecording(_nativeHandle); + } + + /// + /// Retrieves the capture's recording paths. + /// The recorder *must* be started before calling this method. + /// The recording path config used by the capture if a capture is running, empty paths otherwise + /// + public ARCaptureConfig GetCapturePaths() + { + + if (IsRecording()) + { + return PInvoke.GetPaths(_nativeHandle); + } + + return ARCaptureConfig.Default; + } + + /// + /// Stores the name of the application. + /// Calling this method multiple times will override previous calls. + /// The recorder *must* be started before calling this method. + /// The name of the application. + /// + public void SetApplicationName(String applicationName) + { + if (!IsRecording()) + { + Debug.LogWarning("Calling SetApplicationName() while not recording!"); + return; + } + + ARCaptureSetMetadataConfig config = new ARCaptureSetMetadataConfig + { + Metadata = "{ \"app\": \"" + applicationName + "\"}" + }; + + PInvoke.SetMetadata(_nativeHandle, config); + } + + /// + /// Stores the point of interest, represented as a string. + /// Calling this method multiple times will override previous calls. + /// The recorder *must* be started before calling this method. + /// The identifier of the point of interest. + /// + public void SetPointOfInterest(String pointOfInterest) + { + if (!IsRecording()) + { + Debug.LogWarning("Calling SetPointOfInterest() while not recording!"); + return; + } + + ARCaptureSetMetadataConfig config = new ARCaptureSetMetadataConfig + { + Metadata = "{ \"poi\": \"" + pointOfInterest + "\"}" + }; + + PInvoke.SetMetadata(_nativeHandle, config); + } + + /// + /// Stores free-form, application-specific metadata. + /// Calling this method multiple times will overwrite elements previously set. + /// The recorder *must* be started before calling this method. + /// Well-formed JSON dictionary string. + /// + public void SetJSONMetadata(String jsonMetadata) + { + if (!IsRecording()) + { + Debug.LogWarning("Calling SetJSONMetadata() while not recording!"); + return; + } + + ARCaptureSetMetadataConfig config = new ARCaptureSetMetadataConfig + { + Metadata = "{ \"metadata\": " + jsonMetadata + "}" + }; + + PInvoke.SetMetadata(_nativeHandle, config); + } + + private void ReleaseUnmanagedResources() + { + if (_nativeHandle.Handle != IntPtr.Zero) + { + PInvoke.Dtor(_nativeHandle); + _nativeHandle = new HandleRef(); + } + } + + public void Dispose() + { + ReleaseUnmanagedResources(); + GC.SuppressFinalize(this); + } + + #pragma warning disable + /// + /// The pinvokes that call down to the native side of the code. + /// + private static class PInvoke + { + /// + /// Constructs the recorder. + /// + /// Ptr to the UUID in memory. + /// + /// The native ptr to this object (or a ptr that can be used with the native side code). + /// + public static unsafe IntPtr Ctor(void* uuidPtr) + { +#if AR_NATIVE_SUPPORT + return _NARCapture_Init(uuidPtr); +#else + return IntPtr.Zero; +#endif + } + + /// + /// Destroys the recorder. + /// + /// The handle to the native object. + public static void Dtor(HandleRef nativeHandle) + { +#if AR_NATIVE_SUPPORT + _NARCapture_Release(nativeHandle.Handle); +#endif + } + + /// + /// Starts recording on the given recorder. + /// + /// The native handle to the recorder. + /// The config object containing paths to working directory and archive file. + public static void Start(HandleRef nativeHandle, ARCaptureConfig captureConfig) + { + +#if AR_NATIVE_SUPPORT + _NARCapture_Start(nativeHandle.Handle, captureConfig); +#endif + } + + /// + /// Stops recording on the native side code. + /// + /// The native recorder to stop recording on. + public static void Stop(HandleRef nativeHandle) + { +#if AR_NATIVE_SUPPORT + _NARCapture_Stop(nativeHandle.Handle); +#endif + } + + /// + /// Stores application-specific metadata. + /// Calling this method multiple times will overwrite elements previously set. + /// The recorder *must* be started before calling this method. + /// The native recorder to set metadata on. + /// The native recorder to stop recording on. + /// + public static void SetMetadata(HandleRef nativeHandle, ARCaptureSetMetadataConfig config) { +#if AR_NATIVE_SUPPORT + _NARCapture_SetMetadata(nativeHandle.Handle, config); +#endif + } + + /// + /// Returns the capture's recording status. + /// The native recorder to call. + /// true if a recording session is active for the provided handle. + /// + public static bool IsRecording(HandleRef nativeHandle) + { +#if AR_NATIVE_SUPPORT + return _NARCapture_IsRecording(nativeHandle.Handle); +#else + return false; +#endif + } + + /// + /// Returns the capture's recording paths. + /// The recorder *must* be started before calling this method. + /// The native recorder to call. + /// The paths used by the capture session. + /// + public static ARCaptureConfig GetPaths(HandleRef nativeHandle) + { +#if AR_NATIVE_SUPPORT + int bufferSize = 512; + StringBuilder workingDirectoryPath = new StringBuilder(bufferSize); + StringBuilder archivePath = new StringBuilder(bufferSize); + int pathLength = _NARCapture_GetPaths(nativeHandle.Handle, workingDirectoryPath, archivePath, bufferSize); + if (pathLength > bufferSize) + { + // try again with bigger buffer + bufferSize = pathLength + 8; + workingDirectoryPath = new StringBuilder(bufferSize); + archivePath = new StringBuilder(bufferSize); + _NARCapture_GetPaths(nativeHandle.Handle, workingDirectoryPath, archivePath, bufferSize); + } + return new ARCaptureConfig + { + WorkingDirectoryPath = workingDirectoryPath.ToString(), + ArchivePath = archivePath.ToString() + }; +#else + return ARCaptureConfig.Default; +#endif + } + + [DllImport(_ARDKLibrary.libraryName)] + private static extern unsafe IntPtr _NARCapture_Init(void* uuidPtr); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARCapture_Release(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARCapture_Start(IntPtr nativeHandle, ARCaptureConfig captureConfig); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARCapture_Stop(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARCapture_SetMetadata(IntPtr nativeHandle, ARCaptureSetMetadataConfig config); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern bool _NARCapture_IsRecording(IntPtr nativeHandle); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern int _NARCapture_GetPaths(IntPtr nativeHandle, StringBuilder workingDirectoryOut, StringBuilder archiveOut, int bufferSize); + } + } +} +#pragma warning enable diff --git a/Assets/ARDK/Recording/ARCapture.cs.meta b/Assets/ARDK/Recording/ARCapture.cs.meta new file mode 100644 index 0000000..f51e780 --- /dev/null +++ b/Assets/ARDK/Recording/ARCapture.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a5122626103c471b85fe6b9c53837289 +timeCreated: 1592321079 \ No newline at end of file diff --git a/Assets/ARDK/Recording/ARCaptureConfig.cs b/Assets/ARDK/Recording/ARCaptureConfig.cs new file mode 100644 index 0000000..a56d22d --- /dev/null +++ b/Assets/ARDK/Recording/ARCaptureConfig.cs @@ -0,0 +1,75 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.Runtime.InteropServices; + +namespace Niantic.ARDK.Recording +{ + /// + /// Configs for AR captures. + /// + [StructLayout(LayoutKind.Sequential)] + public struct ARCaptureConfig + { + /// + /// The target destination folder path for capture data. + /// This working directory will contain individual frames as JPEG files. + /// It will be created by the native API as soon as the capture is started. + /// The client is responsible for deleting this folder after the capture ends. + /// + [MarshalAs(UnmanagedType.LPStr)] + public string WorkingDirectoryPath; + + /// + /// The target destination file path for the archived capture data. + /// This is the path to the archive file that will be created by the native API + /// as soon as the capture is stopped. + /// The client is responsible for deleting the file at this path after it is + /// uploaded. + /// + [MarshalAs(UnmanagedType.LPStr)] + public string ArchivePath; + + [MarshalAs(UnmanagedType.Bool)] + public bool CaptureLidarIfAvailable; + + /// + /// Creates an ARCaptureConfig, with helpers to provide defaults. + /// + /// + /// The target destination folder path for capture data. + /// This working directory will contain individual frames as JPEG files. + /// It will be created by the native API as soon as the capture is started. + /// The client is responsible for deleting this folder after the capture ends. + /// If null, the recorder picks a working path and deletes it after archiving. + /// + /// + /// The target destination file path for the archived capture data. + /// This is the path to the archive file that will be created by the native API + /// as soon as the capture is stopped. The file must end with ".tgz" and be in + /// a valid path. + /// The client is responsible for deleting the file at this path after it is + /// uploaded. + /// If not given, appends ".tgz" to the working path. + /// + /// @note If this struct with all default values is desired, use the Default property instead. + public ARCaptureConfig(string workingPath = null, string archivePath = null) + { + WorkingDirectoryPath = workingPath; + ArchivePath = archivePath; + CaptureLidarIfAvailable = false; + } + + public static ARCaptureConfig Default + { + get + { + return new ARCaptureConfig + { + WorkingDirectoryPath = null, + ArchivePath = null, + CaptureLidarIfAvailable = false + }; + } + } + } +} diff --git a/Assets/ARDK/Recording/ARCaptureConfig.cs.meta b/Assets/ARDK/Recording/ARCaptureConfig.cs.meta new file mode 100644 index 0000000..b6a42ba --- /dev/null +++ b/Assets/ARDK/Recording/ARCaptureConfig.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a8f20d3d95af4576b8089f38278edae1 +timeCreated: 1594080300 \ No newline at end of file diff --git a/Assets/ARDK/Recording/ARCaptureSetMetadataConfig.cs b/Assets/ARDK/Recording/ARCaptureSetMetadataConfig.cs new file mode 100644 index 0000000..b7f5a1a --- /dev/null +++ b/Assets/ARDK/Recording/ARCaptureSetMetadataConfig.cs @@ -0,0 +1,19 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.IO; +using System.Runtime.InteropServices; +using UnityEngine; + +namespace Niantic.ARDK.Recording { + /// + /// Configs for setting capture metadata. + /// + [StructLayout(LayoutKind.Sequential)] + public struct ARCaptureSetMetadataConfig { + /// + /// JSON-formatted dictionary of metadata fields to add to the capture. + /// + [MarshalAs(UnmanagedType.LPStr)] public string Metadata; + } +} \ No newline at end of file diff --git a/Assets/ARDK/Recording/ARCaptureSetMetadataConfig.cs.meta b/Assets/ARDK/Recording/ARCaptureSetMetadataConfig.cs.meta new file mode 100644 index 0000000..087faab --- /dev/null +++ b/Assets/ARDK/Recording/ARCaptureSetMetadataConfig.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5fa6e49193554dbc9d5842a79c2c6933 +timeCreated: 1592437672 \ No newline at end of file diff --git a/Assets/ARDK/Rendering.meta b/Assets/ARDK/Rendering.meta new file mode 100644 index 0000000..35b2adc --- /dev/null +++ b/Assets/ARDK/Rendering.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fbe6fb6b9f6d942fc81d424a73658209 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Rendering/ARFrameRendererFactory.cs b/Assets/ARDK/Rendering/ARFrameRendererFactory.cs new file mode 100644 index 0000000..bcce79c --- /dev/null +++ b/Assets/ARDK/Rendering/ARFrameRendererFactory.cs @@ -0,0 +1,107 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; +using System.Collections.Generic; +using System.ComponentModel; + +using Niantic.ARDK.AR; +using Niantic.ARDK.VirtualStudio.Remote; + +using UnityEngine; + +namespace Niantic.ARDK.Rendering +{ + public static class ARFrameRendererFactory + { + // Recommended near and far clipping settings for AR rendering + private const float DefaultNearClipping = 0.1f; + private const float DefaultFarClipping = 100f; + + private static ARFrameRenderer _Create + ( + RenderTarget target, + IEnumerable envs, + float nearClipping, + float farClipping + ) + { + bool triedAtLeast1 = false; + + if (envs != null) + { + foreach (var env in envs) + { + var possibleResult = Create(target, env, nearClipping, farClipping); + if (possibleResult != null) + return possibleResult; + + triedAtLeast1 = true; + } + } + + if (!triedAtLeast1) + return _Create(target, ARSessionFactory._defaultBestMatches, nearClipping, farClipping); + + throw new NotSupportedException("None of the provided envs are supported by this build."); + } + + /// Create an ARFrameRenderer with the specified RuntimeEnvironment. + /// @param env The runtime environment to create the renderer for. + /// @returns The created renderer, or null if it was not possible to create a renderer. + public static ARFrameRenderer Create + ( + RenderTarget target, + RuntimeEnvironment env, + float nearClipping = DefaultNearClipping, + float farClipping = DefaultFarClipping + ) + { + ARFrameRenderer result; + switch (env) + { + case RuntimeEnvironment.Default: + return _Create(target, null, nearClipping, farClipping); + + case RuntimeEnvironment.LiveDevice: +#pragma warning disable CS0162 + if (NativeAccess.Mode != NativeAccess.ModeType.Native && NativeAccess.Mode != NativeAccess.ModeType.Testing) + return null; + +#if UNITY_IOS + result = new _ARKitFrameRenderer(target, nearClipping, farClipping); +#elif UNITY_ANDROID + result = new _ARCoreFrameRenderer(target, nearClipping, farClipping); +#else + return null; +#endif + break; +#pragma warning restore CS0162 + + case RuntimeEnvironment.Remote: + if (!_RemoteConnection.IsEnabled) + return null; + + result = new _RemoteFrameRenderer(target, nearClipping, farClipping); + break; + + case RuntimeEnvironment.Mock: + result = new _MockFrameRenderer(target, nearClipping, farClipping); + break; + + default: + throw new InvalidEnumArgumentException(nameof(env), (int)env, env.GetType()); + } + + return result; + } + + internal static ARFrameRenderer _CreatePlayback + ( + RenderTarget target, + float nearClipping = DefaultNearClipping, + float farClipping = DefaultFarClipping + ) + { + return new _ARPlaybackFrameRenderer(target,nearClipping, farClipping); + } + } +} diff --git a/Assets/ARDK/Rendering/ARFrameRendererFactory.cs.meta b/Assets/ARDK/Rendering/ARFrameRendererFactory.cs.meta new file mode 100644 index 0000000..69dc2c2 --- /dev/null +++ b/Assets/ARDK/Rendering/ARFrameRendererFactory.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4d4ed5db240247c89fc986306473a99b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Rendering/ARSessionBuffersHelper.cs b/Assets/ARDK/Rendering/ARSessionBuffersHelper.cs new file mode 100644 index 0000000..bf6cc25 --- /dev/null +++ b/Assets/ARDK/Rendering/ARSessionBuffersHelper.cs @@ -0,0 +1,176 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.Awareness.Depth; + +#if ARDK_HAS_URP +using Niantic.ARDK.Rendering.SRP; +#endif + +using UnityEngine; +using UnityEngine.Rendering; + +namespace Niantic.ARDK.Rendering +{ + public static class ARSessionBuffersHelper + { + /// Adds an IssuePluginEventAndData step to the provided commandBuffer. This method must + /// be called and the given command buffer must be executed in order to receive AR updates + /// on Android devices. + /// @param commandBuffer The command buffer to add the IssuePluginEventAndData step to. + /// @param arSession The AR session to fetch updates for. + public static void IssuePluginEventAndData + ( + this CommandBuffer commandBuffer, + IARSession arSession + ) + { + if (arSession is _NativeARSession nativeSession) + nativeSession.SetupCommandBuffer(commandBuffer); + } + + public static void AddBackgroundBuffer(Camera camera, CommandBuffer commandBuffer) + { + if (camera == null) + throw new ArgumentNullException(nameof(camera)); + + if (commandBuffer == null) + throw new ArgumentNullException(nameof(commandBuffer)); + +#if ARDK_HAS_URP + if (_RenderPipelineInternals.IsUniversalRenderPipelineEnabled) + { + var rendererFeature = GetFeature(); + + if (rendererFeature != null) + { + rendererFeature.SetupBackgroundPass(camera, commandBuffer); + + // The render pass is enabled here to keep the effects of this + // method the same whether the URP is enabled or not + SetCameraRenderPassEnabled(true); + rendererFeature.SetActive(true); + } + + return; + } +#endif + + camera.AddCommandBuffer(CameraEvent.BeforeForwardOpaque, commandBuffer); + } + + public static void AddAfterRenderingBuffer(Camera camera, CommandBuffer commandBuffer) + { + if (camera == null) + throw new ArgumentNullException(nameof(camera)); + + if (commandBuffer == null) + throw new ArgumentNullException(nameof(commandBuffer)); + +#if ARDK_HAS_URP + if (_RenderPipelineInternals.IsUniversalRenderPipelineEnabled) + { + var rendererFeature = + _RenderPipelineInternals.GetFeatureOfType(); + + if (rendererFeature != null) + rendererFeature.SetupAfterRenderingPass(camera, commandBuffer); + + return; + } +#endif + + camera.AddCommandBuffer(CameraEvent.AfterEverything, commandBuffer); + } + + public static void RemoveBackgroundBuffer(Camera camera, CommandBuffer commandBuffer) + { +#if ARDK_HAS_URP + if (_RenderPipelineInternals.IsUniversalRenderPipelineEnabled) + { + var rendererFeature = GetFeature(); + + if (rendererFeature != null) + rendererFeature.RemoveBackgroundPass(); + + return; + } +#endif + + if (camera == null) + { + var msg = + "Camera is null. If the camera was destroyed, you don't need to explicitly remove " + + "this command buffer."; + throw new ArgumentNullException(nameof(camera), msg); + } + + if (commandBuffer == null) + throw new ArgumentNullException(nameof(commandBuffer)); + + var cbHandle = commandBuffer; + if (cbHandle != null) + camera.RemoveCommandBuffer(CameraEvent.BeforeForwardOpaque, cbHandle); + } + + public static void RemoveAfterRenderingBuffer(Camera camera, CommandBuffer commandBuffer) + { +#if ARDK_HAS_URP + if (_RenderPipelineInternals.IsUniversalRenderPipelineEnabled) + { + var rendererFeature = GetFeature(); + + if (rendererFeature != null) + rendererFeature.RemoveNativePass(); + + return; + } +#endif + + if (camera == null) + { + var msg = + "Camera is null. If the camera was destroyed, you don't need to explicitly remove " + + "this command buffer."; + throw new ArgumentNullException(nameof(camera), msg); + } + + if (commandBuffer == null) + throw new ArgumentNullException(nameof(commandBuffer)); + + var cbHandle = commandBuffer; + if (cbHandle != null) + camera.RemoveCommandBuffer(CameraEvent.AfterEverything, cbHandle); + } + +#if ARDK_HAS_URP + public static void SetCameraRenderPassEnabled(bool isEnabled) + { + var rendererFeature = GetFeature(); + + if (rendererFeature != null) + rendererFeature.settings.IsBackgroundPassEnabled = isEnabled; + } + + private static ARSessionFeature GetFeature() + { + var feature = + _RenderPipelineInternals.GetFeatureOfType(); + + if (feature == null) + { + var message = + "No ARSessionFeature was found added to the " + + "active Universal Render Pipeline Renderer."; + + Debug.LogError(message); + return null; + } + + return feature; + } +#endif + } +} diff --git a/Assets/ARDK/Rendering/ARSessionBuffersHelper.cs.meta b/Assets/ARDK/Rendering/ARSessionBuffersHelper.cs.meta new file mode 100644 index 0000000..bbce735 --- /dev/null +++ b/Assets/ARDK/Rendering/ARSessionBuffersHelper.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: cca1a6633bab4a5e971c094689182daf +timeCreated: 1602009013 \ No newline at end of file diff --git a/Assets/ARDK/Rendering/FrameRenderer.meta b/Assets/ARDK/Rendering/FrameRenderer.meta new file mode 100644 index 0000000..da44caf --- /dev/null +++ b/Assets/ARDK/Rendering/FrameRenderer.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e128c77cb5f44a65b43df3aaa9807726 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Rendering/FrameRenderer/ARFrameRenderer.cs b/Assets/ARDK/Rendering/FrameRenderer/ARFrameRenderer.cs new file mode 100644 index 0000000..cbfbf6e --- /dev/null +++ b/Assets/ARDK/Rendering/FrameRenderer/ARFrameRenderer.cs @@ -0,0 +1,527 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; +using System.Collections.Generic; +using System.Linq; + +using Niantic.ARDK.AR; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; +using UnityEngine.Assertions; +using UnityEngine.Rendering; + +using Object = UnityEngine.Object; + +namespace Niantic.ARDK.Rendering +{ + /// Rendering logic and resources shared across all platforms. + public abstract class ARFrameRenderer: + IARFrameRenderer, + IDisposable + { +#region IARFrameRenderer Overrides + public RenderTarget Target { get; } + public Resolution Resolution { get; } + public Matrix4x4 DisplayTransform { get; private set; } + public Matrix4x4 ProjectionTransform { get; private set; } + + public float NearPlane + { + get + { + return _nearClipPlane; + } + set + { + _nearClipPlane = value; + if (Target.IsTargetingCamera) + Target.Camera.nearClipPlane = value; + } + } + + public float FarPlane + { + get + { + return _farClipPlane; + } + set + { + _farClipPlane = value; + if (Target.IsTargetingCamera) + Target.Camera.farClipPlane = value; + } + } + + public GraphicsFence? GPUFence { get; protected set; } + + public virtual int RecommendedFrameRate + { + get + { + return Application.platform == RuntimePlatform.Android ? 30 : 60; + } + } + + /// Event for when the renderer had just finished rendering to its primary target. + public event ArdkEventHandler FrameRendered; + + public void AddFeatureProvider(IRenderFeatureProvider provider) + { + if (!_isInitialized) + throw new InvalidOperationException + ( + "Cannot add IRenderStateProvider components. The renderer has not yet been initialized." + ); + + if (_stateProviders.Contains(provider)) + { + ARLog._Warn("The specified render state provider is already attached to the renderer."); + return; + } + + var features = provider.Features; + if (_stateProviders.Any(entry => entry.Features.Overlaps(features))) + throw new InvalidOperationException("Tried to add a conflicting IRenderStateProvider instance."); + + // Listen to when the provider enables or disables render features + provider.ActiveFeaturesChanged += ActiveFeaturesChanged; + + // Assign render target + provider.Target = Target; + + // Register the provider + _stateProviders.Add(provider); + } + + public void RemoveFeatureProvider(IRenderFeatureProvider provider) + { + if (!_isInitialized) + return; + + if (!_stateProviders.Contains(provider)) + { + ARLog._Warn("The specified render state provider is not attached to the renderer."); + return; + } + + provider.ActiveFeaturesChanged -= ActiveFeaturesChanged; + _stateProviders.Remove(provider); + } +#endregion + +#region Abstraction Layer + /// The platform specific shader used to render the frame. + protected abstract Shader Shader { get; } + + /// Invoked when it is time to allocate rendering resources + /// and configure the platform specific pipeline. + /// @param target The specified render target. + /// @param targetResolution Desired resolution of the artifact. + /// @param sourceResolution The resolution of the native textures. + /// @param renderMaterial Material that will be used for rendering. + /// @returns Fence that should be waited on in other command buffers that utilize the + /// texture output by this renderer. + protected abstract GraphicsFence? OnConfigurePipeline + ( + RenderTarget target, + Resolution targetResolution, + Resolution sourceResolution, + Material renderMaterial + ); + + /// Invoked when it is time to update the renderer's internal state before rendering. + /// This call is required to populate the provided material's properties with + /// information from the ARFrame. + /// @param frame Frame to render. + /// @param projectionTransform Projection matrix. + /// @param displayTransform Affine transform to properly present the image on the screen. + /// @param material The material that will be used to render the frame. + /// @returns Whether the provided information was sufficient to render the frame. + protected abstract bool OnUpdateState + ( + IARFrame frame, + Matrix4x4 projectionTransform, + Matrix4x4 displayTransform, + Material material + ); + + /// Invoked if it is time to add any command buffers to the camera. + protected abstract void OnAddToCamera(Camera camera); + + /// Invoked if it is time to remove any command buffers to the camera. + protected abstract void OnRemoveFromCamera(Camera camera); + + /// Invoked if it is time to manually perform the GPU commands to render the frame. + protected abstract void OnIssueCommands(); + + /// Invoked when this renderer is about to be deallocated. + protected abstract void OnRelease(); +#endregion + + // State variables... + private bool _isInitialized; + private bool _didConfigurePipeline; + + public bool IsEnabled { get; private set; } + + // Clipping plane distances for projection + private float _nearClipPlane = 0.1f; + private float _farClipPlane = 100.0f; + + // Cached initial screen orientation + private readonly ScreenOrientation _originalOrientation; + + /// Material used to render the frame. + private Material _renderMaterial; + + /// Whether the renderer is allowed to rotate the image. + public bool IsOrientationLocked = false; + + // A collection of the components that provide additional + // information to render an AR Frame. + private readonly List _stateProviders = new List(); + + /// Allocates a new ARFrameRenderer. + /// @param target The render target AR frames will be rendered to. + /// If this is a camera, its projection matrix will + /// automatically get updated for each frame. + protected ARFrameRenderer(RenderTarget target) + { + _originalOrientation = RenderTarget.ScreenOrientation; + + Target = target; + Resolution = target.GetResolution(_originalOrientation); + + if (target.IsTargetingCamera) + { + // Set frustum to match the camera + var camera = target.Camera; + _nearClipPlane = camera.nearClipPlane; + _farClipPlane = camera.farClipPlane; + } + } + + /// Allocates a new ARFrameRenderer using specified frustum planes. + /// @param target The render target AR frames will be rendered to. + /// If this is a camera, its projection matrix will + /// automatically get updated for each frame. + /// @param near The distance of the near clipping plane. + /// @param far The distance of the far clipping plane. + protected ARFrameRenderer(RenderTarget target, float near, float far) + { + _originalOrientation = RenderTarget.ScreenOrientation; + + Target = target; + Resolution = target.GetResolution(_originalOrientation); + NearPlane = near; + FarPlane = far; + } + + /// Initializes rendering resources. + /// @note This needs to be called before any frame is sent to this renderer to process. + public void Initialize() + { + if (_isInitialized) + { + ARLog._Error("The ARFrameRenderer is already initialized"); + return; + } + + // Acquire the platform specific shader + Shader platformShader = Shader; + Assert.IsNotNull(platformShader, "platformShader != null"); + + // Allocate the frame rendering material + _renderMaterial = new Material(platformShader); + + _isInitialized = true; + } + + /// Enables the renderer. If the renderer is targeting a camera, + /// this will attach the execution of the rendering commands to it. + public void Enable() + { + if (IsEnabled) + return; + + // Cache state + IsEnabled = true; + + // Wait for the pipeline to initialize + if (!_didConfigurePipeline) + return; + + if (Target.IsTargetingCamera) + { + RegisterCameraEvents(); + OnAddToCamera(Target.Camera); + } + } + + /// Disables the renderer. The rendering commands will be + /// detached from the target camera, if any. + public void Disable() + { + if (!IsEnabled) + return; + + // Cache state + IsEnabled = false; + + // Wait for the pipeline to initialize + if (!_didConfigurePipeline) + return; + + if (Target.IsTargetingCamera) + { + UnregisterCameraEvents(); + OnRemoveFromCamera(Target.Camera); + Target.Camera.ResetProjectionMatrix(); + } + } + + private void RegisterCameraEvents() + { +#if ARDK_HAS_URP + RenderPipelineManager.endCameraRendering += RenderPipelineManager_OnEndCameraRendering; +#else + Camera.onPostRender += Camera_OnPostRender; +#endif + } + + private void UnregisterCameraEvents() + { +#if ARDK_HAS_URP + RenderPipelineManager.endCameraRendering -= RenderPipelineManager_OnEndCameraRendering; +#else + Camera.onPostRender -= Camera_OnPostRender; +#endif + } + + private void ConfigurePipeline + ( + RenderTarget target, + Resolution targetResolution, + Resolution sourceResolution, + Material renderMaterial + ) + { + if (_didConfigurePipeline) + return; + + // Set up the platform specific commands + GPUFence = OnConfigurePipeline(target, targetResolution, sourceResolution, renderMaterial); + + // If this renderer is already enabled by the time it + // initialized, hook up to the target camera's loop + if (IsEnabled && Target.IsTargetingCamera) + { + RegisterCameraEvents(); + OnAddToCamera(Target.Camera); + } + + // Done + _didConfigurePipeline = true; + } + + public void UpdateState(IARFrame withFrame) + { + if (!_isInitialized || !IsEnabled) + return; + + if (withFrame?.Camera == null || withFrame?.CapturedImageTextures == null) + return; + + // We configure the rendering pipeline after the + // first frame update to gather more information + if (!_didConfigurePipeline) + ConfigurePipeline + ( + target: Target, + targetResolution: Resolution, + sourceResolution: withFrame.Camera.ImageResolution, + renderMaterial: _renderMaterial + ); + + // Calculate camera matrices + UpdateCameraMatrices(withFrame); + + // Update states from the ARFrame + var didUpdateState = OnUpdateState + ( + withFrame, + ProjectionTransform, + DisplayTransform, + _renderMaterial + ); + + if (!didUpdateState) + return; + + // Update states from additional providers + for (var i = 0; i < _stateProviders.Count; i++) + _stateProviders[i].UpdateRenderState(_renderMaterial); + + // in case we're rendering offscreen... + if (!Target.IsTargetingCamera) + { + // ... execute the command buffer now + OnIssueCommands(); + + // Propagate event + FrameRendered?.Invoke(new FrameRenderedArgs(this)); + } + else + { + // In case we are targeting a camera, update its projection + Target.Camera.projectionMatrix = ProjectionTransform; + } + } + + /// Performs a graphics blit to the specified texture using the renderer's current + /// internal state. To update the renderer's state, use the UpdateState(IARFrame) API. + /// @param texture The render target. This texture needs to be already allocated. + public void BlitToTexture(ref RenderTexture texture) + { + if (!_didConfigurePipeline) + throw new InvalidOperationException + ("The ARFrameRenderer component cannot blit to texture in its current state"); + + if (texture == null) + return; + + Graphics.Blit(null, texture, _renderMaterial); + } + +#if ARDK_HAS_URP + + private void RenderPipelineManager_OnEndCameraRendering(ScriptableRenderContext context, Camera cam) + { + // Propagate event + if (Target.Camera == cam) + FrameRendered?.Invoke(new FrameRenderedArgs(this)); + } + +#else + + private void Camera_OnPostRender(Camera cam) + { + // Propagate event + if (Target.Camera == cam) + FrameRendered?.Invoke(new FrameRenderedArgs(this)); + } + +#endif + + private void ActiveFeaturesChanged(RenderFeaturesChangedArgs args) + { + var featuresEnabled = args.Configuration.FeaturesEnabled; + if (featuresEnabled != null) + { + foreach (var feature in featuresEnabled) + { + ARLog._Debug("Enable: " + feature); + _renderMaterial.EnableKeyword(feature); + } + } + + var featuresDisabled = args.Configuration.FeaturesDisabled; + if (featuresDisabled != null) + { + foreach (var feature in featuresDisabled) + { + ARLog._Debug("Disable: " + feature); + _renderMaterial.DisableKeyword(feature); + } + } + } + + private void Release() + { + OnRelease(); + + if (_renderMaterial != null) + Object.Destroy(_renderMaterial); + } + + public void Dispose() + { + // Disable renderer + Disable(); + + // Remove render state providers + foreach (var provider in _stateProviders) + provider.ActiveFeaturesChanged -= ActiveFeaturesChanged; + + _stateProviders.Clear(); + + Release(); + GC.SuppressFinalize(this); + } + + ~ARFrameRenderer() + { + Release(); + } + +#region Utility Methods + protected static void CreateOrUpdateExternalTexture + ( + ref Texture2D texture, + Resolution resolution, + TextureFormat format, + IntPtr nativeHandle + ) + { + if (texture == null) + { + texture = Texture2D.CreateExternalTexture + ( + resolution.width, + resolution.height, + format, + false, + false, + nativeHandle + ); + } + else + { + texture.UpdateExternalTexture(nativeHandle); + } + } + + private void UpdateCameraMatrices(IARFrame frame) + { + // Determine target orientation + var targetOrientation = IsOrientationLocked + ? _originalOrientation + : RenderTarget.ScreenOrientation; + + // Calculate the target resolution according to the orientation + var targetResolution = Target.GetResolution(targetOrientation); + + // Update the projection matrix + ProjectionTransform = frame.Camera.CalculateProjectionMatrix + ( + targetOrientation, + targetResolution.width, + targetResolution.height, + _nearClipPlane, + _farClipPlane + ); + + // Update the display transform matrix + DisplayTransform = frame.CalculateDisplayTransform + ( + targetOrientation, + targetResolution.width, + targetResolution.height + ); + } + + #endregion + } +} diff --git a/Assets/ARDK/Rendering/FrameRenderer/ARFrameRenderer.cs.meta b/Assets/ARDK/Rendering/FrameRenderer/ARFrameRenderer.cs.meta new file mode 100644 index 0000000..36acef5 --- /dev/null +++ b/Assets/ARDK/Rendering/FrameRenderer/ARFrameRenderer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cd880f561fe424ceb8e0b1b45c869465 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Rendering/FrameRenderer/IARFrameRenderer.cs b/Assets/ARDK/Rendering/FrameRenderer/IARFrameRenderer.cs new file mode 100644 index 0000000..70107e1 --- /dev/null +++ b/Assets/ARDK/Rendering/FrameRenderer/IARFrameRenderer.cs @@ -0,0 +1,66 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using Niantic.ARDK.Utilities; + +using UnityEngine; +using UnityEngine.Rendering; + +namespace Niantic.ARDK.Rendering +{ + /// Arguments for rendering events. + /// @note This will be renamed to FrameRendererArgs in a future update + public class FrameRenderedArgs: + IArdkEventArgs + { + /// The renderer. + public readonly IARFrameRenderer Renderer; + + public FrameRenderedArgs(IARFrameRenderer renderer) + { + Renderer = renderer; + } + } + + public interface IARFrameRenderer + { + /// Event for when the renderer had just finished rendering to its primary target. + event ArdkEventHandler FrameRendered; + + /// Recommended target framerate of the platform. + int RecommendedFrameRate { get; } + + /// The render target. Either a camera or a GPU texture. + RenderTarget Target { get; } + + /// The resolution of a rendered frame image. + Resolution Resolution { get; } + + /// Affine transform for converting between normalized image coordinates and a + /// coordinate space appropriate for rendering the camera image onscreen. + Matrix4x4 DisplayTransform { get; } + + /// The projection matrix of the device's camera. This takes into account your device's + /// focal length, size of the sensor, distortions inherent in the lenses, autofocus, + /// temperature, and/or etc. + Matrix4x4 ProjectionTransform { get; } + + /// Distance of the near clipping plane in world units. + float NearPlane { get; set; } + + /// Distance of the far clipping plane in world units. + float FarPlane { get; set; } + + /// Fence that should be waited on in other command buffers that utilize the + /// texture output by this renderer. + /// @note Only available if the renderer has been initialized. + GraphicsFence? GPUFence { get; } + + /// Registers a new feature provider to this renderer. + /// Call this method to insert components to the pipeline + /// that alter or extend the background rendering. + void AddFeatureProvider(IRenderFeatureProvider provider); + + /// Removes the specified feature provider from this renderer, + /// if it is present in its pipeline. + void RemoveFeatureProvider(IRenderFeatureProvider provider); + } +} diff --git a/Assets/ARDK/Rendering/FrameRenderer/IARFrameRenderer.cs.meta b/Assets/ARDK/Rendering/FrameRenderer/IARFrameRenderer.cs.meta new file mode 100644 index 0000000..5449420 --- /dev/null +++ b/Assets/ARDK/Rendering/FrameRenderer/IARFrameRenderer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 034ef2ff0b8d443e49515699a858ceab +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Rendering/FrameRenderer/_ARCoreFrameRenderer.cs b/Assets/ARDK/Rendering/FrameRenderer/_ARCoreFrameRenderer.cs new file mode 100644 index 0000000..4af8bd0 --- /dev/null +++ b/Assets/ARDK/Rendering/FrameRenderer/_ARCoreFrameRenderer.cs @@ -0,0 +1,174 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; + +using Niantic.ARDK.AR; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; +using UnityEngine.Rendering; + +using System.Runtime.InteropServices; +using AOT; + +using Object = UnityEngine.Object; + +namespace Niantic.ARDK.Rendering +{ + internal sealed class _ARCoreFrameRenderer: + ARFrameRenderer + { + // Rendering resources + private CommandBuffer _commandBuffer; + private Texture2D _nativeTexture; + private RenderTexture _cachedTexture; + protected override Shader Shader { get; } + + // Resources for caching external textures + private readonly Shader _blitShader; + private Material _blitMaterial; + + public _ARCoreFrameRenderer(RenderTarget target) + : base(target) + { + // The blitting shader used for caching + _blitShader = Resources.Load("ExternalBlit"); + + // The main shader used for rendering the background + Shader = Resources.Load("ARCoreFrame"); + } + + public _ARCoreFrameRenderer + ( + RenderTarget target, + float near, + float far, + Shader customShader = null + ) : base(target, near, far) + { + // The blitting shader used for caching + _blitShader = Resources.Load("ExternalBlit"); + + // The main shader used for rendering the background + Shader = customShader ? customShader : Resources.Load("ARCoreFrame"); + ARLog._Debug("Loaded: " + (Shader != null ? Shader.name : null)); + } + + protected override GraphicsFence? OnConfigurePipeline + ( + RenderTarget target, + Resolution targetResolution, + Resolution sourceResolution, + Material renderMaterial + ) + { + _blitMaterial = new Material(_blitShader) + { + hideFlags = HideFlags.HideAndDontSave + }; + + // Allocate the texture cache for double buffering + _cachedTexture = new RenderTexture + ( + sourceResolution.width, + sourceResolution.height, + 0, + RenderTextureFormat.ARGB32 + ) + { + useMipMap = false, autoGenerateMips = false, filterMode = FilterMode.Point, anisoLevel = 0 + }; + + _cachedTexture.Create(); + + _commandBuffer = new CommandBuffer + { + name = "ARCoreFrameRenderer" + }; + + AddResetOpenGLState(_commandBuffer); + _commandBuffer.ClearRenderTarget(true, true, Color.clear); + _commandBuffer.Blit(null, Target.Identifier, renderMaterial); + +#if UNITY_2019_1_OR_NEWER + return _commandBuffer.CreateAsyncGraphicsFence(); +#else + return _commandBuffer.CreateGPUFence(); +#endif + } + + protected override void OnAddToCamera(Camera camera) + { + ARSessionBuffersHelper.AddBackgroundBuffer(camera, _commandBuffer); + } + + protected override void OnRemoveFromCamera(Camera camera) + { + ARSessionBuffersHelper.RemoveBackgroundBuffer(camera, _commandBuffer); + } + + protected override bool OnUpdateState + ( + IARFrame frame, + Matrix4x4 projectionTransform, + Matrix4x4 displayTransform, + Material material + ) + { + // We require a single plane image as source + if (frame.CapturedImageTextures.Length < 1 || frame.CapturedImageTextures[0] == IntPtr.Zero) + return false; + + // Update the native texture + CreateOrUpdateExternalTexture + ( + ref _nativeTexture, + frame.Camera.ImageResolution, + TextureFormat.ARGB32, + frame.CapturedImageTextures[0] + ); + + // On Android, the native texture is prone to change + // during rendering, so we work with a copy that we own. + _blitMaterial.SetTexture(PropertyBindings.FullImage, _nativeTexture); + var prevTarget = RenderTexture.active; + Graphics.Blit(null, _cachedTexture, _blitMaterial); + RenderTexture.active = prevTarget; + + // Bind texture and the display transform + material.SetTexture(PropertyBindings.FullImage, _cachedTexture); + material.SetMatrix(PropertyBindings.DisplayTransform, displayTransform); + + return true; + } + + protected override void OnIssueCommands() + { + Graphics.ExecuteCommandBuffer(_commandBuffer); + } + + protected override void OnRelease() + { + _commandBuffer?.Dispose(); + + if (_cachedTexture != null) + Object.Destroy(_cachedTexture); + + if (_nativeTexture != null) + Object.Destroy(_nativeTexture); + + if (_blitMaterial != null) + Object.Destroy(_blitMaterial); + } + + // Does nothing but returning from an IssuePluginEvent has the effect of Unity resetting all + // the OpenGL states to known values + [MonoPInvokeCallback(typeof(Action))] + static void ResetGlState(int eventId) {} + static Action s_ResetGlStateDelegate = ResetGlState; + static readonly IntPtr s_ResetGlStateFuncPtr = Marshal.GetFunctionPointerForDelegate(s_ResetGlStateDelegate); + private static void AddResetOpenGLState(CommandBuffer commandBuffer) + { + commandBuffer.IssuePluginEvent(s_ResetGlStateFuncPtr, 0); + } + } +} diff --git a/Assets/ARDK/Rendering/FrameRenderer/_ARCoreFrameRenderer.cs.meta b/Assets/ARDK/Rendering/FrameRenderer/_ARCoreFrameRenderer.cs.meta new file mode 100644 index 0000000..5120a84 --- /dev/null +++ b/Assets/ARDK/Rendering/FrameRenderer/_ARCoreFrameRenderer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 331580655c3ec45928c41d93b8f4dc24 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Rendering/FrameRenderer/_ARKitFrameRenderer.cs b/Assets/ARDK/Rendering/FrameRenderer/_ARKitFrameRenderer.cs new file mode 100644 index 0000000..e83751f --- /dev/null +++ b/Assets/ARDK/Rendering/FrameRenderer/_ARKitFrameRenderer.cs @@ -0,0 +1,135 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using Niantic.ARDK.AR; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; +using UnityEngine.Rendering; + +using Object = UnityEngine.Object; + +namespace Niantic.ARDK.Rendering +{ + internal sealed class _ARKitFrameRenderer: + ARFrameRenderer + { + // Rendering resources + private CommandBuffer _commandBuffer; + private Texture2D _textureY, _textureCbCr; + + protected override Shader Shader { get; } + + public _ARKitFrameRenderer(RenderTarget target) + : base(target) + { + Shader = Resources.Load("ARKitFrame"); + } + + public _ARKitFrameRenderer + ( + RenderTarget target, + float near, + float far, + Shader customShader = null + ) : base(target, near, far) + { + Shader = customShader ? customShader : Resources.Load("ARKitFrame"); + ARLog._Debug("Loaded: " + (Shader != null ? Shader.name : null)); + } + + protected override GraphicsFence? OnConfigurePipeline + ( + RenderTarget target, + Resolution targetResolution, + Resolution sourceResolution, + Material renderMaterial + ) + { + if (target.IsTargetingTexture) + { + // When not targeting a camera, we do not create a command buffer. + // This is because currently, executing the command buffer manually + // causes the GPU to hang on iOS. Could be a driver or Unity issue. + return null; + } + + _commandBuffer = new CommandBuffer + { + name = "ARKitFrameRenderer" + }; + + _commandBuffer.ClearRenderTarget(true, true, Color.clear); + _commandBuffer.Blit(null, target.Identifier, renderMaterial); + +#if UNITY_2019_1_OR_NEWER + return _commandBuffer.CreateAsyncGraphicsFence(); +#else + return _commandBuffer.CreateGPUFence(); +#endif + } + + protected override void OnAddToCamera(Camera camera) + { + ARSessionBuffersHelper.AddBackgroundBuffer(camera, _commandBuffer); + } + + protected override void OnRemoveFromCamera(Camera camera) + { + ARSessionBuffersHelper.RemoveBackgroundBuffer(camera, _commandBuffer); + } + + protected override void OnIssueCommands() + { + // This call raises GPU exceptions on iOS + // Graphics.ExecuteCommandBuffer(_commandBuffer); + + // As an alternative, we blit to the target + var target = Target.RenderTexture; + BlitToTexture(ref target); + } + + protected override bool OnUpdateState + ( + IARFrame frame, + Matrix4x4 projectionTransform, + Matrix4x4 displayTransform, + Material material + ) + { + // We require a biplanar input from ARKit + if (frame.CapturedImageTextures.Length < 2) + return false; + + var nativeResolution = frame.Camera.ImageResolution; + var yResolution = nativeResolution; + var uvResolution = new Resolution + { + width = nativeResolution.width / 2, height = nativeResolution.height / 2 + }; + + // Update source textures + CreateOrUpdateExternalTexture + (ref _textureY, yResolution, TextureFormat.R8, frame.CapturedImageTextures[0]); + + CreateOrUpdateExternalTexture + (ref _textureCbCr, uvResolution, TextureFormat.RG16, frame.CapturedImageTextures[1]); + + // Bind textures and the display transform + material.SetTexture(PropertyBindings.YChannel, _textureY); + material.SetTexture(PropertyBindings.CbCrChannel, _textureCbCr); + material.SetMatrix(PropertyBindings.DisplayTransform, displayTransform); + + return true; + } + + protected override void OnRelease() + { + _commandBuffer?.Dispose(); + + if (_textureY != null) + Object.Destroy(_textureY); + + if (_textureCbCr != null) + Object.Destroy(_textureCbCr); + } + } +} diff --git a/Assets/ARDK/Rendering/FrameRenderer/_ARKitFrameRenderer.cs.meta b/Assets/ARDK/Rendering/FrameRenderer/_ARKitFrameRenderer.cs.meta new file mode 100644 index 0000000..b829d89 --- /dev/null +++ b/Assets/ARDK/Rendering/FrameRenderer/_ARKitFrameRenderer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fc9f2abcaf3c04960bdce505803a9663 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Rendering/FrameRenderer/_ARPlaybackFrameRenderer.cs b/Assets/ARDK/Rendering/FrameRenderer/_ARPlaybackFrameRenderer.cs new file mode 100644 index 0000000..1a24193 --- /dev/null +++ b/Assets/ARDK/Rendering/FrameRenderer/_ARPlaybackFrameRenderer.cs @@ -0,0 +1,126 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using Niantic.ARDK.AR; + +using UnityEngine; +using UnityEngine.Rendering; + +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.Rendering +{ + internal sealed class _ARPlaybackFrameRenderer : + ARFrameRenderer + { + private CommandBuffer _commandBuffer; + private Texture2D _textureY; + private Texture2D _textureCbCr; + + protected override Shader Shader { get; } + + private Shader PlatformShader + { + get => + Application.platform == RuntimePlatform.Android + ? Resources.Load("ARCoreFrameBiplanar") + : Resources.Load("ARKitFrame"); + } + + public _ARPlaybackFrameRenderer(RenderTarget target) + : base(target) + { + Shader = PlatformShader; + } + + public _ARPlaybackFrameRenderer + ( + RenderTarget target, + float near, + float far, + Shader customShader = null + ) : base(target, near, far) + { + Shader = customShader ? customShader : PlatformShader; + } + + protected override GraphicsFence? OnConfigurePipeline + ( + RenderTarget target, + Resolution targetResolution, + Resolution sourceResolution, + Material renderMaterial + ) + { + _commandBuffer = new CommandBuffer + { + name = "PlaybackFrameRenderer" + }; + + _commandBuffer.Blit(null, target.Identifier, renderMaterial); + +#if UNITY_2019_1_OR_NEWER + return _commandBuffer.CreateAsyncGraphicsFence(); +#else + return _commandBuffer.CreateGPUFence(); +#endif + } + + protected override bool OnUpdateState + ( + IARFrame frame, + Matrix4x4 projectionTransform, + Matrix4x4 displayTransform, + Material material + ) + { + if (frame.CapturedImageBuffer == null) + return false; + + if (_textureY == null) + { + var resolution = frame.Camera.CPUImageResolution; + _textureY = new Texture2D(resolution.width, resolution.height, TextureFormat.R8, false); + _textureCbCr = + new Texture2D(resolution.width / 2, resolution.height / 2, TextureFormat.RG16, false); + } + + // Update source textures + _textureY.LoadRawTextureData(frame.CapturedImageBuffer.Planes[0].Data); + _textureCbCr.LoadRawTextureData(frame.CapturedImageBuffer.Planes[1].Data); + _textureY.Apply(); + _textureCbCr.Apply(); + + // Bind the texture and the display transform + material.SetTexture(PropertyBindings.YChannel, _textureY); + material.SetTexture(PropertyBindings.CbCrChannel, _textureCbCr); + material.SetMatrix(PropertyBindings.DisplayTransform, displayTransform); + + return true; + } + + protected override void OnAddToCamera(Camera camera) + { + ARSessionBuffersHelper.AddBackgroundBuffer(camera, _commandBuffer); + } + + protected override void OnRemoveFromCamera(Camera camera) + { + ARSessionBuffersHelper.RemoveBackgroundBuffer(camera, _commandBuffer); + } + + protected override void OnIssueCommands() + { + Graphics.ExecuteCommandBuffer(_commandBuffer); + } + + protected override void OnRelease() + { + if (_textureY != null) + Object.Destroy(_textureY); + + if (_textureCbCr != null) + Object.Destroy(_textureCbCr); + + _commandBuffer?.Dispose(); + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/Rendering/FrameRenderer/_ARPlaybackFrameRenderer.cs.meta b/Assets/ARDK/Rendering/FrameRenderer/_ARPlaybackFrameRenderer.cs.meta new file mode 100644 index 0000000..0808b4e --- /dev/null +++ b/Assets/ARDK/Rendering/FrameRenderer/_ARPlaybackFrameRenderer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f1d404607184741e89aca19cc4b77708 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Rendering/FrameRenderer/_MockFrameRenderer.cs b/Assets/ARDK/Rendering/FrameRenderer/_MockFrameRenderer.cs new file mode 100644 index 0000000..d4f9480 --- /dev/null +++ b/Assets/ARDK/Rendering/FrameRenderer/_MockFrameRenderer.cs @@ -0,0 +1,109 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using Niantic.ARDK.AR; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; +using UnityEngine.Rendering; + +namespace Niantic.ARDK.Rendering +{ + internal sealed class _MockFrameRenderer: + ARFrameRenderer + { + private CommandBuffer _commandBuffer; + private Texture2D _texture; + protected override Shader Shader { get; } + + public _MockFrameRenderer(RenderTarget target) + : base(target) + { + Shader = Resources.Load("EditorFrame"); + } + + public _MockFrameRenderer + ( + RenderTarget target, + float near, + float far, + Shader customShader = null + ) : base(target, near, far) + { + Shader = customShader ? customShader : Resources.Load("EditorFrame"); + ARLog._Debug("Loaded: " + (Shader != null ? Shader.name : null)); + } + + protected override GraphicsFence? OnConfigurePipeline + ( + RenderTarget target, + Resolution targetResolution, + Resolution sourceResolution, + Material renderMaterial + ) + { + _commandBuffer = new CommandBuffer + { + name = "MockFrameRenderer" + }; + + _commandBuffer.ClearRenderTarget(true, true, Color.clear); + _commandBuffer.Blit(null, target.Identifier, renderMaterial); + +#if UNITY_2019_1_OR_NEWER + return _commandBuffer.CreateAsyncGraphicsFence(); +#else + return _commandBuffer.CreateGPUFence(); +#endif + } + + protected override bool OnUpdateState + ( + IARFrame frame, + Matrix4x4 projectionTransform, + Matrix4x4 displayTransform, + Material material + ) + { + if (frame.CapturedImageBuffer == null) + return false; + + if (_texture == null) + { + var resolution = frame.Camera.CPUImageResolution; + _texture = new Texture2D(resolution.width, resolution.height, TextureFormat.BGRA32, false); + } + + // Update source textures + _texture.LoadRawTextureData(frame.CapturedImageBuffer.Planes[0].Data); + _texture.Apply(); + + // Bind the texture and the display transform + material.SetTexture(PropertyBindings.FullImage, _texture); + material.SetMatrix(PropertyBindings.DisplayTransform, displayTransform); + + return true; + } + + protected override void OnAddToCamera(Camera camera) + { + ARSessionBuffersHelper.AddBackgroundBuffer(camera, _commandBuffer); + } + + protected override void OnRemoveFromCamera(Camera camera) + { + ARSessionBuffersHelper.RemoveBackgroundBuffer(camera, _commandBuffer); + } + + protected override void OnIssueCommands() + { + Graphics.ExecuteCommandBuffer(_commandBuffer); + } + + protected override void OnRelease() + { + if (_texture != null) + Object.Destroy(_texture); + + _commandBuffer?.Dispose(); + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/Rendering/FrameRenderer/_MockFrameRenderer.cs.meta b/Assets/ARDK/Rendering/FrameRenderer/_MockFrameRenderer.cs.meta new file mode 100644 index 0000000..95e2853 --- /dev/null +++ b/Assets/ARDK/Rendering/FrameRenderer/_MockFrameRenderer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c4ac454287094e70837a9d07088b3ea8 +timeCreated: 1615309179 \ No newline at end of file diff --git a/Assets/ARDK/Rendering/FrameRenderer/_RemoteFrameRenderer.cs b/Assets/ARDK/Rendering/FrameRenderer/_RemoteFrameRenderer.cs new file mode 100644 index 0000000..fd119d4 --- /dev/null +++ b/Assets/ARDK/Rendering/FrameRenderer/_RemoteFrameRenderer.cs @@ -0,0 +1,116 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using Niantic.ARDK.AR; + +using UnityEngine; +using UnityEngine.Rendering; + +namespace Niantic.ARDK.Rendering +{ + internal sealed class _RemoteFrameRenderer: + ARFrameRenderer + { + private CommandBuffer _commandBuffer; + private Texture2D _textureY; + private Texture2D _textureCbCr; + + protected override Shader Shader { get; } + + public _RemoteFrameRenderer(RenderTarget target) + : base(target) + { + Shader = Resources.Load("ARKitFrame"); + } + + public _RemoteFrameRenderer + ( + RenderTarget target, + float near, + float far, + Shader customShader = null + ) : base(target, near, far) + { + Shader = customShader ? customShader : Resources.Load("ARKitFrame"); + } + + protected override GraphicsFence? OnConfigurePipeline + ( + RenderTarget target, + Resolution targetResolution, + Resolution sourceResolution, + Material renderMaterial + ) + { + _commandBuffer = new CommandBuffer + { + name = "RemoteFrameEditor" + }; + + _commandBuffer.Blit(null, target.Identifier, renderMaterial); + +#if UNITY_2019_1_OR_NEWER + return _commandBuffer.CreateAsyncGraphicsFence(); +#else + return _commandBuffer.CreateGPUFence(); +#endif + } + + protected override bool OnUpdateState + ( + IARFrame frame, + Matrix4x4 projectionTransform, + Matrix4x4 displayTransform, + Material material + ) + { + if (frame.CapturedImageBuffer == null) + return false; + + if (_textureY == null) + { + var resolution = frame.Camera.CPUImageResolution; + _textureY = new Texture2D(resolution.width, resolution.height, TextureFormat.R8, false); + _textureCbCr = + new Texture2D(resolution.width / 2, resolution.height / 2, TextureFormat.RG16, false); + } + + // Update source textures + _textureY.LoadRawTextureData(frame.CapturedImageBuffer.Planes[0].Data); + _textureCbCr.LoadRawTextureData(frame.CapturedImageBuffer.Planes[1].Data); + _textureY.Apply(); + _textureCbCr.Apply(); + + // Bind the texture and the display transform + material.SetTexture(PropertyBindings.YChannel, _textureY); + material.SetTexture(PropertyBindings.CbCrChannel, _textureCbCr); + material.SetMatrix(PropertyBindings.DisplayTransform, displayTransform); + + return true; + } + + protected override void OnAddToCamera(Camera camera) + { + ARSessionBuffersHelper.AddBackgroundBuffer(camera, _commandBuffer); + } + + protected override void OnRemoveFromCamera(Camera camera) + { + ARSessionBuffersHelper.RemoveBackgroundBuffer(camera, _commandBuffer); + } + + protected override void OnIssueCommands() + { + Graphics.ExecuteCommandBuffer(_commandBuffer); + } + + protected override void OnRelease() + { + if (_textureY != null) + Object.Destroy(_textureY); + + if (_textureCbCr != null) + Object.Destroy(_textureCbCr); + + _commandBuffer?.Dispose(); + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/Rendering/FrameRenderer/_RemoteFrameRenderer.cs.meta b/Assets/ARDK/Rendering/FrameRenderer/_RemoteFrameRenderer.cs.meta new file mode 100644 index 0000000..f0f9cb6 --- /dev/null +++ b/Assets/ARDK/Rendering/FrameRenderer/_RemoteFrameRenderer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a03ea03a7020464c8bb3d9a9a1cc4e2d +timeCreated: 1617288886 \ No newline at end of file diff --git a/Assets/ARDK/Rendering/PropertyBindings.cs b/Assets/ARDK/Rendering/PropertyBindings.cs new file mode 100644 index 0000000..a1493c5 --- /dev/null +++ b/Assets/ARDK/Rendering/PropertyBindings.cs @@ -0,0 +1,53 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using UnityEngine; + +namespace Niantic.ARDK.Rendering +{ + public static class PropertyBindings + { + /// Texture property for the full AR image + public static readonly int FullImage = Shader.PropertyToID("_texture"); + + /// Texture property for the luma component of the AR image + public static readonly int YChannel = Shader.PropertyToID("_textureY"); + + /// Texture property for the chroma components of the AR image + public static readonly int CbCrChannel = Shader.PropertyToID("_textureCbCr"); + + /// Texture property for the depth network output + public static readonly int DepthChannel = Shader.PropertyToID("_textureDepth"); + + /// Texture property for the depth suppression mask + public static readonly int DepthSuppressionMask = Shader.PropertyToID("_textureDepthSuppressionMask"); + + /// Affine transform to fit the AR image on the viewport + public static readonly int DisplayTransform = Shader.PropertyToID("_displayTransform"); + + /// Affine transform to fit the depth channel on the viewport + public static readonly int DepthTransform = Shader.PropertyToID("_depthTransform"); + + /// Affine transform to fit the semantic channels on the viewport + public static readonly int SemanticsTransform = Shader.PropertyToID("_semanticsTransform"); + + /// The minimum value of the depth interval used for scaling + public static readonly int DepthScaleMin = Shader.PropertyToID("_depthScaleMin"); + + /// The maximum value of the depth interval used for scaling + public static readonly int DepthScaleMax = Shader.PropertyToID("_depthScaleMax"); + + /// Color mask to visualize components of the screen space occluder mesh (if used) + public static readonly int DebugColorMask = Shader.PropertyToID("_colorMask"); + } + + public static class FeatureBindings + { + /// Refers to the render feature of writing depth directly to the z-buffer + public const string DepthZWrite = "DEPTH_ZWRITE"; + + /// Refers to the render feature of writing depth data to the screen backbuffer + public const string DepthDebug = "DEPTH_DEBUG"; + + /// When enabled, parts of the depth texture defined by a semantic mask get discarded + public const string DepthSuppression = "DEPTH_SUPPRESSION"; + } +} diff --git a/Assets/ARDK/Rendering/PropertyBindings.cs.meta b/Assets/ARDK/Rendering/PropertyBindings.cs.meta new file mode 100644 index 0000000..4c18ac0 --- /dev/null +++ b/Assets/ARDK/Rendering/PropertyBindings.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1840812cff47490188cd348cd39006de +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Rendering/RenderFeatureProvider.meta b/Assets/ARDK/Rendering/RenderFeatureProvider.meta new file mode 100644 index 0000000..5a558d8 --- /dev/null +++ b/Assets/ARDK/Rendering/RenderFeatureProvider.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b4537d70eb6b47a6888697ef4af6aa49 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Rendering/RenderFeatureProvider/ARRenderFeatureProvider.cs b/Assets/ARDK/Rendering/RenderFeatureProvider/ARRenderFeatureProvider.cs new file mode 100644 index 0000000..c214793 --- /dev/null +++ b/Assets/ARDK/Rendering/RenderFeatureProvider/ARRenderFeatureProvider.cs @@ -0,0 +1,131 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System.Collections.Generic; + +using Niantic.ARDK.Extensions; +using Niantic.ARDK.Utilities; + +using UnityEngine; + +namespace Niantic.ARDK.Rendering +{ + /// Base class for render state providers. + /// Render state provider components maintain a two sets: + /// - A list of all possible render features they may be enabled + /// - A list of the render features that are actually need to be enabled + /// A render feature is just a shader keyword that triggers the compilation + /// of additional code to the shader that renders the background. + public abstract class ARRenderFeatureProvider : + ARConfigChanger, + IRenderFeatureProvider + { + private event ArdkEventHandler _activeFeaturesChanged; + + /// Invoked when the provider reconfigures its active features. + public event ArdkEventHandler ActiveFeaturesChanged + { + add + { + _activeFeaturesChanged += value; + if (AreFeaturesEnabled) + value.Invoke(new RenderFeaturesChangedArgs(OnEvaluateConfiguration())); + } + + remove => _activeFeaturesChanged -= value; + } + + private HashSet _features; + + /// A set of all render features this provider may enable or disable. + public ISet Features + { + get => _features ??= OnAcquireFeatureSet(); + } + + private RenderTarget? _renderTarget; + + /// The active render target of this provider + public RenderTarget? Target + { + get => _renderTarget; + set + { + if (!value.HasValue) + { + if (_renderTarget.HasValue) + { + // Reset target + _renderTarget = null; + OnRenderTargetChanged(null); + } + + return; + } + + // Make sure the new target is different + if (_renderTarget.HasValue && _renderTarget.Value.Equals(value.Value)) + return; + + _renderTarget = value; + OnRenderTargetChanged(value); + } + } + + // When the component gets enabled, the set of enabled render features are re-evaluated + // This is because the developer might change the state of the component while it is disabled + protected override void EnableFeaturesImpl() + { + base.EnableFeaturesImpl(); + + // Propagate AR session config changes + RaiseConfigurationChanged(); + + // Propagate active render features + _activeFeaturesChanged?.Invoke(new RenderFeaturesChangedArgs(OnEvaluateConfiguration())); + } + + // When the component gets disabled, every render feature managed by this + // state provider gets deactivated. E.g. Disabling the provider of depth + // will result in a shader that doesn't handle occlusions. + protected override void DisableFeaturesImpl() + { + base.DisableFeaturesImpl(); + + // Propagate AR session config changes + RaiseConfigurationChanged(); + + // Disable all render features + _activeFeaturesChanged?.Invoke + ( + new RenderFeaturesChangedArgs(new RenderFeatureConfiguration(null, Features)) + ); + } + + // Manually triggers the re-evaluation of active render features. + // This should be called from children, when there is an explicit + // request to enable or disable a specific render feature. + protected void InvalidateActiveFeatures() + { + // Propagate active render features + _activeFeaturesChanged?.Invoke(new RenderFeaturesChangedArgs(OnEvaluateConfiguration())); + } + + /// Invoked when this component is asked about the render features + /// it is may be responsible for. + /// @note: The implementation needs to include all features that is + /// possible to manipulate with this component. + protected abstract HashSet OnAcquireFeatureSet(); + + /// Invoked when it is time to calculate the actual features + /// that this component currently manages. + protected abstract RenderFeatureConfiguration OnEvaluateConfiguration(); + + /// Invoked when the active render target has changed for this feature provider + /// @param target The new render target. If this is null, the provider should + /// set its target to the default option. + protected abstract void OnRenderTargetChanged(RenderTarget? target); + + /// Called when it is time to copy the current render state to the main rendering material. + /// @param material Material used to render the frame. + public abstract void UpdateRenderState(Material material); + } +} diff --git a/Assets/ARDK/Rendering/RenderFeatureProvider/ARRenderFeatureProvider.cs.meta b/Assets/ARDK/Rendering/RenderFeatureProvider/ARRenderFeatureProvider.cs.meta new file mode 100644 index 0000000..91dda4f --- /dev/null +++ b/Assets/ARDK/Rendering/RenderFeatureProvider/ARRenderFeatureProvider.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9fbbf5f17645644078ca9570a8a9b643 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Rendering/RenderFeatureProvider/IRenderFeatureProvider.cs b/Assets/ARDK/Rendering/RenderFeatureProvider/IRenderFeatureProvider.cs new file mode 100644 index 0000000..2a2da1b --- /dev/null +++ b/Assets/ARDK/Rendering/RenderFeatureProvider/IRenderFeatureProvider.cs @@ -0,0 +1,53 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System.Collections.Generic; + +using Niantic.ARDK.Utilities; + +using UnityEngine; + +namespace Niantic.ARDK.Rendering +{ + /// A component that supplies the renderer with additional information to render an ARFrame. + public interface IRenderFeatureProvider + { + /// Invoked when the provider reconfigured its active features. + event ArdkEventHandler ActiveFeaturesChanged; + + /// A set of all render features this provider may enable or disable. + ISet Features { get; } + + /// The active render target of this provider + RenderTarget? Target { get; set; } + + /// Updates the provided material with additional information + /// this component is responsible of providing. + void UpdateRenderState(Material material); + } + + /// Stores which render features should be enabled or disabled. + public readonly struct RenderFeatureConfiguration + { + public readonly IEnumerable FeaturesEnabled; + public readonly IEnumerable FeaturesDisabled; + + public RenderFeatureConfiguration + ( + IEnumerable featuresEnabled, + IEnumerable featuresDisabled + ) + { + FeaturesEnabled = featuresEnabled; + FeaturesDisabled = featuresDisabled; + } + } + + /// Event args for when the provider reconfigured its active features. + public class RenderFeaturesChangedArgs: IArdkEventArgs + { + public readonly RenderFeatureConfiguration Configuration; + public RenderFeaturesChangedArgs(RenderFeatureConfiguration configuration) + { + Configuration = configuration; + } + } +} diff --git a/Assets/ARDK/Rendering/RenderFeatureProvider/IRenderFeatureProvider.cs.meta b/Assets/ARDK/Rendering/RenderFeatureProvider/IRenderFeatureProvider.cs.meta new file mode 100644 index 0000000..3509175 --- /dev/null +++ b/Assets/ARDK/Rendering/RenderFeatureProvider/IRenderFeatureProvider.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 004b2ba7b1d942b3abd4b7558a6e3c99 +timeCreated: 1616082715 \ No newline at end of file diff --git a/Assets/ARDK/Rendering/RenderTarget.cs b/Assets/ARDK/Rendering/RenderTarget.cs new file mode 100644 index 0000000..8d81052 --- /dev/null +++ b/Assets/ARDK/Rendering/RenderTarget.cs @@ -0,0 +1,132 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; + +using UnityEngine; +using UnityEngine.Rendering; + +namespace Niantic.ARDK.Rendering +{ + /// A render target can either be a camera or an offscreen texture. + public readonly struct RenderTarget: + IEquatable + { + /// The actual camera as a render target, if any. + public readonly Camera Camera; + + /// The actual GPU texture as a render target, if any. + public readonly RenderTexture RenderTexture; + + /// The identifier of this render target. + public readonly RenderTargetIdentifier Identifier; + + // Whether the target is a Unity camera + public readonly bool IsTargetingCamera; + + // Whether the target is a RenderTexture + public readonly bool IsTargetingTexture; + + /// Creates a render target from the specified camera. + public RenderTarget(Camera cam) + { + Camera = cam; + IsTargetingCamera = true; + + RenderTexture = null; + IsTargetingTexture = false; + + Identifier = Camera.targetTexture == null + ? BuiltinRenderTextureType.CurrentActive // TODO: what if this is a secondary camera? + : BuiltinRenderTextureType.CameraTarget; + } + + /// Creates a render target from the specified texture. + public RenderTarget(RenderTexture texture) + { + Camera = null; + IsTargetingCamera = false; + + RenderTexture = texture; + IsTargetingTexture = true; + + Identifier = new RenderTargetIdentifier(texture); + } + + /// Returns a the resolution of the target, in the function of + /// the specified screen orientation. + public Resolution GetResolution(ScreenOrientation forOrientation) + { + int longer, shorter; + + if (IsTargetingCamera) + { + longer = Camera.pixelWidth > Camera.pixelHeight + ? Camera.pixelWidth + : Camera.pixelHeight; + + shorter = Camera.pixelWidth < Camera.pixelHeight + ? Camera.pixelWidth + : Camera.pixelHeight; + } + else + { + longer = RenderTexture.width > RenderTexture.height + ? RenderTexture.width + : RenderTexture.height; + + shorter = RenderTexture.width < RenderTexture.height + ? RenderTexture.width + : RenderTexture.height; + } + + var needsLandscape = forOrientation == ScreenOrientation.LandscapeLeft || + forOrientation == ScreenOrientation.LandscapeRight; + + return needsLandscape + // Landscape + ? new Resolution { width = longer, height = shorter } + // Portrait + : new Resolution { width = shorter, height = longer }; + } + + public static implicit operator RenderTarget(Camera cam) + { + return new RenderTarget(cam); + } + + public static implicit operator RenderTarget(RenderTexture texture) + { + return new RenderTarget(texture); + } + + public bool Equals(RenderTarget other) + { + return Identifier.Equals(other.Identifier); + } + + public override bool Equals(object obj) + { + return obj is RenderTarget other && Equals(other); + } + + public override int GetHashCode() + { + return Identifier.GetHashCode(); + } + + /// Returns the current screen orientation. When called in the editor, + /// this property infers the orientation from the screen resolution. + public static ScreenOrientation ScreenOrientation + { + get + { +#if UNITY_EDITOR + return Screen.width > Screen.height + ? UnityEngine.ScreenOrientation.LandscapeLeft + : UnityEngine.ScreenOrientation.Portrait; +#else + return Screen.orientation; +#endif + } + } + } +} diff --git a/Assets/ARDK/Rendering/RenderTarget.cs.meta b/Assets/ARDK/Rendering/RenderTarget.cs.meta new file mode 100644 index 0000000..e041a2f --- /dev/null +++ b/Assets/ARDK/Rendering/RenderTarget.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a0f5dd4b2501e4aea80272e537799f05 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Rendering/ResolutionMode.cs b/Assets/ARDK/Rendering/ResolutionMode.cs new file mode 100644 index 0000000..cdce0af --- /dev/null +++ b/Assets/ARDK/Rendering/ResolutionMode.cs @@ -0,0 +1,22 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +namespace Niantic.ARDK.Rendering +{ + /// Possible ways to determine camera feed resolution. + public enum ResolutionMode + { + /// Behaviour is same as `Screen`, below. + Default = 0, + + /// Use a custom resolution size, but automatically handle screen rotation. + Custom, + + /// Match resolution of the CPU image surfaced by ARKit or ARCore. + FromHardware, + + /// Match screen resolution. + Screen, + + /// Use a custom resolution size and do not automatically handle screen rotation. + Fixed + } +} diff --git a/Assets/ARDK/Rendering/ResolutionMode.cs.meta b/Assets/ARDK/Rendering/ResolutionMode.cs.meta new file mode 100644 index 0000000..44ae1f1 --- /dev/null +++ b/Assets/ARDK/Rendering/ResolutionMode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 336b1849b6e0640ebb830b94d7011abb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Rendering/Resources.meta b/Assets/ARDK/Rendering/Resources.meta new file mode 100644 index 0000000..a170a58 --- /dev/null +++ b/Assets/ARDK/Rendering/Resources.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2b469e805e70647da8baae201c6f4d81 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Rendering/Resources/ARCoreFrame.shader b/Assets/ARDK/Rendering/Resources/ARCoreFrame.shader new file mode 100644 index 0000000..28a6e67 --- /dev/null +++ b/Assets/ARDK/Rendering/Resources/ARCoreFrame.shader @@ -0,0 +1,164 @@ +Shader "Unlit/ARCoreFrame" +{ + Properties + { + _textureDepthSuppressionMask ("Depth Suppresion Mask", 2D) = "black" {} + _textureDepth ("Depth", 2D) = "black" {} + _texture ("Texture", 2D) = "black" {} + } + SubShader + { + Tags + { + "Queue" = "Background" + "RenderType" = "Background" + "ForceNoShadowCasting" = "True" + } + + Pass + { + Cull Off + ZWrite On + ZTest Always + Lighting Off + LOD 100 + Tags + { + "LightMode" = "Always" + } + + GLSLPROGRAM + + #pragma multi_compile_local __ DEPTH_ZWRITE + #pragma multi_compile_local __ DEPTH_SUPPRESSION + #pragma multi_compile_local __ DEPTH_DEBUG + + #pragma only_renderers gles3 + + #include "UnityCG.glslinc" + + // #ifdef SHADER_API_GLES3 + // #extension GL_OES_EGL_image_external_essl3 : require + // #endif + +#ifdef VERTEX + + // Transform used to sample the color planes + uniform mat4 _displayTransform; + + // Transform used to sample the context awareness textures + uniform mat4 _depthTransform; + uniform mat4 _semanticsTransform; + + // Transformed UVs + varying vec2 _colorUV; + varying vec3 _depthUV; + varying vec3 _semanticsUV; + + void main() + { + #ifdef SHADER_API_GLES3 + + // Transform UVs for the color texture + vec4 texCoord = vec4(gl_MultiTexCoord0.x, gl_MultiTexCoord0.y, 0.0f, 1.0f); + _colorUV = (_displayTransform * texCoord).xy; + + #ifdef DEPTH_ZWRITE + + // Transform UVs for the context awareness textures + vec4 uv = vec4(gl_MultiTexCoord0.x, gl_MultiTexCoord0.y, 1.0f, 1.0f); + _depthUV = (_depthTransform * uv).xyz; + + #ifdef DEPTH_SUPPRESSION + _semanticsUV = (_semanticsTransform * uv).xyz; + #endif + + #endif + + // Transform vertex position + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; + + #endif + } +#endif + +#ifdef FRAGMENT + + // Transformed texture coordinates + varying vec2 _colorUV; + varying vec3 _depthUV; + varying vec3 _semanticsUV; + + // Depth range used for scaling + uniform float _depthScaleMin; + uniform float _depthScaleMax; + + uniform sampler2D _textureDepth; + uniform sampler2D _textureDepthSuppressionMask; + + // Currently, we render camera images using a cached version of the native texture. + // We don't require an OES sampler for the cached texture. + // uniform samplerExternalOES _texture; + uniform sampler2D _texture; + +#if defined(SHADER_API_GLES3) && defined(DEPTH_ZWRITE) + + uniform vec4 _ZBufferParams; + + // Inverse of LinearEyeDepth + float EyeDepthToNonLinear(float eyeDepth) + { + return (1.0f - (eyeDepth * _ZBufferParams.w)) / (eyeDepth * _ZBufferParams.z); + } +#endif + void main() + { +#ifdef SHADER_API_GLES3 + + // Sample color + vec4 color = texture(_texture, _colorUV); + + // Reset depth + float depth = 1.0f; + + #ifdef DEPTH_ZWRITE + #ifdef DEPTH_SUPPRESSION + // If depth is not suppressed at this pixel + vec2 semanticsUV = vec2(_semanticsUV.x / _semanticsUV.z, _semanticsUV.y / _semanticsUV.z); + if (texture(_textureDepthSuppressionMask, semanticsUV).x == 0.0f) + #endif + { + // Sample depth + vec2 depthUV = vec2(_depthUV.x / _depthUV.z, _depthUV.y / _depthUV.z); + float rawDepth = texture(_textureDepth, depthUV).x; + + // Scale depth in case it is normalized + // Note: If depth is not normalized, min and max should + // be 0 and 1 respectively to leave the value intact + float scaledDepth = rawDepth * (_depthScaleMax - _depthScaleMin) + _depthScaleMin; + + // Convert depth to z-value and write the zbuffer + depth = EyeDepthToNonLinear(scaledDepth); + + #ifdef DEPTH_DEBUG + // Write disparity to the color channels for debug purposes + float MAX_VIEW_DISP = 4.0f; + float scaledDisparity = 1.0f/scaledDepth; + float normDisparity = scaledDisparity/MAX_VIEW_DISP; + color = vec4(normDisparity, normDisparity, normDisparity, 1.0f); + #endif + } + #endif + gl_FragColor = color; + gl_FragDepth = depth; +#endif + } + +#endif + + ENDGLSL + } + } + + Fallback "Unlit/ARCoreFrameLegacy" +} diff --git a/Assets/ARDK/Rendering/Resources/ARCoreFrame.shader.meta b/Assets/ARDK/Rendering/Resources/ARCoreFrame.shader.meta new file mode 100644 index 0000000..284dbf3 --- /dev/null +++ b/Assets/ARDK/Rendering/Resources/ARCoreFrame.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 067b2d60881b548b7a5ebf7ecb304db9 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Rendering/Resources/ARCoreFrameBiplanar.shader b/Assets/ARDK/Rendering/Resources/ARCoreFrameBiplanar.shader new file mode 100644 index 0000000..7dd65a1 --- /dev/null +++ b/Assets/ARDK/Rendering/Resources/ARCoreFrameBiplanar.shader @@ -0,0 +1,167 @@ +Shader "Unlit/ARCoreFrameBiplanar" +{ + Properties + { + _textureDepthSuppressionMask ("Depth Suppresion Mask", 2D) = "black" {} + _textureDepth ("Depth", 2D) = "black" {} + _textureY ("TextureY", 2D) = "black" {} + _textureCbCr ("TextureCbCr", 2D) = "gray" {} + } + SubShader + { + Tags + { + "Queue" = "Background" + "RenderType" = "Background" + "ForceNoShadowCasting" = "True" + } + + Pass + { + Cull Off + ZWrite On + ZTest Always + Lighting Off + LOD 100 + Tags + { + "LightMode" = "Always" + } + + GLSLPROGRAM + + #pragma multi_compile_local __ DEPTH_ZWRITE + #pragma multi_compile_local __ DEPTH_SUPPRESSION + #pragma multi_compile_local __ DEPTH_DEBUG + + #pragma only_renderers gles3 + + #include "UnityCG.glslinc" + +#ifdef VERTEX + + // Transform used to sample the color planes + uniform mat4 _displayTransform; + + // Transform used to sample the context awareness textures + uniform mat4 _depthTransform; + uniform mat4 _semanticsTransform; + + // Transformed UVs + varying vec2 _colorUV; + varying vec3 _depthUV; + varying vec3 _semanticsUV; + + void main() + { + #ifdef SHADER_API_GLES3 + + // Transform UVs for the color texture + vec4 texCoord = vec4(gl_MultiTexCoord0.x, gl_MultiTexCoord0.y, 0.0f, 1.0f); + _colorUV = (_displayTransform * texCoord).xy; + + #ifdef DEPTH_ZWRITE + + // Transform UVs for the context awareness textures + vec4 uv = vec4(gl_MultiTexCoord0.x, gl_MultiTexCoord0.y, 1.0f, 1.0f); + _depthUV = (_depthTransform * uv).xyz; + + #ifdef DEPTH_SUPPRESSION + _semanticsUV = (_semanticsTransform * uv).xyz; + #endif + + #endif + + // Transform vertex position + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; + + #endif + } +#endif + +#ifdef FRAGMENT + + // Transformation used to convert yCbCr color format to RGB + const mat4 colorTransform = mat4( + vec4(1.0, 1.0, 1.0, 0.0), + vec4(0.0, -0.3441, 1.772, 0.0), + vec4(1.402, -0.7141, 0.0, 0.0), + vec4(-0.701, 0.5291, -0.886, 1.0) + ); + + // Transformed texture coordinates + varying vec2 _colorUV; + varying vec3 _depthUV; + varying vec3 _semanticsUV; + + // Depth range used for scaling + uniform float _depthScaleMin; + uniform float _depthScaleMax; + + uniform sampler2D _textureDepth; + uniform sampler2D _textureDepthSuppressionMask; + uniform sampler2D _textureY; + uniform sampler2D _textureCbCr; + +#if defined(SHADER_API_GLES3) && defined(DEPTH_ZWRITE) + + uniform vec4 _ZBufferParams; + + // Inverse of LinearEyeDepth + float EyeDepthToNonLinear(float eyeDepth) + { + return (1.0f - (eyeDepth * _ZBufferParams.w)) / (eyeDepth * _ZBufferParams.z); + } +#endif + void main() + { +#ifdef SHADER_API_GLES3 + + // Convert the biplanar image to RGB + vec4 color = colorTransform * + vec4(texture(_textureY, _colorUV).x, texture(_textureCbCr, _colorUV).xy, 1.0f); + + // Reset depth + float depth = 1.0f; + + #ifdef DEPTH_ZWRITE + #ifdef DEPTH_SUPPRESSION + // If depth is not suppressed at this pixel + vec2 semanticsUV = vec2(_semanticsUV.x / _semanticsUV.z, _semanticsUV.y / _semanticsUV.z); + if (texture(_textureDepthSuppressionMask, semanticsUV).x == 0.0f) + #endif + { + // Sample depth + vec2 depthUV = vec2(_depthUV.x / _depthUV.z, _depthUV.y / _depthUV.z); + float rawDepth = texture(_textureDepth, depthUV).x; + + // Scale depth in case it is normalized + // Note: If depth is not normalized, min and max should + // be 0 and 1 respectively to leave the value intact + float scaledDepth = rawDepth * (_depthScaleMax - _depthScaleMin) + _depthScaleMin; + + // Convert depth to z-value and write the zbuffer + depth = EyeDepthToNonLinear(scaledDepth); + + #ifdef DEPTH_DEBUG + // Write disparity to the color channels for debug purposes + float MAX_VIEW_DISP = 4.0f; + float scaledDisparity = 1.0f/scaledDepth; + float normDisparity = scaledDisparity/MAX_VIEW_DISP; + color = vec4(normDisparity, normDisparity, normDisparity, 1.0f); + #endif + } + #endif + gl_FragColor = color; + gl_FragDepth = depth; +#endif + } + +#endif + + ENDGLSL + } + } + + Fallback Off +} diff --git a/Assets/ARDK/Rendering/Resources/ARCoreFrameBiplanar.shader.meta b/Assets/ARDK/Rendering/Resources/ARCoreFrameBiplanar.shader.meta new file mode 100644 index 0000000..d80dea8 --- /dev/null +++ b/Assets/ARDK/Rendering/Resources/ARCoreFrameBiplanar.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: e6fb30071528d4f0c9be3f49a7ec833d +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Rendering/Resources/ARCoreFrameLegacy.shader b/Assets/ARDK/Rendering/Resources/ARCoreFrameLegacy.shader new file mode 100644 index 0000000..491f200 --- /dev/null +++ b/Assets/ARDK/Rendering/Resources/ARCoreFrameLegacy.shader @@ -0,0 +1,61 @@ +Shader "Unlit/ARCoreFrameLegacy" +{ + Properties + { + _texture ("Texture", 2D) = "black" {} + } + + // For legacy GLES, no depth + SubShader +{ + Tags { "RenderType"="Opaque" } + Pass + { + Cull Off + ZWrite Off + + GLSLPROGRAM + + #pragma exclude_renderers gles3 + + // #extension GL_OES_EGL_image_external : enable + + #ifdef VERTEX + + uniform mat4 _displayTransform; + varying vec2 _colorUV; + + void main() + { + #if defined(SHADER_API_GLES) + vec4 texCoord = vec4(gl_MultiTexCoord0.x, gl_MultiTexCoord0.y, 0.0f, 1.0f); + _colorUV = (_displayTransform * texCoord).xy; + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; + #endif + } + + #endif + + #ifdef FRAGMENT + + varying vec2 _colorUV; + + // Currently, we render camera images using a cached version of the native texture. + // We don't require an OES sampler for the cached texture. + // uniform samplerExternalOES _texture; + uniform sampler2D _texture; + + void main() + { + #if defined(SHADER_API_GLES) + gl_FragColor = texture(_texture, _colorUV); + #endif + } + + #endif + + ENDGLSL + } +} + FallBack Off +} diff --git a/Assets/ARDK/Rendering/Resources/ARCoreFrameLegacy.shader.meta b/Assets/ARDK/Rendering/Resources/ARCoreFrameLegacy.shader.meta new file mode 100644 index 0000000..70c911d --- /dev/null +++ b/Assets/ARDK/Rendering/Resources/ARCoreFrameLegacy.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: f23cb1baa88c34e20addcadeb499a51b +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Rendering/Resources/ARKitFrame.shader b/Assets/ARDK/Rendering/Resources/ARKitFrame.shader new file mode 100644 index 0000000..3bf2d7e --- /dev/null +++ b/Assets/ARDK/Rendering/Resources/ARKitFrame.shader @@ -0,0 +1,154 @@ +Shader "Unlit/ARKitFrame" +{ + Properties + { + _textureY ("TextureY", 2D) = "black" {} + _textureCbCr ("TextureCbCr", 2D) = "gray" {} + _textureDepth ("Depth", 2D) = "white" {} + _textureDepthSuppressionMask ("Depth Suppresion Mask", 2D) = "black" {} + } + SubShader + { + Tags + { + "Queue" = "Background" + "RenderType" = "Background" + "ForceNoShadowCasting" = "True" + } + + Pass + { + Cull Off + ZTest Always + ZWrite On + Lighting Off + LOD 100 + Tags + { + "LightMode" = "Always" + } + + HLSLPROGRAM + + #pragma vertex vert + #pragma fragment frag + + #pragma multi_compile_local __ DEPTH_ZWRITE + #pragma multi_compile_local __ DEPTH_SUPPRESSION + #pragma multi_compile_local __ DEPTH_DEBUG + + #include "UnityCG.cginc" + + // Transformation used to convert yCbCr color format to RGB + static const float4x4 colorTransform = float4x4( + float4(1.0, +0.0000, +1.4020, -0.7010), + float4(1.0, -0.3441, -0.7141, +0.5291), + float4(1.0, +1.7720, +0.0000, -0.8860), + float4(0.0, +0.0000, +0.0000, +1.0000) + ); + + // Transform used to sample the color planes + float4x4 _displayTransform; + + // Transforms used to sample the context awareness textures + float4x4 _depthTransform; + float4x4 _semanticsTransform; + + // Depth range used for scaling + float _depthScaleMin; + float _depthScaleMax; + + // Plane samplers + sampler2D _textureY; + sampler2D _textureCbCr; + sampler2D _textureDepth; + sampler2D _textureDepthSuppressionMask; + + struct appdata + { + float4 vertex : POSITION; + float2 uv : TEXCOORD0; + }; + + struct v2f + { + float4 vertex : SV_POSITION; + float2 color_uv : TEXCOORD0; +#if DEPTH_ZWRITE + float3 depth_uv : TEXCOORD1; +#if DEPTH_SUPPRESSION + float3 semantics_uv : TEXCOORD2; +#endif +#endif + }; + +#if DEPTH_ZWRITE + + // Inverse of LinearEyeDepth + inline float EyeDepthToNonLinear(float eyeDepth, float4 zBufferParam) + { + return (1.0f - (eyeDepth * zBufferParam.w)) / (eyeDepth * zBufferParam.z * 2.0f); + } + +#endif + + v2f vert (appdata v) + { + v2f o; + o.vertex = UnityObjectToClipPos(v.vertex); + + // Apply display transform + o.color_uv = mul(_displayTransform, float4(v.uv, 0.0f, 1.0f)).xy; + + // Transform UVs for the context awareness textures +#if DEPTH_ZWRITE + o.depth_uv = mul(_depthTransform, float4(v.uv, 1.0f, 1.0f)).xyz; +#if DEPTH_SUPPRESSION + o.semantics_uv = mul(_semanticsTransform, float4(v.uv, 1.0f, 1.0f)).xyz; +#endif +#endif + + return o; + } + + void frag(in v2f i, out float4 out_color : SV_Target, out float out_depth : SV_Depth) + { + // Convert the biplanar image to RGB + out_color = mul(colorTransform, + float4(tex2D(_textureY, i.color_uv).r, tex2D(_textureCbCr, i.color_uv).rg, 1.0f)); + + // Clear depth + out_depth = 0.0f; + +#if DEPTH_ZWRITE +#if DEPTH_SUPPRESSION + // If depth is not suppressed at this pixel + float2 semanticsUV = float2(i.semantics_uv.x / i.semantics_uv.z, i.semantics_uv.y / i.semantics_uv.z); + if (tex2D(_textureDepthSuppressionMask, semanticsUV).r == 0.0f) +#endif + { + // Sample depth + float2 depthUV = float2(i.depth_uv.x / i.depth_uv.z, i.depth_uv.y / i.depth_uv.z); + float rawDepth = tex2D(_textureDepth, depthUV).r; + + // Scale depth in case it is normalized + // Note: If depth is not normalized, min and max should + // be 0 and 1 respectively to leave the value intact + float scaledDepth = rawDepth * (_depthScaleMax - _depthScaleMin) + _depthScaleMin; + + // Convert to nonlinear and write to the zbuffer + out_depth = EyeDepthToNonLinear(scaledDepth, _ZBufferParams); +#if DEPTH_DEBUG + // Write disparity to the color channels for debug purposes + const float MAX_VIEW_DISP = 4.0f; + const float scaledDisparity = 1.0f/scaledDepth; + const float normDisparity = scaledDisparity/MAX_VIEW_DISP; + out_color = float4(normDisparity, normDisparity, normDisparity, 1.0f); +#endif + } +#endif + } + ENDHLSL + } + } +} diff --git a/Assets/ARDK/Rendering/Resources/ARKitFrame.shader.meta b/Assets/ARDK/Rendering/Resources/ARKitFrame.shader.meta new file mode 100644 index 0000000..f456ba2 --- /dev/null +++ b/Assets/ARDK/Rendering/Resources/ARKitFrame.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: a670a8e1a0b134935940c3e489d44a55 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Rendering/Resources/BGRANonOESShader.shader b/Assets/ARDK/Rendering/Resources/BGRANonOESShader.shader new file mode 100644 index 0000000..073426b --- /dev/null +++ b/Assets/ARDK/Rendering/Resources/BGRANonOESShader.shader @@ -0,0 +1,112 @@ +Shader "Unlit/ARDKCameraShaderBGRANonOES" +{ + Properties + { + _texture ("Texture", 2D) = "black" {} + } + +// For GLES3 or GLES2 +SubShader +{ + Cull Off + Tags { "RenderType"="Opaque" } + Pass + { + ZWrite Off + + GLSLPROGRAM + + #pragma only_renderers gles3 gles + + #ifdef SHADER_API_GLES3 + #extension GL_OES_EGL_image_external_essl3 : enable + #else + #extension GL_OES_EGL_image_external : enable + #endif + + uniform mat4 _textureTransform; + + #ifdef VERTEX + + varying vec2 textureCoord; + + void main() + { + #if defined(SHADER_API_GLES3) || defined(SHADER_API_GLES) + textureCoord = (_textureTransform * vec4(gl_MultiTexCoord0.x, gl_MultiTexCoord0.y, 0.0f, 1.0f)).xy; + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; + #endif + } + + #endif + + #ifdef FRAGMENT + varying vec2 textureCoord; + uniform sampler2D _texture; + + void main() + { + #ifdef SHADER_API_GLES3 + gl_FragColor = texture(_texture, textureCoord); + #else + gl_FragColor = textureExternal(_texture, textureCoord); + #endif + } + + #endif + + ENDGLSL + } +} + + SubShader + { + Cull Off + Tags { "RenderType"="Opaque" } + LOD 100 + + Pass + { + ZWrite Off + CGPROGRAM + #pragma exclude_renderers gles3 + #pragma vertex vert + #pragma fragment frag + + #include "UnityCG.cginc" + + float4x4 _textureTransform; + + struct Vertex { + float4 position : POSITION; + float2 texcoord : TEXCOORD0; + }; + + struct TexCoordInOut { + float4 position : SV_POSITION; + float2 texcoord : TEXCOORD0; + }; + + TexCoordInOut vert (Vertex vertex) { + TexCoordInOut o; + o.position = UnityObjectToClipPos(vertex.position); + o.texcoord = mul(_textureTransform, float4(vertex.texcoord, 0.0f, 1.0f)).xy; + return o; + } + + // samplers + sampler2D _texture; + + fixed4 frag (TexCoordInOut i) : SV_Target { + // sample the texture + float2 texcoord = i.texcoord; + return tex2D(_texture, texcoord); + } + ENDCG + } + } + + + + FallBack Off +} diff --git a/Assets/ARDK/Rendering/Resources/BGRANonOESShader.shader.meta b/Assets/ARDK/Rendering/Resources/BGRANonOESShader.shader.meta new file mode 100644 index 0000000..5e60ca0 --- /dev/null +++ b/Assets/ARDK/Rendering/Resources/BGRANonOESShader.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: ff150d4088f314ba18bb727bc7282505 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Rendering/Resources/BGRAShader.shader b/Assets/ARDK/Rendering/Resources/BGRAShader.shader new file mode 100644 index 0000000..2f26de1 --- /dev/null +++ b/Assets/ARDK/Rendering/Resources/BGRAShader.shader @@ -0,0 +1,113 @@ +Shader "Unlit/ARDKCameraShaderBGRA" +{ + Properties + { + _texture ("Texture", 2D) = "black" {} + } + +// For GLES3 or GLES2 +SubShader +{ + Cull Off + Tags { "RenderType"="Opaque" } + + Pass + { + ZWrite Off + + GLSLPROGRAM + + #pragma only_renderers gles3 gles + + #ifdef SHADER_API_GLES3 + #extension GL_OES_EGL_image_external_essl3 : enable + #else + #extension GL_OES_EGL_image_external : enable + #endif + + uniform mat4 _textureTransform; + + #ifdef VERTEX + + varying vec2 textureCoord; + + void main() + { + #if defined(SHADER_API_GLES3) || defined(SHADER_API_GLES) + textureCoord = (_textureTransform * vec4(gl_MultiTexCoord0.x, gl_MultiTexCoord0.y, 0.0f, 1.0f)).xy; + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; + #endif + } + + #endif + + #ifdef FRAGMENT + varying vec2 textureCoord; + uniform samplerExternalOES _texture; + + void main() + { + #ifdef SHADER_API_GLES3 + gl_FragColor = texture(_texture, textureCoord); + #else + gl_FragColor = textureExternal(_texture, textureCoord); + #endif + } + + #endif + + ENDGLSL + } +} + + SubShader + { + Cull Off + Tags { "RenderType"="Opaque" } + LOD 100 + + Pass + { + ZWrite Off + CGPROGRAM + #pragma exclude_renderers gles3 + #pragma vertex vert + #pragma fragment frag + + #include "UnityCG.cginc" + + float4x4 _textureTransform; + + struct Vertex { + float4 position : POSITION; + float2 texcoord : TEXCOORD0; + }; + + struct TexCoordInOut { + float4 position : SV_POSITION; + float2 texcoord : TEXCOORD0; + }; + + TexCoordInOut vert (Vertex vertex) { + TexCoordInOut o; + o.position = UnityObjectToClipPos(vertex.position); + o.texcoord = mul(_textureTransform, float4(vertex.texcoord, 0.0f, 1.0f)).xy; + return o; + } + + // samplers + sampler2D _texture; + + fixed4 frag (TexCoordInOut i) : SV_Target { + // sample the texture + float2 texcoord = i.texcoord; + return tex2D(_texture, texcoord); + } + ENDCG + } + } + + + + FallBack Off +} diff --git a/Assets/ARDK/Rendering/Resources/BGRAShader.shader.meta b/Assets/ARDK/Rendering/Resources/BGRAShader.shader.meta new file mode 100644 index 0000000..7ec94d0 --- /dev/null +++ b/Assets/ARDK/Rendering/Resources/BGRAShader.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: bed1eafb4c4ce48ea86e557f30b1a650 +timeCreated: 1525206742 +licenseType: Pro +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Rendering/Resources/EditorFrame.shader b/Assets/ARDK/Rendering/Resources/EditorFrame.shader new file mode 100644 index 0000000..cd7ff06 --- /dev/null +++ b/Assets/ARDK/Rendering/Resources/EditorFrame.shader @@ -0,0 +1,146 @@ +Shader "Unlit/EditorFrame" +{ + Properties + { + _texture ("Texture", 2D) = "black" {} + _textureDepth ("Depth", 2D) = "black" {} + _textureDepthSuppressionMask ("Depth Suppresion Mask", 2D) = "black" {} + } + SubShader + { + Tags + { + "Queue" = "Background" + "RenderType" = "Background" + "ForceNoShadowCasting" = "True" + } + + Pass + { + Cull Off + ZWrite On + ZTest Always + Lighting Off + LOD 100 + Tags + { + "LightMode" = "Always" + } + + HLSLPROGRAM + + #pragma vertex vert + #pragma fragment frag + + #pragma multi_compile_local __ DEPTH_ZWRITE + #pragma multi_compile_local __ DEPTH_SUPPRESSION + #pragma multi_compile_local __ DEPTH_DEBUG + + #include "UnityCG.cginc" + + struct appdata + { + float4 vertex : POSITION; + float2 uv : TEXCOORD0; + }; + + struct v2f + { + float4 vertex : SV_POSITION; + float2 color_uv : TEXCOORD0; +#if DEPTH_ZWRITE + float3 depth_uv : TEXCOORD1; +#if DEPTH_SUPPRESSION + float3 semantics_uv : TEXCOORD2; +#endif +#endif + }; + + // Transform used to sample the color planes + float4x4 _displayTransform; + + // Transform used to sample the context awareness textures + float4x4 _depthTransform; + float4x4 _semanticsTransform; + + // Plane samplers + sampler2D _texture; + sampler2D _textureDepth; + sampler2D _textureDepthSuppressionMask; + + // Depth range used for scaling + float _depthScaleMin; + float _depthScaleMax; + +#if DEPTH_ZWRITE + + // Inverse of LinearEyeDepth + inline float EyeDepthToNonLinear(float eyeDepth, float4 zBufferParam) + { + return (1.0f - (eyeDepth * zBufferParam.w)) / (eyeDepth * zBufferParam.z * 2.0f); + } + +#endif + + v2f vert (appdata v) + { + v2f o; + o.vertex = UnityObjectToClipPos(v.vertex); + + // Transform UVs for the color texture + o.color_uv = mul(_displayTransform, float4(v.uv, 0.0f, 1.0f)).xy; + + // Transform UVs for the context awareness textures +#if DEPTH_ZWRITE + o.depth_uv = mul(_depthTransform, float4(v.uv, 1.0f, 1.0f)).xyz; +#if DEPTH_SUPPRESSION + o.semantics_uv = mul(_semanticsTransform, float4(v.uv, 1.0f, 1.0f)).xyz; +#endif +#endif + return o; + } + + void frag(in v2f i, out float4 out_color : SV_Target, out float out_depth : SV_Depth) + { + // Sample color + out_color = tex2D(_texture, i.color_uv); + + // Clear depth +#if defined(UNITY_REVERSED_Z) + out_depth = 0; +#else + out_depth = 1; +#endif + +#if DEPTH_ZWRITE +#if DEPTH_SUPPRESSION + // If depth is not suppressed at this pixel + float2 semanticsUV = float2(i.semantics_uv.x / i.semantics_uv.z, i.semantics_uv.y / i.semantics_uv.z); + if (tex2D(_textureDepthSuppressionMask, semanticsUV).r == 0.0f) +#endif + { + // Sample depth + float2 depthUV = float2(i.depth_uv.x / i.depth_uv.z, i.depth_uv.y / i.depth_uv.z); + float rawDepth = tex2D(_textureDepth, depthUV).r; + + // Scale depth in case it is normalized + // Note: If depth is not normalized, min and max should + // be 0 and 1 respectively to leave the value intact + float scaledDepth = rawDepth * (_depthScaleMax - _depthScaleMin) + _depthScaleMin; + + // Convert to nonlinear and write to the zbuffer + out_depth = EyeDepthToNonLinear(scaledDepth, _ZBufferParams); +#if DEPTH_DEBUG + // Write disparity to the color channels for debug purposes + const float MAX_VIEW_DISP = 4.0f; + const float scaledDisparity = 1.0/scaledDepth; + const float normDisparity = scaledDisparity/MAX_VIEW_DISP; + out_color = float4(normDisparity, normDisparity, normDisparity, 1.0f); +#endif + } +#endif + } + ENDHLSL + } + } +} diff --git a/Assets/ARDK/Rendering/Resources/EditorFrame.shader.meta b/Assets/ARDK/Rendering/Resources/EditorFrame.shader.meta new file mode 100644 index 0000000..1d5a51c --- /dev/null +++ b/Assets/ARDK/Rendering/Resources/EditorFrame.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 29d1ef4b965fd413c907f267fd5d8086 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Rendering/Resources/ExternalBlit.shader b/Assets/ARDK/Rendering/Resources/ExternalBlit.shader new file mode 100644 index 0000000..4af4ae6 --- /dev/null +++ b/Assets/ARDK/Rendering/Resources/ExternalBlit.shader @@ -0,0 +1,66 @@ +// Discussion: +// This shader was created to blit EGL textures (external) to +// regular Unity texture targets on Android platform. +// For context, ARCore performs its camera and pose update within the rendering thread. +// Therefore, we cannot use the external camera textures directly because their contents +// might get overriden during rendering. +// The currently implemented solution to tackle this issue, is to cache the external +// texture every frame and use the cached version for rendering, because it's guaranteed to be intact. +// Now, this is performed by a Graphics.Blit. It turns out, possibly due to variance in +// driver implementations, on some devices the built-in blit shader cannot read from external textures. +// This shader therefore is written in glsl, using an OES sampler explicitly to enable +// blitting on those devices as well. +// Note that, once ARDK implements the ability to use multiple native textures for its +// camera feed, amongst other things, this shader will become redundant and can be removed. +Shader "Unlit/ExternalBlit" +{ + Properties + { + _texture("Main Texture", 2D) = "white" {} + } + + SubShader + { + Pass + { + Cull Off ZWrite Off ZTest Always + Fog { Mode off } + + GLSLPROGRAM + + #ifdef SHADER_API_GLES3 + #extension GL_OES_EGL_image_external_essl3 : require + #else + #extension GL_OES_EGL_image_external : enable + #endif + + #ifdef VERTEX + + varying vec2 _textureCoord; + + void main() + { + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; + _textureCoord = gl_MultiTexCoord0.xy; + } + + #endif + + #ifdef FRAGMENT + + uniform samplerExternalOES _texture; + varying vec2 _textureCoord; + + void main() + { + gl_FragColor = texture(_texture, _textureCoord); + } + + #endif + + ENDGLSL + } + } + + Fallback Off +} \ No newline at end of file diff --git a/Assets/ARDK/Rendering/Resources/ExternalBlit.shader.meta b/Assets/ARDK/Rendering/Resources/ExternalBlit.shader.meta new file mode 100644 index 0000000..53a9b85 --- /dev/null +++ b/Assets/ARDK/Rendering/Resources/ExternalBlit.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 367e019b002c04f4cb43ef55118ce2f8 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Rendering/Resources/YCbCrShader.shader b/Assets/ARDK/Rendering/Resources/YCbCrShader.shader new file mode 100644 index 0000000..a7f0e42 --- /dev/null +++ b/Assets/ARDK/Rendering/Resources/YCbCrShader.shader @@ -0,0 +1,69 @@ +Shader "Unlit/ARDKCameraShaderYCbCr" +{ + Properties + { + // Together the following textures produce BLACK in YCbCr format! + _textureY ("TextureY", 2D) = "black" {} + _textureCbCr ("TextureCbCr", 2D) = "gray" {} + } + SubShader + { + Cull Off + Tags { "RenderType"="Opaque" } + LOD 100 + + Pass + { + ZWrite Off + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + + #include "UnityCG.cginc" + + float4x4 _textureTransform; + + struct Vertex + { + float4 position : POSITION; + float2 texcoord : TEXCOORD0; + }; + + struct TexCoordInOut + { + float4 position : SV_POSITION; + float2 texcoord : TEXCOORD0; + }; + + TexCoordInOut vert (Vertex vertex) + { + TexCoordInOut o; + o.position = UnityObjectToClipPos(vertex.position); + o.texcoord = mul(_textureTransform, float4(vertex.texcoord, 0.0f, 1.0f)).xy; + return o; + } + + // samplers + sampler2D _textureY; + sampler2D _textureCbCr; + + fixed4 frag (TexCoordInOut i) : SV_Target + { + // sample the texture + float2 texcoord = i.texcoord; + float y = tex2D(_textureY, texcoord).r; + float4 ycbcr = float4(y, tex2D(_textureCbCr, texcoord).rg, 1.0); + + const float4x4 ycbcrToRGBTransform = float4x4( + float4(1.0, +0.0000, +1.4020, -0.7010), + float4(1.0, -0.3441, -0.7141, +0.5291), + float4(1.0, +1.7720, +0.0000, -0.8860), + float4(0.0, +0.0000, +0.0000, +1.0000) + ); + + return mul(ycbcrToRGBTransform, ycbcr); + } + ENDCG + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/Rendering/Resources/YCbCrShader.shader.meta b/Assets/ARDK/Rendering/Resources/YCbCrShader.shader.meta new file mode 100644 index 0000000..790682e --- /dev/null +++ b/Assets/ARDK/Rendering/Resources/YCbCrShader.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 515e9b5d7265f415ba6c10f447a279d8 +timeCreated: 1525206742 +licenseType: Pro +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Rendering/SRP.meta b/Assets/ARDK/Rendering/SRP.meta new file mode 100644 index 0000000..33b7e39 --- /dev/null +++ b/Assets/ARDK/Rendering/SRP.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6d54bac4437b84a5abce19f9c3159164 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Rendering/SRP/ARSessionFeature.cs b/Assets/ARDK/Rendering/SRP/ARSessionFeature.cs new file mode 100644 index 0000000..8b21c07 --- /dev/null +++ b/Assets/ARDK/Rendering/SRP/ARSessionFeature.cs @@ -0,0 +1,91 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +#if ARDK_HAS_URP +using System; + +using UnityEngine; +using UnityEngine.Rendering; +using UnityEngine.Rendering.Universal; + +using Niantic.ARDK.Rendering.SRP; + +namespace Niantic.ARDK.Rendering.SRP +{ + public class ARSessionFeature: ScriptableRendererFeature + { + [Serializable] + public class ARSessionFeatureSettings + { + public bool IsBackgroundPassEnabled; + } + + // Must be named "settings" (lowercase) to be shown in the Render Features inspector + public ARSessionFeatureSettings settings = new ARSessionFeatureSettings(); + + private _CommandBufferPass _backgroundPass; + private _CommandBufferPass _afterRenderingPass; + + public override void Create() + { + } + + public void SetupBackgroundPass(Camera camera, CommandBuffer commandBuffer) + { + if (camera == null) + throw new ArgumentNullException(nameof(camera)); + + if (commandBuffer == null) + throw new ArgumentNullException(nameof(commandBuffer)); + + _backgroundPass = new _CommandBufferPass(RenderPassEvent.BeforeRenderingOpaques); + _backgroundPass.Setup(camera, commandBuffer); + } + + public void SetupAfterRenderingPass(Camera camera, CommandBuffer commandBuffer) + { + if (camera == null) + throw new ArgumentNullException(nameof(camera)); + + if (commandBuffer == null) + throw new ArgumentNullException(nameof(commandBuffer)); + + _afterRenderingPass = new _CommandBufferPass(RenderPassEvent.AfterRendering); + _afterRenderingPass.Setup(camera, commandBuffer); + } + + public void RemoveBackgroundPass() + { + settings.IsBackgroundPassEnabled = false; + _backgroundPass = null; + } + + public void RemoveNativePass() + { + _afterRenderingPass = null; + } + + public override void AddRenderPasses + ( + ScriptableRenderer renderer, + ref RenderingData renderingData + ) + { + if (settings.IsBackgroundPassEnabled) + { + if (_backgroundPass != null && + renderingData.cameraData.camera == _backgroundPass.TargetCamera) + { + renderer.EnqueuePass(_backgroundPass); + } + } + + if (_afterRenderingPass != null && + renderingData.cameraData.camera == _afterRenderingPass.TargetCamera) + { + renderer.EnqueuePass(_afterRenderingPass); + } + } + } +} + +#endif diff --git a/Assets/ARDK/Rendering/SRP/ARSessionFeature.cs.meta b/Assets/ARDK/Rendering/SRP/ARSessionFeature.cs.meta new file mode 100644 index 0000000..3e77864 --- /dev/null +++ b/Assets/ARDK/Rendering/SRP/ARSessionFeature.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 725810a0501574c09844b394e6a907a9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Rendering/SRP/ArdkReplacementRenderer.asset b/Assets/ARDK/Rendering/SRP/ArdkReplacementRenderer.asset new file mode 100644 index 0000000..1eef2ac --- /dev/null +++ b/Assets/ARDK/Rendering/SRP/ArdkReplacementRenderer.asset @@ -0,0 +1,78 @@ +%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: ArdkReplacementRenderer + m_EditorClassIdentifier: + m_RendererFeatures: + - {fileID: 2804613763663772903} + m_RendererFeatureMap: e7bc59cb5bfdeb26 + postProcessData: {fileID: 11400000, guid: 41439944d30ece34e96484bdb6645b55, type: 2} + shaders: + blitPS: {fileID: 4800000, guid: c17132b1f77d20942aa75f8429c0f8bc, type: 3} + copyDepthPS: {fileID: 4800000, guid: d6dae50ee9e1bfa4db75f19f99355220, type: 3} + screenSpaceShadowPS: {fileID: 4800000, guid: 0f854b35a0cf61a429bd5dcfea30eddd, + type: 3} + samplingPS: {fileID: 4800000, guid: 04c410c9937594faa893a11dceb85f7e, type: 3} + fallbackErrorPS: {fileID: 4800000, guid: e6e9a19c3678ded42a3bc431ebef7dbd, type: 3} + m_OpaqueLayerMask: + serializedVersion: 2 + m_Bits: 0 + m_TransparentLayerMask: + serializedVersion: 2 + m_Bits: 0 + m_DefaultStencilState: + overrideStencilState: 0 + stencilReference: 0 + stencilCompareFunction: 8 + passOperation: 0 + failOperation: 0 + zFailOperation: 0 + m_ShadowTransparentReceive: 0 +--- !u!114 &2804613763663772903 +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: 6b3d386ba5cd94485973aee1479b272e, type: 3} + m_Name: SemanticLabels + m_EditorClassIdentifier: + m_Active: 1 + settings: + passTag: SemanticLabels + Event: 300 + filterSettings: + RenderQueueType: 0 + LayerMask: + serializedVersion: 2 + m_Bits: 256 + PassNames: [] + overrideMaterial: {fileID: 2100000, guid: b218845e158f048c78cb09bc2c407366, type: 2} + overrideMaterialPassIndex: 0 + overrideDepthState: 0 + depthCompareFunction: 4 + enableWrite: 1 + stencilSettings: + overrideStencilState: 0 + stencilReference: 0 + stencilCompareFunction: 8 + passOperation: 0 + failOperation: 0 + zFailOperation: 0 + cameraSettings: + overrideCamera: 0 + restoreCamera: 1 + offset: {x: 0, y: 0, z: 0, w: 0} + cameraFieldOfView: 60 diff --git a/Assets/ARDK/Rendering/SRP/ArdkReplacementRenderer.asset.meta b/Assets/ARDK/Rendering/SRP/ArdkReplacementRenderer.asset.meta new file mode 100644 index 0000000..27243cb --- /dev/null +++ b/Assets/ARDK/Rendering/SRP/ArdkReplacementRenderer.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c89fc15b6f5fc4c83b9444bfa325c19a +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Rendering/SRP/ArdkUrpAsset.asset b/Assets/ARDK/Rendering/SRP/ArdkUrpAsset.asset new file mode 100644 index 0000000..0b0b498 --- /dev/null +++ b/Assets/ARDK/Rendering/SRP/ArdkUrpAsset.asset @@ -0,0 +1,57 @@ +%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: ArdkUrpAsset + m_EditorClassIdentifier: + k_AssetVersion: 5 + k_AssetPreviousVersion: 5 + m_RendererType: 1 + m_RendererData: {fileID: 0} + m_RendererDataList: + - {fileID: 11400000, guid: 7d3be5c514c9a4ac7af188b9969f47de, type: 2} + - {fileID: 11400000, guid: c89fc15b6f5fc4c83b9444bfa325c19a, type: 2} + m_DefaultRendererIndex: 0 + m_RequireDepthTexture: 0 + m_RequireOpaqueTexture: 0 + m_OpaqueDownsampling: 1 + m_SupportsTerrainHoles: 1 + m_SupportsHDR: 0 + m_MSAA: 1 + m_RenderScale: 1 + m_MainLightRenderingMode: 1 + m_MainLightShadowsSupported: 1 + m_MainLightShadowmapResolution: 2048 + m_AdditionalLightsRenderingMode: 1 + m_AdditionalLightsPerObjectLimit: 4 + m_AdditionalLightShadowsSupported: 0 + m_AdditionalLightsShadowmapResolution: 512 + m_ShadowDistance: 50 + m_ShadowCascades: 0 + m_Cascade2Split: 0.25 + m_Cascade4Split: {x: 0.067, y: 0.2, z: 0.467} + m_ShadowDepthBias: 1 + m_ShadowNormalBias: 1 + m_SoftShadowsSupported: 0 + m_UseSRPBatcher: 1 + m_SupportsDynamicBatching: 0 + m_MixedLightingSupported: 1 + m_DebugLevel: 0 + m_UseAdaptivePerformance: 0 + m_PostProcessingFeatureSet: 0 + m_ColorGradingMode: 0 + m_ColorGradingLutSize: 32 + m_ShadowType: 1 + m_LocalShadowsSupported: 0 + m_LocalShadowsAtlasResolution: 256 + m_MaxPixelLights: 0 + m_ShadowAtlasResolution: 256 + m_ShaderVariantLogLevel: 0 diff --git a/Assets/ARDK/Rendering/SRP/ArdkUrpAsset.asset.meta b/Assets/ARDK/Rendering/SRP/ArdkUrpAsset.asset.meta new file mode 100644 index 0000000..9de73e9 --- /dev/null +++ b/Assets/ARDK/Rendering/SRP/ArdkUrpAsset.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a857f2a9d2f014d2b84f097d70eefa14 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Rendering/SRP/ArdkUrpAssetRenderer.asset b/Assets/ARDK/Rendering/SRP/ArdkUrpAssetRenderer.asset new file mode 100644 index 0000000..6829673 --- /dev/null +++ b/Assets/ARDK/Rendering/SRP/ArdkUrpAssetRenderer.asset @@ -0,0 +1,122 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &-4594455243346908458 +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: 725810a0501574c09844b394e6a907a9, type: 3} + m_Name: NewBeforeOpaqueFeature + m_EditorClassIdentifier: + m_Active: 1 + settings: + IsBackgroundPassEnabled: 0 +--- !u!114 &-4389037444396958428 +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: 725810a0501574c09844b394e6a907a9, type: 3} + m_Name: ARSessionFeature + m_EditorClassIdentifier: + m_Active: 1 + settings: + IsBackgroundPassEnabled: 0 +--- !u!114 &-4240945727464425909 +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: 6b3d386ba5cd94485973aee1479b272e, type: 3} + m_Name: SemanticLabels + m_EditorClassIdentifier: + m_Active: 1 + settings: + passTag: SemanticLabels + Event: 300 + filterSettings: + RenderQueueType: 0 + LayerMask: + serializedVersion: 2 + m_Bits: 256 + PassNames: [] + overrideMaterial: {fileID: 0} + overrideMaterialPassIndex: 0 + overrideDepthState: 0 + depthCompareFunction: 4 + enableWrite: 1 + stencilSettings: + overrideStencilState: 0 + stencilReference: 0 + stencilCompareFunction: 8 + passOperation: 0 + failOperation: 0 + zFailOperation: 0 + cameraSettings: + overrideCamera: 0 + restoreCamera: 1 + offset: {x: 0, y: 0, z: 0, w: 0} + cameraFieldOfView: 60 +--- !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: ArdkUrpAssetRenderer + m_EditorClassIdentifier: + m_RendererFeatures: + - {fileID: -4389037444396958428} + - {fileID: 5519357869355778861} + m_RendererFeatureMap: 24bdd4ccb20117c32d433547bdb2984c + postProcessData: {fileID: 11400000, guid: 41439944d30ece34e96484bdb6645b55, type: 2} + shaders: + blitPS: {fileID: 4800000, guid: c17132b1f77d20942aa75f8429c0f8bc, type: 3} + copyDepthPS: {fileID: 4800000, guid: d6dae50ee9e1bfa4db75f19f99355220, type: 3} + screenSpaceShadowPS: {fileID: 4800000, guid: 0f854b35a0cf61a429bd5dcfea30eddd, + type: 3} + samplingPS: {fileID: 4800000, guid: 04c410c9937594faa893a11dceb85f7e, type: 3} + fallbackErrorPS: {fileID: 4800000, guid: e6e9a19c3678ded42a3bc431ebef7dbd, type: 3} + m_OpaqueLayerMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_TransparentLayerMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_DefaultStencilState: + overrideStencilState: 0 + stencilReference: 0 + stencilCompareFunction: 8 + passOperation: 0 + failOperation: 0 + zFailOperation: 0 + m_ShadowTransparentReceive: 0 +--- !u!114 &5519357869355778861 +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: 50b17de350ea549a4a4312087f83fb9d, type: 3} + m_Name: DepthMeshRendererFeature + m_EditorClassIdentifier: + m_Active: 1 diff --git a/Assets/ARDK/Rendering/SRP/ArdkUrpAssetRenderer.asset.meta b/Assets/ARDK/Rendering/SRP/ArdkUrpAssetRenderer.asset.meta new file mode 100644 index 0000000..49d03f8 --- /dev/null +++ b/Assets/ARDK/Rendering/SRP/ArdkUrpAssetRenderer.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7d3be5c514c9a4ac7af188b9969f47de +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Rendering/SRP/SemanticsMat.mat b/Assets/ARDK/Rendering/SRP/SemanticsMat.mat new file mode 100644 index 0000000..b3a3891 --- /dev/null +++ b/Assets/ARDK/Rendering/SRP/SemanticsMat.mat @@ -0,0 +1,90 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &-3084654156391112256 +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: 2 +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: SemanticsMat + m_Shader: {fileID: 4800000, guid: a4c48a72b6b249c1a1da1226dd53dedd, type: 3} + m_ShaderKeywords: + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + 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} + - _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} + - _SpecGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _AlphaClip: 0 + - _Blend: 0 + - _BumpScale: 1 + - _Cull: 2 + - _Cutoff: 0.5 + - _DstBlend: 0 + - _EnvironmentReflections: 1 + - _GlossMapScale: 0 + - _Glossiness: 0 + - _GlossyReflections: 0 + - _Metallic: 0 + - _OcclusionStrength: 1 + - _QueueOffset: 0 + - _ReceiveShadows: 1 + - _Smoothness: 0.5 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _Surface: 0 + - _WorkflowMode: 1 + - _ZWrite: 1 + m_Colors: + - PackedColor: {r: 0, g: 0, b: 0, a: 0} + - _BaseColor: {r: 1, g: 1, b: 1, a: 1} + - _Color: {r: 1, g: 1, b: 1, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} diff --git a/Assets/ARDK/Rendering/SRP/SemanticsMat.mat.meta b/Assets/ARDK/Rendering/SRP/SemanticsMat.mat.meta new file mode 100644 index 0000000..147c531 --- /dev/null +++ b/Assets/ARDK/Rendering/SRP/SemanticsMat.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b218845e158f048c78cb09bc2c407366 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Rendering/SRP/_CommandBufferPass.cs b/Assets/ARDK/Rendering/SRP/_CommandBufferPass.cs new file mode 100644 index 0000000..2e628d4 --- /dev/null +++ b/Assets/ARDK/Rendering/SRP/_CommandBufferPass.cs @@ -0,0 +1,54 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +#if ARDK_HAS_URP + +using UnityEngine; +using UnityEngine.Rendering; +using UnityEngine.Rendering.Universal; + +namespace Niantic.ARDK.Rendering.SRP +{ + internal sealed class _CommandBufferPass: ScriptableRenderPass + { + public Camera TargetCamera + { + get + { + return _targetCamera; + } + } + + public CommandBuffer CommandBuffer + { + get + { + return _commandBuffer; + } + } + + private Camera _targetCamera; + private CommandBuffer _commandBuffer; + + public _CommandBufferPass(RenderPassEvent renderPassEvent) + { + this.renderPassEvent = renderPassEvent; + } + + public void Setup(Camera targetCamera, CommandBuffer commandBuffer) + { + _targetCamera = targetCamera; + _commandBuffer = commandBuffer; + } + + public override void Execute + ( + ScriptableRenderContext context, + ref RenderingData renderingData + ) + { + context.ExecuteCommandBuffer(_commandBuffer); + } + } +} + +#endif \ No newline at end of file diff --git a/Assets/ARDK/Rendering/SRP/_CommandBufferPass.cs.meta b/Assets/ARDK/Rendering/SRP/_CommandBufferPass.cs.meta new file mode 100644 index 0000000..6f8e4dd --- /dev/null +++ b/Assets/ARDK/Rendering/SRP/_CommandBufferPass.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 07a602b36a37a409b97472bba98ee220 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Rendering/SRP/_RenderPipelineInternals.cs b/Assets/ARDK/Rendering/SRP/_RenderPipelineInternals.cs new file mode 100644 index 0000000..d7b993f --- /dev/null +++ b/Assets/ARDK/Rendering/SRP/_RenderPipelineInternals.cs @@ -0,0 +1,103 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +#if ARDK_HAS_URP + +using System; +using System.Collections.Generic; +using System.Reflection; + +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; +using UnityEngine.Rendering.Universal; + +namespace Niantic.ARDK.Rendering.SRP +{ + /// + /// Provides reflection-based access to the internal interface of the rendering pipeline. + /// + internal static class _RenderPipelineInternals + { + public const string ARDK_RENDERER_NAME = "ArdkUrpAssetRenderer"; + public const string REPLACEMENT_RENDERER_NAME = "ArdkReplacementRenderer"; + + private static Dictionary _features = + new Dictionary(); + + public static bool IsUniversalRenderPipelineEnabled + { + get + { + var asset = UniversalRenderPipeline.asset; + return asset != null && UniversalRenderPipeline.asset.scriptableRenderer != null; + } + } + + public static void SetFeatureActive(bool isActive) + where T:ScriptableRendererFeature + { + var feature = GetFeatureOfType(); + + if (feature == null) + { + var messageFormat = + "No {0} was found added to the active Universal Render Pipeline Renderer."; + Debug.LogWarningFormat(messageFormat, typeof(T).Name); + } + + feature.SetActive(isActive); + } + + public static T GetFeatureOfType() + where T: ScriptableRendererFeature + { + if (!IsUniversalRenderPipelineEnabled) + return null; + + if (_features.ContainsKey(typeof(T))) + return _features[typeof(T)] as T; + + var renderer = UniversalRenderPipeline.asset.scriptableRenderer; + + var propertyInfo = + renderer + .GetType() + .GetProperty("rendererFeatures", BindingFlags.Instance | BindingFlags.NonPublic); + + var features = (List) propertyInfo.GetValue(renderer); + var item = features.Find(x => x is T); + + _features.Add(typeof(T), item); + + return item as T; + } + + public static int GetRendererIndex(string rendererName) + { + if (!IsUniversalRenderPipelineEnabled) + return -1; + + var index = 0; + + var pipeline = UniversalRenderPipeline.asset; + var fieldInfo = + pipeline + .GetType() + .GetField("m_RendererDataList", BindingFlags.Instance | BindingFlags.NonPublic); + + var data = (ScriptableRendererData[]) fieldInfo.GetValue(pipeline); + + while (index < data.Length) + { + if (string.Equals(data[index].name, rendererName)) + return index; + + index++; + } + + return -1; + } + } +} + +#endif diff --git a/Assets/ARDK/Rendering/SRP/_RenderPipelineInternals.cs.meta b/Assets/ARDK/Rendering/SRP/_RenderPipelineInternals.cs.meta new file mode 100644 index 0000000..ab98c7f --- /dev/null +++ b/Assets/ARDK/Rendering/SRP/_RenderPipelineInternals.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d480a7ef130024690ba13dc02dcd7c84 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Rendering/_VirtualCamera.cs b/Assets/ARDK/Rendering/_VirtualCamera.cs new file mode 100644 index 0000000..93b5daf --- /dev/null +++ b/Assets/ARDK/Rendering/_VirtualCamera.cs @@ -0,0 +1,130 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.Utilities; + +using UnityEngine; +using UnityEngine.Rendering; + +using Object = UnityEngine.Object; + +namespace Niantic.ARDK.Rendering +{ + /// + /// Helper for creating a virtual camera that doesn't render the game world, but instead can be + /// used by the user to inject rendering commands into Unity's rendering pipeline. + /// + internal sealed class _VirtualCamera: IDisposable + { + ~_VirtualCamera() + { + ReleaseUnmanagedResources(); + } + + public event Action<_VirtualCamera> OnPreRender = camera => {}; + public event Action<_VirtualCamera> OnPostRender = camera => {}; + + private RealCamera _realCamera; + + private const int GpuCacheLineSize = 128; + + public Camera GetCamera() + { + return _realCamera._camera; + } + + /// + /// Creates a new virtual camera. + /// + /// A callback that is invoked to setup the UnityCamera before it is hidden. + /// The command buffer to attach to the unity camera. + /// The order in the unity rending pipeline this should be executed in. + public _VirtualCamera + ( + Action setupRealCamera, + CommandBuffer commandBuffer, + int renderOrder = Int32.MinValue + ) + { + _realCamera = + new GameObject("__real_camera__", typeof(RealCamera)).GetComponent(); + + _realCamera.Init(); + setupRealCamera(_realCamera._camera); + + ARSessionBuffersHelper.AddAfterRenderingBuffer(_realCamera._camera, commandBuffer); + + _realCamera.gameObject.hideFlags = HideFlags.HideInHierarchy; + _realCamera._camera.depth = renderOrder; + _realCamera._owner = this; + + if (Application.isPlaying) + { + Object.DontDestroyOnLoad(_realCamera.gameObject); + } + } + + private class RealCamera: MonoBehaviour + { + public Camera _camera; + + public _VirtualCamera _owner; + + internal void Init() + { + _camera = gameObject.AddComponent(); + var _renderBuffer = new RenderTexture(GpuCacheLineSize, 1, 0, RenderTextureFormat.R8); + _camera.targetTexture = _renderBuffer; + _camera.cullingMask = 0; + } + + private void OnPreRender() + { + _owner.OnPreRender(_owner); + } + + private void OnPostRender() + { + _owner.OnPostRender(_owner); + } + } + + /// + /// Forces the virtual camera to render. This command will halt the CPU until all rendering for + /// this virtual camera is finished. + /// + public void ForceRender() + { + _realCamera._camera.Render(); + } + + private void ReleaseUnmanagedResources() + { + _CallbackQueue.QueueCallback + ( + () => + { + if (_realCamera != null) + { + // This check is to allow unit tests to run this code + if (Application.isEditor) + { + Object.DestroyImmediate(_realCamera.gameObject); + } + else + { + Object.Destroy(_realCamera.gameObject); + } + } + } + ); + } + + public void Dispose() + { + ReleaseUnmanagedResources(); + GC.SuppressFinalize(this); + } + } +} diff --git a/Assets/ARDK/Rendering/_VirtualCamera.cs.meta b/Assets/ARDK/Rendering/_VirtualCamera.cs.meta new file mode 100644 index 0000000..65c9224 --- /dev/null +++ b/Assets/ARDK/Rendering/_VirtualCamera.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 362eee9eade647f981f253a29fd0db5c +timeCreated: 1553554180 \ No newline at end of file diff --git a/Assets/ARDK/Rendering/_VirtualCameraFactory.cs b/Assets/ARDK/Rendering/_VirtualCameraFactory.cs new file mode 100644 index 0000000..d712645 --- /dev/null +++ b/Assets/ARDK/Rendering/_VirtualCameraFactory.cs @@ -0,0 +1,38 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using UnityEngine.Rendering; + +namespace Niantic.ARDK.Rendering +{ + /// + /// Helper for creating a . + /// + internal static class _VirtualCameraFactory + { + /// + /// Creates a virtual camera that will automatically render every unity frame. + /// + /// The command buffer to execute on the camera. + /// When in the render stack this virtual camera should be rendered. + /// The newly created + public static _VirtualCamera CreateContinousVirtualCamera + (CommandBuffer commandBuffer, int renderOrder = Int32.MinValue) + { + return new _VirtualCamera(camera => {}, commandBuffer, renderOrder); + } + + /// + /// Creates a virtual camera that will need to be told explicitly when to render by the user. + /// + /// The command buffer to run on render. + /// When in the render stack this virtual camera should be rendered. + /// The newly created + public static _VirtualCamera CreateSnapshotVirtualCamera + (CommandBuffer commandBuffer, int renderOrder = Int32.MinValue) + { + return new _VirtualCamera(camera => camera.enabled = false, commandBuffer, renderOrder); + } + } +} diff --git a/Assets/ARDK/Rendering/_VirtualCameraFactory.cs.meta b/Assets/ARDK/Rendering/_VirtualCameraFactory.cs.meta new file mode 100644 index 0000000..2f8b2fd --- /dev/null +++ b/Assets/ARDK/Rendering/_VirtualCameraFactory.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 4cfd7b21b141401487b01c7fc50e8f62 +timeCreated: 1553554279 \ No newline at end of file diff --git a/Assets/ARDK/Resources.meta b/Assets/ARDK/Resources.meta new file mode 100644 index 0000000..2df88ed --- /dev/null +++ b/Assets/ARDK/Resources.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4f54549ed8f7599419b0750dc83e378f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities.meta b/Assets/ARDK/Utilities.meta new file mode 100644 index 0000000..a660a79 --- /dev/null +++ b/Assets/ARDK/Utilities.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 8cd6396b55bf54e0d800b6b42cc68fce +folderAsset: yes +timeCreated: 1546974931 +licenseType: Pro +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/ArdkEventHandler.cs b/Assets/ARDK/Utilities/ArdkEventHandler.cs new file mode 100644 index 0000000..bbfa925 --- /dev/null +++ b/Assets/ARDK/Utilities/ArdkEventHandler.cs @@ -0,0 +1,15 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.Utilities +{ + // Mark only interface for event-args. The only reason to have this interface is to avoid + // a possible accidental use of an ArdkEventHandler with a non-args object (like passing + // a MultipeerNetworking object instead of an args that contains a MultipeerNetworking). + public interface IArdkEventArgs + { + } + + public delegate void ArdkEventHandler(TArgs args) + where + TArgs: IArdkEventArgs; +} diff --git a/Assets/ARDK/Utilities/ArdkEventHandler.cs.meta b/Assets/ARDK/Utilities/ArdkEventHandler.cs.meta new file mode 100644 index 0000000..513ae7b --- /dev/null +++ b/Assets/ARDK/Utilities/ArdkEventHandler.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0089a67510198422f891db59b768066c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization.meta b/Assets/ARDK/Utilities/BinarySerialization.meta new file mode 100644 index 0000000..43f8433 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 54b06c7a6574842c68eea96a57b4755a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/BinaryDeserializer.cs b/Assets/ARDK/Utilities/BinarySerialization/BinaryDeserializer.cs new file mode 100644 index 0000000..481eed2 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/BinaryDeserializer.cs @@ -0,0 +1,53 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.IO; + +using Niantic.ARDK.Utilities.BinarySerialization.Contexts; +using Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers; +using Niantic.ARDK.Utilities.Logging; + +namespace Niantic.ARDK.Utilities.BinarySerialization +{ + /// + /// Class used to deserialize objects that were serialized using the BinarySerializer class. + /// + public sealed class BinaryDeserializer: + BinarySerializerOrDeserializer + { + private readonly _TypeDeserializationContext _context = new _TypeDeserializationContext(); + + /// + /// Creates a new BinaryDeserializer that uses the given Stream to read the data to deserialize. + /// + public BinaryDeserializer(Stream stream): + base(stream) + { + ARLog._Debug("Creating a BinaryDeserializer."); + } + + public override void Dispose() + { + base.Dispose(); + + ARLog._Debug("Disposed of a BinaryDeserializer."); + } + + /// + /// Deserializes an object from the Stream this deserializer is bound to. + /// The deserialization can throw if the Stream is closed, if there's no more data to read + /// or if the Stream data is just corrupted. + /// + public object Deserialize() + { + UInt32 id = CompressedUInt32Serializer.Instance.Deserialize(this); + // ID 0 is the magic number for null. + if (id == 0) + return null; + + var itemDeserializer = _context._DeserializeTypeAndGetItemDeserializer(this, id); + return itemDeserializer.Deserialize(this); + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/BinaryDeserializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/BinaryDeserializer.cs.meta new file mode 100644 index 0000000..46f0824 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/BinaryDeserializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c92369c6c3a624845988fca94ed9e3f3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/BinarySerializer.cs b/Assets/ARDK/Utilities/BinarySerialization/BinarySerializer.cs new file mode 100644 index 0000000..f1dfa24 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/BinarySerializer.cs @@ -0,0 +1,71 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.IO; + +using Niantic.ARDK.Utilities.BinarySerialization.Contexts; +using Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers; +using Niantic.ARDK.Utilities.Logging; + +namespace Niantic.ARDK.Utilities.BinarySerialization +{ + /// + /// Class used to serialize objects in binary-format. + /// + public sealed class BinarySerializer: + BinarySerializerOrDeserializer + { + private readonly _TypeSerializationContext _context = new _TypeSerializationContext(); + + /// + /// Creates a new binary-serializer, which will serialize data to the given stream. + /// + public BinarySerializer(Stream stream): + base(stream) + { + ARLog._Debug("Creating a BinarySerializer."); + } + + /// + /// Releases the resources of this serializer and flushes the stream. + /// Disposing of the stream is not done, on purpose, as we might want to use + /// different serializers to send each message over a NetworkStream or similar. + /// + public override void Dispose() + { + var stream = Stream; + base.Dispose(); + + if (stream != null) + stream.Flush(); + + ARLog._Debug("Disposed of a BinarySerializer."); + } + + /// + /// Serializes the given item (including null) to the Stream this BinarySerializer is bound to. + /// If an item-serializer for the given type is not found, an exception is thrown. + /// + public void Serialize(object item) + { + if (item == null) + { + CompressedUInt32Serializer.Instance.Serialize(this, 0); + return; + } + + var itemType = item.GetType(); + + GlobalSerializer._SerializerInfo info; + if (!GlobalSerializer._itemSerializers.TryGetValue(itemType, out info)) + { + string message = "There's no item serializer for type " + itemType.FullName + "."; + throw new InvalidOperationException(message); + } + + _context._SerializeType(this, itemType, info._serializationName); + info._serializer.Serialize(this, item); + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/BinarySerializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/BinarySerializer.cs.meta new file mode 100644 index 0000000..d39a9d5 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/BinarySerializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c5e99d2509d694b19ab3045db269e7bf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/BinarySerializerOrDeserializer.cs b/Assets/ARDK/Utilities/BinarySerialization/BinarySerializerOrDeserializer.cs new file mode 100644 index 0000000..0207204 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/BinarySerializerOrDeserializer.cs @@ -0,0 +1,85 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.IO; + +using Niantic.ARDK.Utilities.BinarySerialization.Contexts; +using Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers; + +namespace Niantic.ARDK.Utilities.BinarySerialization +{ + /// + /// Base class for both binary serializers and binary deserializers. + /// This class is responsible for holding the Stream as well as the "serialization contexts" + /// that might be needed during serialization. + /// + public abstract class BinarySerializerOrDeserializer: + IDisposable + { + private static readonly object _runningStreamsLock = new object(); + private static readonly HashSet _runningStreams = + new HashSet(_ReferenceComparer.Instance); + + private readonly Dictionary _contexts = + new Dictionary(_ReferenceComparer.Instance); + + const string _duplicatedSerializerErrorMessage = + "There's another BinarySerializer or BinaryDeserializer for this stream.\n" + + "Use it instead or dispose it before creating a new one."; + + internal BinarySerializerOrDeserializer(Stream stream) + { + if (stream == null) + throw new ArgumentNullException(nameof(stream)); + + lock(_runningStreamsLock) + if (!_runningStreams.Add(stream)) + throw new InvalidOperationException(_duplicatedSerializerErrorMessage); + + Stream = stream; + } + + /// + /// Releases resources used by this serializer or deserializer. + /// This does *not* dispose the stream. + /// + public virtual void Dispose() + { + var stream = Stream; + if (stream == null) + return; + + Stream = null; + + lock(_runningStreamsLock) + _runningStreams.Remove(stream); + } + + /// + /// Gets the stream used to serialize or deserialize data from this serializer/deserializer. + /// + public Stream Stream { get; private set; } + + /// + /// Gets a context of type T for this serialization. Item serializers might want to keep some + /// context per serialization, like arrays use a maximum length limit, which is controlled by + /// the class ArrayLengthLimiter (which is a context class). + /// + public T GetContext() + where + T: ISerializationContext, new() + { + ISerializationContext context; + _contexts.TryGetValue(typeof(T), out context); + + if (context == null) + { + context = new T(); + _contexts.Add(typeof(T), context); + } + + return (T)context; + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/BinarySerializerOrDeserializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/BinarySerializerOrDeserializer.cs.meta new file mode 100644 index 0000000..e671454 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/BinarySerializerOrDeserializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cbdf37e4cfb1e4984adb2a3fb3c252e9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/Contexts.meta b/Assets/ARDK/Utilities/BinarySerialization/Contexts.meta new file mode 100644 index 0000000..1d14534 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/Contexts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b782fce834f5c4f2a8edd27c70c5e409 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/Contexts/ArrayLengthLimiter.cs b/Assets/ARDK/Utilities/BinarySerialization/Contexts/ArrayLengthLimiter.cs new file mode 100644 index 0000000..d3024e7 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/Contexts/ArrayLengthLimiter.cs @@ -0,0 +1,62 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.IO; + +using UnityEngine; + +namespace Niantic.ARDK.Utilities.BinarySerialization.Contexts +{ + /// + /// Context class used by array serializers to limit the maximum amount of array items + /// in a single serialization (even if from different arrays). This is used to avoid possible + /// Denial of Service attacks where a Stream tells to allocate 2GB of memory or similar. + /// The limit is int items, not actual bytes allocated. By default, the limit is 10 million items, + /// which is around one 10mb for bytes, 40mb for ints. + /// + public sealed class ArrayLengthLimiter: + ISerializationContext + { + private static int _limit = 10 * 1000 * 1000; // Approx 10mb. + + /// + /// Gets or sets the limit of array items that can be serialized or deserialized. + /// This value is used *before* allocating memory during deserialization, as a way to avoid + /// DoS attacks. + /// + public static int Limit + { + get + { + return _limit; + } + set + { + if (value < 0) + throw new ArgumentOutOfRangeException("Limit"); + + _limit = value; + } + } + + /// + /// Gets the amount of array items already in use during the current (de)serialization process. + /// + public int AmountInUse { get; private set; } + + private const string _errorMessageAboveLimit = + "The requested amount will pass the limit length reserved for this serialization operation."; + + /// + /// Reserves the given amount of "array items" or throw an InvalidOperationException if that + // amount will be above the limit allowed for the current serialization process. + /// + public void ReserveOrThrow(int amount) + { + if (AmountInUse + amount > _limit) + throw new InvalidOperationException(_errorMessageAboveLimit); + + AmountInUse += amount; + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/Contexts/ArrayLengthLimiter.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/Contexts/ArrayLengthLimiter.cs.meta new file mode 100644 index 0000000..cc204ad --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/Contexts/ArrayLengthLimiter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a68cc45597be044cea672f74433bf542 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/Contexts/_TypeDeserializationContext.cs b/Assets/ARDK/Utilities/BinarySerialization/Contexts/_TypeDeserializationContext.cs new file mode 100644 index 0000000..f742f93 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/Contexts/_TypeDeserializationContext.cs @@ -0,0 +1,50 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.IO; + +using Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers; + +namespace Niantic.ARDK.Utilities.BinarySerialization.Contexts +{ + internal sealed class _TypeDeserializationContext + { + private readonly List _itemDeserializers = new List(); + + internal IItemSerializer _DeserializeTypeAndGetItemDeserializer( + BinaryDeserializer deserializer, + UInt32 id) + { + // 0 is magic value for null, 1 is magic value for new type. 2+ means already known type. + if (id == 1) + return _LoadNewType(deserializer); + + Int32 index = checked((Int32)id) - 2; + if (index < 0 || index >= _itemDeserializers.Count) + throw new IOException("Stream contained invalid type index."); + + return _itemDeserializers[index]; + } + + private IItemSerializer _LoadNewType(BinaryDeserializer deserializer) + { + string typeName = StringSerializer.Instance.Deserialize(deserializer); + + IItemSerializer result; + GlobalSerializer._itemSerializersByTypeName.TryGetValue(typeName, out result); + + if (result == null) + { + string message = + "Couldn't find an item deserializer for type " + typeName + + ", which is in the serialization data."; + + throw new IOException(message); + } + + _itemDeserializers.Add(result); + return result; + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/Contexts/_TypeDeserializationContext.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/Contexts/_TypeDeserializationContext.cs.meta new file mode 100644 index 0000000..9793ef1 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/Contexts/_TypeDeserializationContext.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f777b04aa3d3a4ac19253bec6afc0690 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/Contexts/_TypeSerializationContext.cs b/Assets/ARDK/Utilities/BinarySerialization/Contexts/_TypeSerializationContext.cs new file mode 100644 index 0000000..8c43f8b --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/Contexts/_TypeSerializationContext.cs @@ -0,0 +1,30 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; + +using Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers; + +namespace Niantic.ARDK.Utilities.BinarySerialization.Contexts +{ + internal sealed class _TypeSerializationContext + { + private readonly Dictionary _itemSerializers = + new Dictionary(_ReferenceComparer.Instance); + + internal void _SerializeType(BinarySerializer serializer, Type type, string serializationName) + { + UInt32 id; + if (_itemSerializers.TryGetValue(type, out id)) + { + CompressedUInt32Serializer.Instance.Serialize(serializer, id); + return; + } + + // Magic numbers: 0 = null. 1 = sending type info for the first time. 2+ = existing types. + _itemSerializers.Add(type, (UInt32)(_itemSerializers.Count + 2)); + CompressedUInt32Serializer.Instance.Serialize(serializer, 1); + StringSerializer.Instance.Serialize(serializer, serializationName); + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/Contexts/_TypeSerializationContext.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/Contexts/_TypeSerializationContext.cs.meta new file mode 100644 index 0000000..6e4d291 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/Contexts/_TypeSerializationContext.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6afbaf039bca54f1eae0bcf614a7d68c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/GlobalSerializer.cs b/Assets/ARDK/Utilities/BinarySerialization/GlobalSerializer.cs new file mode 100644 index 0000000..eef929b --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/GlobalSerializer.cs @@ -0,0 +1,415 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Concurrent; +using System.Collections.ObjectModel; +using System.IO; +using System.Reflection; + +using Niantic.ARDK.AR.Anchors; +using Niantic.ARDK.AR.Configuration; +using Niantic.ARDK.AR.Awareness.Depth; +using Niantic.ARDK.AR.Awareness.Semantics; +using Niantic.ARDK.AR.Image; +using Niantic.ARDK.AR.SLAM; +using Niantic.ARDK.Networking.HLAPI.Authority; +using Niantic.ARDK.Networking.HLAPI.Object.Unity; +using Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers; +using Niantic.ARDK.Utilities.Logging; + +using Unity.Collections; + +using SpawnMessage = Niantic.ARDK.Networking.HLAPI.Object.Unity.NetworkSpawner.SpawnMessage; + +namespace Niantic.ARDK.Utilities.BinarySerialization +{ + /// + /// This static class manages all individual "item serializers" for types. This way, we have + /// a single point in our application to serialize data, any data, in a binary format. + /// This global serializer allows item-serializers to be mapped to types that are otherwise + /// non-serializable (that is, types don't need to have the [Serializable] or implement any + /// interface to be able to be serialized by using this class/framework). + /// + public static class GlobalSerializer + { + // We use locks just on write, as we update two ConcurrentDictionaries together. + // On reads, the ConcurrentDictionary allows for lock-free access. + private static readonly object _itemSerializersLock = new object(); + + internal static readonly + ConcurrentDictionary _itemSerializersByTypeName = + new ConcurrentDictionary(); + + internal struct _SerializerInfo + { + internal _SerializerInfo(IItemSerializer serializer, string serializationName) + { + _serializer = serializer; + _serializationName = serializationName; + } + + internal readonly IItemSerializer _serializer; + internal readonly string _serializationName; + } + + internal static readonly ConcurrentDictionary _itemSerializers = + new ConcurrentDictionary(_ReferenceComparer.Instance); + + /// + /// Registers all the "default" serializers supported by this framework. + /// + static GlobalSerializer() + { + ARLog._Debug("Initializing static GlobalSerializer."); + + RegisterItemSerializer(BooleanSerializer.Instance, "2", false); + RegisterItemSerializer(BooleanArraySerializer.Instance, "3", false, false); + RegisterItemSerializer(ByteSerializer.Instance, "b", false); + RegisterItemSerializer(ByteArraySerializer.Instance, "b+", false, false); + RegisterItemSerializer(SByteSerializer.Instance, "-b", false); + RegisterItemSerializer(ArrayOfUnsealedSerializer.Instance, "o+", false); + RegisterItemSerializer(CompressedInt64Serializer.Instance, "i64"); + RegisterItemSerializer(CompressedUInt64Serializer.Instance, "ui64"); + RegisterItemSerializer(CompressedInt32Serializer.Instance, "i32"); + RegisterItemSerializer(CompressedUInt32Serializer.Instance, "ui32"); + RegisterItemSerializer(Int16Serializer.Instance, "i16"); + RegisterItemSerializer(UInt16Serializer.Instance, "ui16"); + RegisterItemSerializer(IntPtrSerializer.Instance, "iptr"); + RegisterItemSerializer(FloatSerializer.Instance, "f"); + RegisterItemSerializer(DoubleSerializer.Instance, "d"); + RegisterItemSerializer(GuidSerializer.Instance, "g"); + RegisterItemSerializer(ResolutionSerializer.Instance, "r"); + RegisterItemSerializer(Vector2Serializer.Instance, "v2"); + RegisterItemSerializer(Vector3Serializer.Instance, "v3"); + RegisterItemSerializer(Vector4Serializer.Instance, "v4"); + RegisterItemSerializer(QuaternionSerializer.Instance, "q"); + RegisterItemSerializer(Matrix4x4Serializer.Instance, "m4x4"); + RegisterItemSerializer(CameraIntrinsicsSerializer.Instance, "ci"); + RegisterItemSerializer(StringSerializer.Instance, "s"); + RegisterItemSerializer(ColorSerializer.Instance, "c"); + RegisterItemSerializer(NetworkIdSerializer.Instance, "NId"); + RegisterItemSerializer(NativeArraySerializer.Instance, "naf"); + RegisterItemSerializer(NativeArraySerializer.Instance, "nai16"); + + RegisterItemSerializer(_SerializableImagePlaneSerializer._instance); + RegisterItemSerializer(_SerializableImageBufferSerializer._instance); + RegisterItemSerializer(_SerializableDepthBufferSerializer._instance); + RegisterItemSerializer(_SerializableSemanticBufferSerializer._instance); + + // We use the same serializer for Native and Serializable configurations, in a way that the + // application doesn't know if it is native or not. But, to make a Serializable one be + // deserialized as a native one, we need to register them with the same name, that's why + // we explicitly specify a name that doesn't include either Native or Serializable. + RegisterItemSerializer + ( + _ARWorldTrackingConfigurationSerializer._instance, + "Niantic.ARDK.AR.Configuration.WorldConfiguration" + ); + + // TODO: Write specific serializer for performance. + var spawnMessageSerializer = SimpleSerializableSerializer.Instance; + RegisterItemSerializer(spawnMessageSerializer); + + + var networkIdAndDataSerializer = + SimpleSerializableSerializer.Instance; + + RegisterItemSerializer(networkIdAndDataSerializer); + + + var networkGroupDataSerializer = + SimpleSerializableSerializer.Instance; + + RegisterItemSerializer(networkGroupDataSerializer); + + + var packedTransformSerializer = + SimpleSerializableSerializer.Instance; + + RegisterItemSerializer(packedTransformSerializer); + + + var roleSerializer = EnumSerializer.ForType(); + RegisterItemSerializer(roleSerializer); + + // We only need to explicitly register those types that we serialize as arrays. + // Unfortunately, we can't use reflection on iOS to find the array serializers for + // those. All the other non-arrays for enums and [Serializable] are registered + // automatically. + RegisterItemSerializer(SimpleSerializableSerializer<_SerializableARMap>.Instance); + RegisterItemSerializer(SimpleSerializableSerializer<_SerializableARBasicAnchor>.Instance); + RegisterItemSerializer(SimpleSerializableSerializer<_SerializableARImageAnchor>.Instance); + RegisterItemSerializer(SimpleSerializableSerializer<_SerializableARPlaneAnchor>.Instance); + + RegisterItemSerializer(ArraySerializer.Instance, null, false, false); + + RegisterItemSerializer + ( + SimpleSerializableSerializer>.Instance, + null, + false, + false + ); + + RegisterItemSerializer(ArraySerializer<_SerializableARAnchor>.Instance, null, false, false); + + RegisterItemSerializer + ( + SimpleSerializableSerializer>.Instance, + null, + false, + false + ); + + RegisterItemSerializer(ArraySerializer.Instance, null, false, false); + + RegisterItemSerializer + ( + SimpleSerializableSerializer>.Instance, + null, + false, + false + ); + + // Register all "default serializers" for enums and [Serializable] types. + var assembly = Assembly.GetExecutingAssembly(); + EnumSerializer.RegisterSerializerForAllEnumsOf(assembly); + SimpleSerializableSerializer.RegisterSerializerForAllSimpleSerializablesOf(assembly); + + ARLog._Debug("Finished initialization of static GlobalSerializer."); + } + + /// + /// Registers the given item-serializer, optionally allowing to use a different "serialization + /// name" and to tell if the default array serializer should be used for this type (by default, + /// the arrays are always registered for any given type). + /// + /// + /// This method is *not* thread-safe and is supposed to be called only during the initialization + /// of the application, before any serialization or deserialization takes place. + /// + public static void RegisterItemSerializer + ( + IItemSerializer itemSerializer, + string serializationName = null, + bool registerDefaultArraySerializerOfT = true, + bool registerDefaultReadOnlyCollectionOfT = true + ) + { + if (itemSerializer == null) + throw new ArgumentNullException(nameof(itemSerializer)); + + ARLog._Debug("Registering ItemSerializer<" + typeof(T).FullName + ">."); + + var untypedItemSerializer = itemSerializer as IItemSerializer; + if (untypedItemSerializer == null) + { + string msg = "All item serializers should also implement the non-generic IItemSerializer."; + throw new ArgumentException(msg, nameof(itemSerializer)); + } + + if (untypedItemSerializer.DataType != typeof(T)) + { + string msg = + "The generic argument of the type-serializer must match the type returned by the " + + "DataType property."; + + throw new ArgumentException(msg, nameof(itemSerializer)); + } + + RegisterUntypedItemSerializer(untypedItemSerializer, serializationName); + + if (registerDefaultArraySerializerOfT || registerDefaultReadOnlyCollectionOfT) + { + if (serializationName == null) + serializationName = typeof(T).FullName; + + // Originally, the call was like this: + // RegisterItemSerializer(ArraySerializer.Instance, serializationName + "+", false); + // But it was crashing on iOS when trying to run any RegisterItemSerializer. + // I thought generic methods didn't work with IL2Cpp, but the truth is that the recursivity + // didn't, even though I am not using the exact same type. Not sure what happens there, + // but it is clearly a bug of IL2Cpp and only happens at run-time. + // So, now we invoke the RegisterUntypedItemSerializer and everything works. + + if (registerDefaultArraySerializerOfT) + { + var untypedArraySerializer = (IItemSerializer)ArraySerializer.Instance; + RegisterUntypedItemSerializer(untypedArraySerializer, serializationName + "+"); + } + + if (registerDefaultReadOnlyCollectionOfT) + { + var untypedReadOnlyCollectionSerializer = + (IItemSerializer)SimpleSerializableSerializer>.Instance; + + string name = "ROC<" + serializationName + ">"; + RegisterUntypedItemSerializer(untypedReadOnlyCollectionSerializer, name); + } + } + } + + public static void RegisterUntypedItemSerializer + ( + IItemSerializer untypedItemSerializer, + string serializationName = null + ) + { + if (untypedItemSerializer == null) + throw new ArgumentNullException(nameof(untypedItemSerializer)); + + var dataType = untypedItemSerializer.DataType; + if (dataType == null) + throw new ArgumentException("Serializer DataType is null.", nameof(untypedItemSerializer)); + + ARLog._Debug("Registering untyped item-serializer for " + dataType.FullName + "."); + + if (dataType.IsAbstract) + throw new ArgumentException(dataType.FullName + " is abstract.", "dataType"); + + if (serializationName == null) + serializationName = dataType.FullName; + + var info = new _SerializerInfo(untypedItemSerializer, serializationName); + lock(_itemSerializersLock) + { + if (_itemSerializers.ContainsKey(dataType)) + { + string msg = + "An item serializer for type " + dataType.FullName + " has already been registered."; + + throw new InvalidOperationException(msg); + } + + if (_itemSerializersByTypeName.ContainsKey(serializationName)) + { + string msg = + "There's an item serializer already registered for a different type that is also " + + "named: " + serializationName + "."; + + throw new InvalidOperationException(msg); + } + + _itemSerializers.TryAdd(dataType, info); + _itemSerializersByTypeName.TryAdd(serializationName, untypedItemSerializer); + } + } + + /// + /// Gets the item serializer for the given type, or returns null if a serializer for that type + /// is not found. + /// + public static IItemSerializer TryGetItemSerializer(Type dataType) + { + if (dataType == null) + throw new ArgumentNullException(nameof(dataType)); + + _SerializerInfo info; + if (!_itemSerializers.TryGetValue(dataType, out info)) + { + ARLog._Debug("Item serializer for " + dataType.FullName + " not found."); + return null; + } + + return info._serializer; + } + + /// + /// Gets the item serializer for the generic type T, or returns null if a serializer for that + /// type is not found. + /// This method is particularly useful if users don't have direct access to the item-serializer + /// for the type they plan to serialize, and such type is a struct. By first getting the item + /// serializer, and using it to serialize the values, serializing the type-information is + /// skipped, and there's no boxing. + /// Note that if the type is class/reference type, it might still be preferable to use the + /// Serialize() method if it is possible the value is null, as item serializers can't deal with + /// null values. + /// + public static IItemSerializer TryGetItemSerializer() + { + _SerializerInfo info; + if (!_itemSerializers.TryGetValue(typeof(T), out info)) + return null; + + var typedResult = info._serializer as IItemSerializer; + if (typedResult == null) + { + typedResult = new _UntypedToTypedSerializerAdapter(info._serializer); + + // When we get a typed-serializer from an untyped one, we actually replace the existing + // registration, so now we don't need to reinstantiate an adapter every time. + info = new _SerializerInfo((IItemSerializer)typedResult, info._serializationName); + _itemSerializers[typeof(T)] = info; + + ARLog._Debug("Replaced untyped serializer for " + typeof(T).FullName + " by a typed one."); + } + + return typedResult; + } + + /// + /// Gets the untyped item-serializer for the given run-time type, or throws an + /// InvalidOperationException if there's no serializer for the given type. + /// + public static IItemSerializer GetItemSerializerOrThrow(Type type) + { + var result = TryGetItemSerializer(type); + + if (result == null) + { + string msg = "Couldn't get item serializer for " + type.FullName + "."; + throw new InvalidOperationException(msg); + } + + return result; + } + + /// + /// Gets the item-serializer for the generic type T, or throws an InvalidOperationException if + /// there's no serializer for such a type. + /// + public static IItemSerializer GetItemSerializerOrThrow() + { + var result = TryGetItemSerializer(); + + if (result == null) + { + string msg = "Couldn't get item serializer for " + typeof(T).FullName + "."; + throw new InvalidOperationException(msg); + } + + return result; + } + + /// + /// Serializes the given object (including null) into the given stream, or throws if a + /// serializer for the given type of any of its members is not found. + /// + /// Required. The stream where the data will be serialized. + /// + /// Can be null. The item to serialize. null value is a valid item to serialize. + /// + public static void Serialize(Stream stream, object item) + { + if (stream == null) + throw new ArgumentNullException(nameof(stream)); + + using(var binarySerializer = new BinarySerializer(stream)) + binarySerializer.Serialize(item); + } + + /// + /// Deserializes an object from the given stream. + /// This method can very easily throw if the stream is corrupted, references an unregistered + /// type or similar. + /// + public static object Deserialize(Stream stream) + { + if (stream == null) + throw new ArgumentNullException(nameof(stream)); + + using(var binaryDeserializer = new BinaryDeserializer(stream)) + return binaryDeserializer.Deserialize(); + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/Utilities/BinarySerialization/GlobalSerializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/GlobalSerializer.cs.meta new file mode 100644 index 0000000..45df7e4 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/GlobalSerializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cb67c8061d1a74190ae288ce5624dd0d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/IItemSerializer.cs b/Assets/ARDK/Utilities/BinarySerialization/IItemSerializer.cs new file mode 100644 index 0000000..64b5f23 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/IItemSerializer.cs @@ -0,0 +1,65 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.IO; + +namespace Niantic.ARDK.Utilities.BinarySerialization +{ + /// + /// Represents an "untyped" serializer for an item of a specific type, which can be registered + /// in the GlobalSerializer class. + /// + public interface IItemSerializer + { + /// + /// Gets the data-type this item serializer is capable of serializing and deserializing. + /// + Type DataType { get; } + + /// + /// Serializes the given object into the stream of the given "generic purpose" serializer. + /// To avoid any confusion, this item-serializer only knows how to serialize a single type, + /// while the serializer given as argument is the one invoking this item serializer, but + /// might be used if to serialize the current item, items of different types need to be + /// serialized. + /// Example: To serialize a Vector3, we also need to serialize 3 floats, the the + /// BinarySerializer can help the Vector3Serializer to do this. + /// + void Serialize(BinarySerializer serializer, object item); + + /// + /// Deserializes an item. The given BinarySerializer is the one calling this item deserializer + /// and can be used if the current item-serializer needs to deserialize data of other types + /// before being able to provide the final item. + /// + object Deserialize(BinaryDeserializer deserializer); + } + + /// + /// Represents a typed serializer for items of the generic type T. + /// All implementations of this interface should also implement the non-generic (untyped) + /// interface. This interface doesn't depend on the other one directly so users of this interface + /// will not see the untyped methods (avoiding possible calls to Serialize() giving objects of + /// the wrong type). + /// + public interface IItemSerializer + { + /// + /// Serializes the given object into the stream of the given "generic purpose" serializer. + /// To avoid any confusion, this item-serializer only knows how to serialize a single type, + /// while the serializer given as argument is the one invoking this item serializer, but + /// might be used if to serialize the current item, items of different types need to be + /// serialized. + /// Example: To serialize a Vector3, we also need to serialize 3 floats, the the + /// BinarySerializer can help the Vector3Serializer to do this. + /// + void Serialize(BinarySerializer serializer, T item); + + /// + /// Deserializes an item. The given BinarySerializer is the one calling this item deserializer + /// and can be used if the current item-serializer needs to deserialize data of other types + /// before being able to provide the final item. + /// + T Deserialize(BinaryDeserializer deserializer); + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/IItemSerializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/IItemSerializer.cs.meta new file mode 100644 index 0000000..755862d --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/IItemSerializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 36273ec1515a5490aa064679547fd82e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/ISerializationContext.cs b/Assets/ARDK/Utilities/BinarySerialization/ISerializationContext.cs new file mode 100644 index 0000000..a458974 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ISerializationContext.cs @@ -0,0 +1,16 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.IO; + +namespace Niantic.ARDK.Utilities.BinarySerialization +{ + /// + /// Interface used to "mark" a class as a serialization-context, so it can be used + /// in a call to BinarySerializer.GetContext<T>();. + /// Context classes must be default-constructible. + /// + public interface ISerializationContext + { + } +} \ No newline at end of file diff --git a/Assets/ARDK/Utilities/BinarySerialization/ISerializationContext.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/ISerializationContext.cs.meta new file mode 100644 index 0000000..916b1a0 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ISerializationContext.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 71cd81cdddb084f82817c5580bbe59dc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers.meta b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers.meta new file mode 100644 index 0000000..086209c --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0f86221adbaf74f9198951163414242d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ArrayOfSealedSerializer.cs b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ArrayOfSealedSerializer.cs new file mode 100644 index 0000000..1d6da66 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ArrayOfSealedSerializer.cs @@ -0,0 +1,101 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.IO; + +using Niantic.ARDK.Utilities.Extensions; +using Niantic.ARDK.Utilities.BinarySerialization.Contexts; +using Niantic.ARDK.Utilities.Collections; + +namespace Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers +{ + // Serializer for types that are sealed. + // This serializer does a single search for the item serializer, and reuses it for all items. + // This only works for sealed types, as array of non-sealed types might actually have objects of + // sub-classes, requiring new searches. + public sealed class ArrayOfSealedSerializer: + BaseItemSerializer + { + public static readonly ArrayOfSealedSerializer Instance = new ArrayOfSealedSerializer(); + + static ArrayOfSealedSerializer() + { + if (!typeof(T).IsSealed) + throw new InvalidOperationException("This serializer only supports sealed types."); + } + + private ArrayOfSealedSerializer() + { + } + + protected override void DoSerialize(BinarySerializer serializer, T[] array) + { + int length = array.Length; + + var arrayLengthLimiter = serializer.GetContext(); + arrayLengthLimiter.ReserveOrThrow(length); + CompressedUInt32Serializer.Instance.Serialize(serializer, (UInt32)length); + + if (length == 0) + return; + + var itemSerializer = GlobalSerializer.GetItemSerializerOrThrow(); + if (typeof(T).IsValueType) + { + // Value types can't be null. + foreach (T item in array) + itemSerializer.Serialize(serializer, item); + } + else + { + foreach (T item in array) + { + bool hasItem = item != null; + BooleanSerializer.Instance.Serialize(serializer, hasItem); + + if (hasItem) + itemSerializer.Serialize(serializer, item); + } + } + } + + protected override T[] DoDeserialize(BinaryDeserializer deserializer) + { + UInt32 unsignedLength = CompressedUInt32Serializer.Instance.Deserialize(deserializer); + if (unsignedLength == 0) + return EmptyArray.Instance; + + Int32 length = checked((Int32)unsignedLength); + var arrayLengthLimiter = deserializer.GetContext(); + arrayLengthLimiter.ReserveOrThrow(length); + + var itemSerializer = GlobalSerializer.GetItemSerializerOrThrow(); + + T[] result = new T[length]; + + // Value types can't be null, so we avoid such a check. + if (typeof(T).IsValueType) + { + for (int i = 0; i < length; i++) + { + T item = itemSerializer.Deserialize(deserializer); + result[i] = item; + } + } + else + { + for (int i = 0; i < length; i++) + { + bool hasItem = BooleanSerializer.Instance.Deserialize(deserializer); + if (hasItem) + { + T item = itemSerializer.Deserialize(deserializer); + result[i] = item; + } + } + } + + return result; + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ArrayOfSealedSerializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ArrayOfSealedSerializer.cs.meta new file mode 100644 index 0000000..26d8826 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ArrayOfSealedSerializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8d6a8268bd0254a6cafbb953357a454d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ArrayOfUnsealedSerializer.cs b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ArrayOfUnsealedSerializer.cs new file mode 100644 index 0000000..c47a3cc --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ArrayOfUnsealedSerializer.cs @@ -0,0 +1,61 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.Utilities.Extensions; +using Niantic.ARDK.Utilities.BinarySerialization.Contexts; +using Niantic.ARDK.Utilities.Collections; + +namespace Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers +{ + public sealed class ArrayOfUnsealedSerializer: + BaseItemSerializer + { + public static readonly ArrayOfUnsealedSerializer Instance = + new ArrayOfUnsealedSerializer(); + + private const string _errorMessageUnsealedTypesOnly = + "This serializer is for unsealed types only. Use the ArrayOfSealedSerializer instead."; + + static ArrayOfUnsealedSerializer() + { + if (typeof(T).IsSealed) + throw new Exception(_errorMessageUnsealedTypesOnly); + } + + private ArrayOfUnsealedSerializer() + { + } + + protected override void DoSerialize(BinarySerializer serializer, T[] array) + { + int length = array.Length; + + var arrayLengthLimiter = serializer.GetContext(); + arrayLengthLimiter.ReserveOrThrow(length); + CompressedUInt32Serializer.Instance.Serialize(serializer, (UInt32)length); + + foreach (T item in array) + serializer.Serialize(item); + } + + protected override T[] DoDeserialize(BinaryDeserializer deserializer) + { + UInt32 unsignedLength = CompressedUInt32Serializer.Instance.Deserialize(deserializer); + if (unsignedLength == 0) + return EmptyArray.Instance; + + Int32 length = checked((Int32)unsignedLength); + var arrayLengthLimiter = deserializer.GetContext(); + arrayLengthLimiter.ReserveOrThrow(length); + + T[] result = new T[length]; + for (int i = 0; i < length; i++) + { + T item = (T)deserializer.Deserialize(); + result[i] = item; + } + return result; + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ArrayOfUnsealedSerializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ArrayOfUnsealedSerializer.cs.meta new file mode 100644 index 0000000..335bf55 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ArrayOfUnsealedSerializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7bab4983a41f543ce8c8b1efff906fcd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ArraySerializer.cs b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ArraySerializer.cs new file mode 100644 index 0000000..85204c6 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ArraySerializer.cs @@ -0,0 +1,17 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers +{ + public static class ArraySerializer + { + public static readonly IItemSerializer Instance; + + static ArraySerializer() + { + if (typeof(T).IsSealed) + Instance = ArrayOfSealedSerializer.Instance; + else + Instance = ArrayOfUnsealedSerializer.Instance; + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ArraySerializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ArraySerializer.cs.meta new file mode 100644 index 0000000..4244bdf --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ArraySerializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: af9e8894a89d64aa3bfa2fe99a2ad7c0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/BaseItemSerializer.cs b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/BaseItemSerializer.cs new file mode 100644 index 0000000..4e34f6c --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/BaseItemSerializer.cs @@ -0,0 +1,78 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +namespace Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers +{ + /// + /// Class used to implement the untyped IItemSerializer and the typed IItemSerializer<T> + /// the right way. This class should be used only as a base-class to implement a new serializer + /// but any method that requires a serializer should ask only for the interfaces, be it the + /// typed or the untyped version. + /// + public abstract class BaseItemSerializer: + IItemSerializer, IItemSerializer + { + /// + /// Implements the IItemSerializer<T>.Serialize() method. + /// + public void Serialize(BinarySerializer serializer, T item) + { + if (serializer == null) + throw new ArgumentNullException(nameof(serializer)); + + if (item == null) + throw new ArgumentNullException(nameof(item)); + + DoSerialize(serializer, item); + } + + private const string _errorMessageGotNull = + "The ItemSerializer.Deserialize() returned null. This shouldn't happen."; + + /// + /// Implements the IItemSerializer<T>.Deserialize() method. + /// + public T Deserialize(BinaryDeserializer deserializer) + { + if (deserializer == null) + throw new ArgumentNullException(nameof(deserializer)); + + T result = DoDeserialize(deserializer); + if (result == null) + throw new InvalidOperationException(_errorMessageGotNull); + + return result; + } + + /// + /// Method that sub-classes need to override to provide the actual serialization for item. + /// There's no need to check if either serializer or item are null, as this is done by the + /// Serialize() method. + /// + protected abstract void DoSerialize(BinarySerializer serializer, T item); + + /// + /// Method that sub-classes need to override to provide the actual deserialization logic. + /// There's no need to check if either deserializer is nuyll as this is done by the + /// Deserialize() method. + /// + protected abstract T DoDeserialize(BinaryDeserializer deserializer); + + Type IItemSerializer.DataType + { + get + { + return typeof(T); + } + } + void IItemSerializer.Serialize(BinarySerializer serializer, object item) + { + Serialize(serializer, (T)item); + } + object IItemSerializer.Deserialize(BinaryDeserializer deserializer) + { + return Deserialize(deserializer); + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/BaseItemSerializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/BaseItemSerializer.cs.meta new file mode 100644 index 0000000..e635215 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/BaseItemSerializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 165999427f7054141ac1b9e946092ca3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/BooleanArraySerializer.cs b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/BooleanArraySerializer.cs new file mode 100644 index 0000000..db825d3 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/BooleanArraySerializer.cs @@ -0,0 +1,88 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.IO; + +using Niantic.ARDK.Utilities.Extensions; +using Niantic.ARDK.Utilities.BinarySerialization.Contexts; +using Niantic.ARDK.Utilities.Collections; + +namespace Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers +{ + public sealed class BooleanArraySerializer: + BaseItemSerializer + { + public static readonly BooleanArraySerializer Instance = new BooleanArraySerializer(); + + private BooleanArraySerializer() + { + } + + protected override void DoSerialize(BinarySerializer serializer, bool[] item) + { + var length = item.Length; + + var arrayLengthLimiter = serializer.GetContext(); + arrayLengthLimiter.ReserveOrThrow((length+7) / 8); + CompressedUInt32Serializer.Instance.Serialize(serializer, (UInt32)length); + + var stream = serializer.Stream; + byte b = 0; + int shift = 7; + for (int i = 0; i < length; i++) + { + if (item[i]) + b |= (byte)(1 << shift); + + if (shift != 0) + shift--; + else + { + shift = 7; + stream.WriteByte(b); + b = 0; + } + } + + if (shift != 7) + stream.WriteByte(b); + } + protected override bool[] DoDeserialize(BinaryDeserializer deserializer) + { + UInt32 unsignedLength = CompressedUInt32Serializer.Instance.Deserialize(deserializer); + if (unsignedLength == 0) + return EmptyArray.Instance; + + Int32 length = checked((Int32)unsignedLength); + var arrayLengthLimiter = deserializer.GetContext(); + arrayLengthLimiter.ReserveOrThrow((length+7) / 8); + + var stream = deserializer.Stream; + bool[] result = new bool[length]; + for (int i = 0; i < length; i += 8) + { + byte b = stream.ReadByteOrThrow(); + + _SetValue(result, b >> 7, i); + _SetValue(result, b >> 6, i + 1); + _SetValue(result, b >> 5, i + 2); + _SetValue(result, b >> 4, i + 3); + _SetValue(result, b >> 3, i + 4); + _SetValue(result, b >> 2, i + 5); + _SetValue(result, b >> 1, i + 6); + _SetValue(result, b, i + 7); + } + + return result; + } + + private static void _SetValue(bool[] array, int value, int index) + { + // We don't check if index is bigger than the length of the array because the + // values for the last byte (if length is not multiple of 8) should be 0 for non-existing + // indexes. And, if it is not (which is an error) .NET will throw. + if ((value & 1) == 1) + array[index] = true; + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/BooleanArraySerializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/BooleanArraySerializer.cs.meta new file mode 100644 index 0000000..bb79144 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/BooleanArraySerializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 94fdff00ae758478b9ab18c20e6ea79a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/BooleanSerializer.cs b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/BooleanSerializer.cs new file mode 100644 index 0000000..c18f2c3 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/BooleanSerializer.cs @@ -0,0 +1,36 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.IO; + +using Niantic.ARDK.Utilities.Extensions; + +namespace Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers +{ + public sealed class BooleanSerializer: + BaseItemSerializer + { + public static readonly BooleanSerializer Instance = new BooleanSerializer(); + + private BooleanSerializer() + { + } + + protected override void DoSerialize(BinarySerializer serializer, bool item) + { + byte b = item ? (byte)1 : (byte)0; + serializer.Stream.WriteByte(b); + } + protected override bool DoDeserialize(BinaryDeserializer deserializer) + { + byte b = deserializer.Stream.ReadByteOrThrow(); + + switch(b) + { + case 0: return false; + case 1: return true; + default: throw new IOException("Invalid boolean value in stream."); + } + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/BooleanSerializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/BooleanSerializer.cs.meta new file mode 100644 index 0000000..d30aa75 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/BooleanSerializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1410432371fe9404aaafc87369b1e102 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ByteArraySerializer.cs b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ByteArraySerializer.cs new file mode 100644 index 0000000..e5eb384 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ByteArraySerializer.cs @@ -0,0 +1,47 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.IO; + +using Niantic.ARDK.Utilities.Extensions; +using Niantic.ARDK.Utilities.BinarySerialization.Contexts; +using Niantic.ARDK.Utilities.Collections; + +namespace Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers +{ + public sealed class ByteArraySerializer: + BaseItemSerializer + { + public static readonly ByteArraySerializer Instance = new ByteArraySerializer(); + + private ByteArraySerializer() + { + } + + protected override void DoSerialize(BinarySerializer serializer, byte[] item) + { + int length = item.Length; + + var arrayLengthLimiter = serializer.GetContext(); + arrayLengthLimiter.ReserveOrThrow(length); + + CompressedUInt32Serializer.Instance.Serialize(serializer, (UInt32)length); + serializer.Stream.Write(item, 0, item.Length); + } + + protected override byte[] DoDeserialize(BinaryDeserializer deserializer) + { + UInt32 unsignedLength = CompressedUInt32Serializer.Instance.Deserialize(deserializer); + if (unsignedLength == 0) + return EmptyArray.Instance; + + Int32 length = checked((Int32)unsignedLength); + var arrayLengthLimiter = deserializer.GetContext(); + arrayLengthLimiter.ReserveOrThrow(length); + + byte[] result = new byte[length]; + deserializer.Stream.ReadOrThrow(result, 0, length); + return result; + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ByteArraySerializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ByteArraySerializer.cs.meta new file mode 100644 index 0000000..5042046 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ByteArraySerializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0da4498dc865c4f279df8b0b9b460a09 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ByteSerializer.cs b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ByteSerializer.cs new file mode 100644 index 0000000..10e54ad --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ByteSerializer.cs @@ -0,0 +1,27 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.Utilities.Extensions; + +namespace Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers +{ + public sealed class ByteSerializer: + BaseItemSerializer + { + public static readonly ByteSerializer Instance = new ByteSerializer(); + + private ByteSerializer() + { + } + + protected override void DoSerialize(BinarySerializer serializer, byte item) + { + serializer.Stream.WriteByte(item); + } + protected override byte DoDeserialize(BinaryDeserializer deserializer) + { + return deserializer.Stream.ReadByteOrThrow(); + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ByteSerializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ByteSerializer.cs.meta new file mode 100644 index 0000000..8c8ba8d --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ByteSerializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0d903d27bfd0742c7aa50dc52bd0af75 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/CameraIntrinsicsSerializer.cs b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/CameraIntrinsicsSerializer.cs new file mode 100644 index 0000000..2ec6092 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/CameraIntrinsicsSerializer.cs @@ -0,0 +1,28 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.AR.Camera; + +namespace Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers +{ + public sealed class CameraIntrinsicsSerializer: + BaseItemSerializer + { + public static readonly CameraIntrinsicsSerializer Instance = new CameraIntrinsicsSerializer(); + + private CameraIntrinsicsSerializer() + { + } + + protected override void DoSerialize(BinarySerializer serializer, CameraIntrinsics item) + { + Vector2Serializer.Instance.Serialize(serializer, item.FocalLength); + Vector2Serializer.Instance.Serialize(serializer, item.PrincipalPoint); + } + protected override CameraIntrinsics DoDeserialize(BinaryDeserializer deserializer) + { + var focalLength = Vector2Serializer.Instance.Deserialize(deserializer); + var principalPoint = Vector2Serializer.Instance.Deserialize(deserializer); + return new CameraIntrinsics(focalLength.x, focalLength.y, principalPoint.x, principalPoint.y); + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/CameraIntrinsicsSerializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/CameraIntrinsicsSerializer.cs.meta new file mode 100644 index 0000000..4c2f8a5 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/CameraIntrinsicsSerializer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 765f0bc84ee5434198435e02049ac544 +timeCreated: 1627501950 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ColorSerializer.cs b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ColorSerializer.cs new file mode 100644 index 0000000..b84978c --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ColorSerializer.cs @@ -0,0 +1,36 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using UnityEngine; + +namespace Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers +{ + + public sealed class ColorSerializer: + BaseItemSerializer + { + public static readonly ColorSerializer Instance = new ColorSerializer(); + + private ColorSerializer() + { + } + + protected override void DoSerialize(BinarySerializer serializer, Color item) + { + var floatSerializer = FloatSerializer.Instance; + floatSerializer.Serialize(serializer, item.r); + floatSerializer.Serialize(serializer, item.g); + floatSerializer.Serialize(serializer, item.b); + floatSerializer.Serialize(serializer, item.a); + } + protected override Color DoDeserialize(BinaryDeserializer deserializer) + { + var floatSerializer = FloatSerializer.Instance; + float r = floatSerializer.Deserialize(deserializer); + float g = floatSerializer.Deserialize(deserializer); + float b = floatSerializer.Deserialize(deserializer); + float a = floatSerializer.Deserialize(deserializer); + return new Color(r, g, b, a); + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ColorSerializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ColorSerializer.cs.meta new file mode 100644 index 0000000..a9c2433 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ColorSerializer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 72462e63e286413f8743124c440194c0 +timeCreated: 1586547346 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/CompressedInt32Serializer.cs b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/CompressedInt32Serializer.cs new file mode 100644 index 0000000..9705dbe --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/CompressedInt32Serializer.cs @@ -0,0 +1,61 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.IO; + +using Niantic.ARDK.Utilities.Extensions; + +namespace Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers +{ + public sealed class CompressedInt32Serializer: + BaseItemSerializer + { + public static readonly CompressedInt32Serializer Instance = new CompressedInt32Serializer(); + + public static Int32 ReadCompressedInt32(Stream stream) + { + UInt32 uint32Value = CompressedUInt32Serializer.ReadCompressedUInt32(stream); + + bool isNegative = (uint32Value & 1) == 1; + uint32Value >>= 1; + + if (isNegative) + uint32Value = ~uint32Value; + + return (Int32)uint32Value; + } + + + /// + /// Writes an Int32 value in "compressed" format. + /// This uses the UInt32 compression logic, with an extra twist. -1 has all bytes set, meaning + /// that if we just want to use the "compression" on it, it will occupy 5 bytes. So, instead, we + /// shift the sign bit to the right and invert all the bits when a value is negative. In this + /// way, the values 0, -1, 1, -2, 2, -3, 3 etc are actually written as 0, 1, 2, 3, 4, 5, 6, + /// keeping just one byte instead of 4 (no compression) or 5 (bad compression for negatives). + /// + public static void WriteCompressedInt32(Stream stream, Int32 value) + { + UInt32 uint32Value = (UInt32)value; + uint32Value <<= 1; + + if (value < 0) + uint32Value = ~uint32Value; + + CompressedUInt32Serializer.WriteCompressedUInt32(stream, uint32Value); + } + + private CompressedInt32Serializer() + { + } + + protected override void DoSerialize(BinarySerializer serializer, Int32 item) + { + WriteCompressedInt32(serializer.Stream, item); + } + protected override Int32 DoDeserialize(BinaryDeserializer deserializer) + { + return ReadCompressedInt32(deserializer.Stream); + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/CompressedInt32Serializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/CompressedInt32Serializer.cs.meta new file mode 100644 index 0000000..ca9ab8e --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/CompressedInt32Serializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 73c2ac1f9c35b4b8fbacabbd5841aa58 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/CompressedInt64Serializer.cs b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/CompressedInt64Serializer.cs new file mode 100644 index 0000000..fe38d0f --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/CompressedInt64Serializer.cs @@ -0,0 +1,60 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.IO; + +using Niantic.ARDK.Utilities.Extensions; + +namespace Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers +{ + public sealed class CompressedInt64Serializer: + BaseItemSerializer + { + public static readonly CompressedInt64Serializer Instance = new CompressedInt64Serializer(); + + public static Int64 ReadCompressedInt64(Stream stream) + { + UInt64 uint64Value = CompressedUInt64Serializer.ReadCompressedUInt64(stream); + + bool isNegative = (uint64Value & 1) == 1; + uint64Value >>= 1; + + if (isNegative) + uint64Value = ~uint64Value; + + return (Int64)uint64Value; + } + + /// + /// Writes an Int64 value in "compressed" format. + /// This uses the UInt64 compression logic, with an extra twist. -1 has all bytes set, meaning + /// that if we just want to use the "compression" on it, it will occupy 10 bytes. So, instead, + /// we shift the sign bit to the right and invert all the bits when a value is negative. In this + /// way, the values 0, -1, 1, -2, 2, -3, 3 etc are actually written as 0, 1, 2, 3, 4, 5, 6, + /// keeping just one byte instead of 4 (no compression) or 10 (bad compression for negatives). + /// + public static void WriteCompressedInt64(Stream stream, Int64 value) + { + UInt64 uint64Value = (UInt64)value; + uint64Value <<= 1; + + if (value < 0) + uint64Value = ~uint64Value; + + CompressedUInt64Serializer.WriteCompressedUInt64(stream, uint64Value); + } + + private CompressedInt64Serializer() + { + } + + protected override void DoSerialize(BinarySerializer serializer, Int64 item) + { + WriteCompressedInt64(serializer.Stream, item); + } + protected override Int64 DoDeserialize(BinaryDeserializer deserializer) + { + return ReadCompressedInt64(deserializer.Stream); + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/CompressedInt64Serializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/CompressedInt64Serializer.cs.meta new file mode 100644 index 0000000..184eb88 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/CompressedInt64Serializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c66595c5b26f243e5a3daeca4273078a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/CompressedUInt32Serializer.cs b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/CompressedUInt32Serializer.cs new file mode 100644 index 0000000..f9cd8b3 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/CompressedUInt32Serializer.cs @@ -0,0 +1,77 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.IO; + +using Niantic.ARDK.Utilities.Extensions; + +namespace Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers +{ + public sealed class CompressedUInt32Serializer: + BaseItemSerializer + { + public static readonly CompressedUInt32Serializer Instance = new CompressedUInt32Serializer(); + + public static UInt32 ReadCompressedUInt32(Stream stream) + { + UInt32 result = 0; + int shiftAmount = 0; + while(true) { + UInt32 read = stream.ReadByteOrThrow(); + + UInt32 readValue = read & ((1 << 7) - 1); + UInt32 shiftedValue = readValue << shiftAmount; + + // Even in checked scopes, bit shifting doesn't throw. So, we check for an overflow by + // making a shifted value be shifted in the opposite direction and comparing to the + // unshifted value. If it is not the same value anymore, that means we had an overflow. + if ((shiftedValue >> shiftAmount) != readValue) + throw new IOException("Overflow when reading compressed int."); + + result |= shiftedValue; + + if ((read >> 7) == 0) + return result; + + shiftAmount += 7; + } + } + + /// + /// Writes an UInt32 value in "compressed" format. + /// Assuming most values are small, we can possibly write a single byte instead of 4 if the + /// value is smaller than 127. To do the "compression", we write 7 bits of the value at a time, + /// and use the last bit to tell if there's more data or not. + /// Unfortunately, in the worst case, we might end-up writing 5 bytes instead of 4. + /// + public static void WriteCompressedUInt32(Stream stream, UInt32 value) + { + while(true) + { + byte b = (byte)value; + value >>= 7; + + if (value > 0) + b |= 1 << 7; + + stream.WriteByte(b); + + if (value == 0) + break; + } + } + + private CompressedUInt32Serializer() + { + } + + protected override void DoSerialize(BinarySerializer serializer, UInt32 item) + { + WriteCompressedUInt32(serializer.Stream, item); + } + protected override UInt32 DoDeserialize(BinaryDeserializer deserializer) + { + return ReadCompressedUInt32(deserializer.Stream); + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/CompressedUInt32Serializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/CompressedUInt32Serializer.cs.meta new file mode 100644 index 0000000..9afed3e --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/CompressedUInt32Serializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 110dd9a47eb8943c7b041f3de1b45d6a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/CompressedUInt64Serializer.cs b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/CompressedUInt64Serializer.cs new file mode 100644 index 0000000..40836aa --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/CompressedUInt64Serializer.cs @@ -0,0 +1,77 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.IO; + +using Niantic.ARDK.Utilities.Extensions; + +namespace Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers +{ + public sealed class CompressedUInt64Serializer: + BaseItemSerializer + { + public static readonly CompressedUInt64Serializer Instance = new CompressedUInt64Serializer(); + + public static UInt64 ReadCompressedUInt64(Stream stream) + { + UInt64 result = 0; + int shiftAmount = 0; + while(true) { + UInt64 read = stream.ReadByteOrThrow(); + + UInt64 readValue = read & ((1 << 7) - 1); + UInt64 shiftedValue = readValue << shiftAmount; + + // Even in checked scopes, bit shifting doesn't throw. So, we check for an overflow by + // making a shifted value be shifted in the opposite direction and comparing to the + // unshifted value. If it is not the same value anymore, that means we had an overflow. + if ((shiftedValue >> shiftAmount) != readValue) + throw new IOException("Overflow when reading compressed int."); + + result |= shiftedValue; + + if ((read >> 7) == 0) + return result; + + shiftAmount += 7; + } + } + + /// + /// Writes an UInt64 value in "compressed" format. + /// Assuming most values are small, we can possibly write a single byte instead of 8 if the + /// value is smaller than 127. To do the "compression", we write 7 bits of the value at a time, + /// and use the last bit to tell if there's more data or not. + /// Unfortunately, in the worst case, we might end-up writing 10 bytes instead of 8. + /// + public static void WriteCompressedUInt64(Stream stream, UInt64 value) + { + while(true) + { + byte b = (byte)value; + value >>= 7; + + if (value > 0) + b |= 1 << 7; + + stream.WriteByte(b); + + if (value == 0) + break; + } + } + + private CompressedUInt64Serializer() + { + } + + protected override void DoSerialize(BinarySerializer serializer, UInt64 item) + { + WriteCompressedUInt64(serializer.Stream, item); + } + protected override UInt64 DoDeserialize(BinaryDeserializer deserializer) + { + return ReadCompressedUInt64(deserializer.Stream); + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/CompressedUInt64Serializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/CompressedUInt64Serializer.cs.meta new file mode 100644 index 0000000..ef2876c --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/CompressedUInt64Serializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fc51ee660ec64445983fb0ef77720182 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/DoubleSerializer.cs b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/DoubleSerializer.cs new file mode 100644 index 0000000..f2d3fbc --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/DoubleSerializer.cs @@ -0,0 +1,67 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.Utilities.Extensions; + +namespace Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers +{ + public sealed class DoubleSerializer: + BaseItemSerializer + { + public static readonly DoubleSerializer Instance = new DoubleSerializer(); + + private DoubleSerializer() + { + } + + protected override void DoSerialize(BinarySerializer serializer, double item) + { + unsafe + { + void* address = &item; + UInt64* uint64Address = (UInt64*)address; + UInt64 value = *uint64Address; + + var stream = serializer.Stream; + stream.WriteByte((byte)(value >> 56)); + stream.WriteByte((byte)(value >> 48)); + stream.WriteByte((byte)(value >> 40)); + stream.WriteByte((byte)(value >> 32)); + stream.WriteByte((byte)(value >> 24)); + stream.WriteByte((byte)(value >> 16)); + stream.WriteByte((byte)(value >> 8)); + stream.WriteByte((byte)value); + } + } + protected override double DoDeserialize(BinaryDeserializer deserializer) + { + var stream = deserializer.Stream; + UInt64 byte1 = stream.ReadByteOrThrow(); + UInt64 byte2 = stream.ReadByteOrThrow(); + UInt64 byte3 = stream.ReadByteOrThrow(); + UInt64 byte4 = stream.ReadByteOrThrow(); + UInt64 byte5 = stream.ReadByteOrThrow(); + UInt64 byte6 = stream.ReadByteOrThrow(); + UInt64 byte7 = stream.ReadByteOrThrow(); + UInt64 byte8 = stream.ReadByteOrThrow(); + + UInt64 uint64Value = + byte1 << 56 | + byte2 << 48 | + byte3 << 40 | + byte4 << 32 | + byte5 << 24 | + byte6 << 16 | + byte7 << 8 | + byte8; + + unsafe + { + void* address = &uint64Value; + double* doubleAddress = (double*)address; + return *doubleAddress; + } + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/DoubleSerializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/DoubleSerializer.cs.meta new file mode 100644 index 0000000..efed31a --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/DoubleSerializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c3382f114b90a48d286e8cee0ccc9354 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/EnumSerializer.cs b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/EnumSerializer.cs new file mode 100644 index 0000000..8428da0 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/EnumSerializer.cs @@ -0,0 +1,107 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Reflection; + +namespace Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers +{ + public sealed class EnumSerializer: + IItemSerializer + { + private static readonly ConcurrentDictionary _enumSerializers = + new ConcurrentDictionary(); + + private static readonly Func _createUntypedSerializerFunc = + (enumType) => + { + if (!enumType.IsEnum) + throw new ArgumentException(enumType.FullName + " is not an enum type.", nameof(enumType)); + + var result = new EnumSerializer(enumType); + return result; + }; + + public static IItemSerializer ForType(Type enumType) + { + if (enumType == null) + throw new ArgumentNullException(nameof(enumType)); + + return _enumSerializers.GetOrAdd(enumType, _createUntypedSerializerFunc); + } + + // Unfortunately, because of the generic type to untyped conversion, we can't use a concurrent + // dictionary here. + private static readonly object _typedSerializersLock = new object(); + private static readonly Dictionary _typedSerializers = + new Dictionary(); + + public static IItemSerializer ForType() + { + lock(_typedSerializersLock) + { + IItemSerializer uncastSerializer; + if (_typedSerializers.TryGetValue(typeof(T), out uncastSerializer)) + return (IItemSerializer)uncastSerializer; + + var untypedSerializer = ForType(typeof(T)); + var typedSerializer = new _UntypedToTypedSerializerAdapter(untypedSerializer); + _typedSerializers.Add(typeof(T), typedSerializer); + return typedSerializer; + } + } + + /// + /// Registers an EnumSerializer instance for each enum type found in the given assembly. + /// + public static void RegisterSerializerForAllEnumsOf(Assembly assembly) + { + if (assembly == null) + throw new ArgumentNullException(nameof(assembly)); + + foreach(var type in assembly.GetTypes()) + { + if (type.IsEnum) + { + var existingSerializer = GlobalSerializer.TryGetItemSerializer(type); + if (existingSerializer == null) + { + var serializer = ForType(type); + GlobalSerializer.RegisterUntypedItemSerializer(serializer); + } + } + } + } + + private readonly Type _enumType; + private readonly Type _underlyingType; + private readonly IItemSerializer _underlyingSerializer; + private EnumSerializer(Type enumType) + { + _enumType = enumType; + _underlyingType = Enum.GetUnderlyingType(_enumType); + _underlyingSerializer = GlobalSerializer.GetItemSerializerOrThrow(_underlyingType); + } + + public Type DataType + { + get + { + return _enumType; + } + } + + public void Serialize(BinarySerializer serializer, object item) + { + var underlyingValue = Convert.ChangeType(item, _underlyingType); + _underlyingSerializer.Serialize(serializer, underlyingValue); + } + public object Deserialize(BinaryDeserializer deserializer) + { + var underlyingValue = _underlyingSerializer.Deserialize(deserializer); + var result = Enum.ToObject(_enumType, underlyingValue); + return result; + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/EnumSerializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/EnumSerializer.cs.meta new file mode 100644 index 0000000..6a8b5ed --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/EnumSerializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 83e7a3f303b7b4985b61c0ffa46a5add +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/FloatSerializer.cs b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/FloatSerializer.cs new file mode 100644 index 0000000..2522160 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/FloatSerializer.cs @@ -0,0 +1,55 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.Utilities.Extensions; + +namespace Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers +{ + public sealed class FloatSerializer: + BaseItemSerializer + { + public static readonly FloatSerializer Instance = new FloatSerializer(); + + private FloatSerializer() + { + } + + protected override void DoSerialize(BinarySerializer serializer, float item) + { + unsafe + { + void* address = &item; + UInt32* uint32Address = (UInt32*)address; + UInt32 value = *uint32Address; + + var stream = serializer.Stream; + stream.WriteByte((byte)(value >> 24)); + stream.WriteByte((byte)(value >> 16)); + stream.WriteByte((byte)(value >> 8)); + stream.WriteByte((byte)value); + } + } + protected override float DoDeserialize(BinaryDeserializer deserializer) + { + var stream = deserializer.Stream; + UInt32 byte1 = stream.ReadByteOrThrow(); + UInt32 byte2 = stream.ReadByteOrThrow(); + UInt32 byte3 = stream.ReadByteOrThrow(); + UInt32 byte4 = stream.ReadByteOrThrow(); + + UInt32 uint32Value = + byte1 << 24 | + byte2 << 16 | + byte3 << 8 | + byte4; + + unsafe + { + void* address = &uint32Value; + float* floatAddress = (float*)address; + return *floatAddress; + } + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/FloatSerializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/FloatSerializer.cs.meta new file mode 100644 index 0000000..1636fb7 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/FloatSerializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a3c6ef8dbff99419f8d16172c8c8d367 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/GuidSerializer.cs b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/GuidSerializer.cs new file mode 100644 index 0000000..9a89086 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/GuidSerializer.cs @@ -0,0 +1,27 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +namespace Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers +{ + public sealed class GuidSerializer: + BaseItemSerializer + { + public static readonly GuidSerializer Instance = new GuidSerializer(); + + private GuidSerializer() + { + } + + protected override void DoSerialize(BinarySerializer serializer, Guid item) + { + var array = item.ToByteArray(); + ByteArraySerializer.Instance.Serialize(serializer, array); + } + protected override Guid DoDeserialize(BinaryDeserializer deserializer) + { + var array = ByteArraySerializer.Instance.Deserialize(deserializer); + return new Guid(array); + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/GuidSerializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/GuidSerializer.cs.meta new file mode 100644 index 0000000..2a5d7ec --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/GuidSerializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bd5e8382a92e1420cb71a4a618f2c40f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/Int16Serializer.cs b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/Int16Serializer.cs new file mode 100644 index 0000000..5057058 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/Int16Serializer.cs @@ -0,0 +1,25 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +namespace Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers +{ + public sealed class Int16Serializer: + BaseItemSerializer + { + public static readonly Int16Serializer Instance = new Int16Serializer(); + + private Int16Serializer() + { + } + + protected override void DoSerialize(BinarySerializer serializer, Int16 item) + { + UInt16Serializer.Instance.Serialize(serializer, (UInt16)item); + } + protected override Int16 DoDeserialize(BinaryDeserializer deserializer) + { + return (Int16)UInt16Serializer.Instance.Deserialize(deserializer); + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/Int16Serializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/Int16Serializer.cs.meta new file mode 100644 index 0000000..23151ae --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/Int16Serializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7271ed13c053f471bba8b64377fc8303 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/IntPtrSerializer.cs b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/IntPtrSerializer.cs new file mode 100644 index 0000000..607efba --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/IntPtrSerializer.cs @@ -0,0 +1,56 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.Utilities.Extensions; + +namespace Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers +{ + public sealed class IntPtrSerializer: + BaseItemSerializer + { + public static readonly IntPtrSerializer Instance = new IntPtrSerializer(); + + private IntPtrSerializer() + { + } + + protected override void DoSerialize(BinarySerializer serializer, IntPtr item) + { + Int64 value = (Int64)item; + var stream = serializer.Stream; + stream.WriteByte((byte)(value >> 56)); + stream.WriteByte((byte)(value >> 48)); + stream.WriteByte((byte)(value >> 40)); + stream.WriteByte((byte)(value >> 32)); + stream.WriteByte((byte)(value >> 24)); + stream.WriteByte((byte)(value >> 16)); + stream.WriteByte((byte)(value >> 8)); + stream.WriteByte((byte)value); + } + protected override IntPtr DoDeserialize(BinaryDeserializer deserializer) + { + var stream = deserializer.Stream; + UInt64 byte1 = stream.ReadByteOrThrow(); + UInt64 byte2 = stream.ReadByteOrThrow(); + UInt64 byte3 = stream.ReadByteOrThrow(); + UInt64 byte4 = stream.ReadByteOrThrow(); + UInt64 byte5 = stream.ReadByteOrThrow(); + UInt64 byte6 = stream.ReadByteOrThrow(); + UInt64 byte7 = stream.ReadByteOrThrow(); + UInt64 byte8 = stream.ReadByteOrThrow(); + + UInt64 result = + byte1 << 56 | + byte2 << 48 | + byte3 << 40 | + byte4 << 32 | + byte5 << 24 | + byte6 << 16 | + byte7 << 8 | + byte8; + + return (IntPtr)result; + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/IntPtrSerializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/IntPtrSerializer.cs.meta new file mode 100644 index 0000000..cf141ed --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/IntPtrSerializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2b1bf216918e84b1cac5a7e88cd8ebd7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/Matrix4x4Serializer.cs b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/Matrix4x4Serializer.cs new file mode 100644 index 0000000..9655228 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/Matrix4x4Serializer.cs @@ -0,0 +1,35 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using UnityEngine; + +namespace Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers +{ + public sealed class Matrix4x4Serializer: + BaseItemSerializer + { + public static readonly Matrix4x4Serializer Instance = new Matrix4x4Serializer(); + + private Matrix4x4Serializer() + { + } + + protected override void DoSerialize(BinarySerializer serializer, Matrix4x4 item) + { + var vector4Serializer = Vector4Serializer.Instance; + vector4Serializer.Serialize(serializer, item.GetColumn(0)); + vector4Serializer.Serialize(serializer, item.GetColumn(1)); + vector4Serializer.Serialize(serializer, item.GetColumn(2)); + vector4Serializer.Serialize(serializer, item.GetColumn(3)); + } + protected override Matrix4x4 DoDeserialize(BinaryDeserializer deserializer) + { + var vector4Serializer = Vector4Serializer.Instance; + var column0 = vector4Serializer.Deserialize(deserializer); + var column1 = vector4Serializer.Deserialize(deserializer); + var column2 = vector4Serializer.Deserialize(deserializer); + var column3 = vector4Serializer.Deserialize(deserializer); + return new Matrix4x4(column0, column1, column2, column3); + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/Matrix4x4Serializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/Matrix4x4Serializer.cs.meta new file mode 100644 index 0000000..9068dad --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/Matrix4x4Serializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6cfb59cf6e01f44dd83498d7966ca2d0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/NativeArraySerializer.cs b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/NativeArraySerializer.cs new file mode 100644 index 0000000..9ecdf9b --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/NativeArraySerializer.cs @@ -0,0 +1,55 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.IO; + +using Niantic.ARDK.Utilities.BinarySerialization.Contexts; +using Niantic.ARDK.Utilities.Collections; + +using Unity.Collections; + +namespace Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers +{ + public sealed class NativeArraySerializer: + BaseItemSerializer> + where T: struct + { + public static readonly NativeArraySerializer Instance = new NativeArraySerializer(); + + private NativeArraySerializer() + { + } + + protected override void DoSerialize(BinarySerializer serializer, NativeArray item) + { + int length = item.Length; + + var arrayLengthLimiter = serializer.GetContext(); + arrayLengthLimiter.ReserveOrThrow(length); + CompressedUInt32Serializer.Instance.Serialize(serializer, (UInt32)length); + + foreach (T t in item) + serializer.Serialize(t); + } + protected override NativeArray DoDeserialize(BinaryDeserializer deserializer) + { + UInt32 unsignedLength = CompressedUInt32Serializer.Instance.Deserialize(deserializer); + if (unsignedLength == 0) + return new NativeArray(); + + Int32 length = checked((Int32)unsignedLength); + var arrayLengthLimiter = deserializer.GetContext(); + arrayLengthLimiter.ReserveOrThrow(length); + + var result = new NativeArray((int)unsignedLength, Allocator.Persistent); + + for (int i = 0; i < length; i++) + { + T item = (T)deserializer.Deserialize(); + result[i] = item; + } + + return result; + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/NativeArraySerializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/NativeArraySerializer.cs.meta new file mode 100644 index 0000000..0d58365 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/NativeArraySerializer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 133698bd37bf4b8fbf9be30d1243cd68 +timeCreated: 1613511096 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/NetworkIdSerializer.cs b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/NetworkIdSerializer.cs new file mode 100644 index 0000000..6eb36ec --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/NetworkIdSerializer.cs @@ -0,0 +1,28 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.Networking.HLAPI.Routing; + +namespace Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers +{ + public sealed class NetworkIdSerializer: + BaseItemSerializer + { + public static readonly NetworkIdSerializer Instance = new NetworkIdSerializer(); + + private NetworkIdSerializer() + { + } + + protected override void DoSerialize(BinarySerializer serializer, NetworkId item) + { + CompressedUInt64Serializer.Instance.Serialize(serializer, item.RawId); + } + protected override NetworkId DoDeserialize(BinaryDeserializer deserializer) + { + UInt64 rawId = CompressedUInt64Serializer.Instance.Deserialize(deserializer); + return new NetworkId(rawId); + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/NetworkIdSerializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/NetworkIdSerializer.cs.meta new file mode 100644 index 0000000..e514376 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/NetworkIdSerializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d42423b907ef645e6b896777fbb2e613 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/QuaternionSerializer.cs b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/QuaternionSerializer.cs new file mode 100644 index 0000000..702a402 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/QuaternionSerializer.cs @@ -0,0 +1,35 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using UnityEngine; + +namespace Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers +{ + public sealed class QuaternionSerializer: + BaseItemSerializer + { + public static readonly QuaternionSerializer Instance = new QuaternionSerializer(); + + private QuaternionSerializer() + { + } + + protected override void DoSerialize(BinarySerializer serializer, Quaternion item) + { + var floatSerializer = FloatSerializer.Instance; + floatSerializer.Serialize(serializer, item.x); + floatSerializer.Serialize(serializer, item.y); + floatSerializer.Serialize(serializer, item.z); + floatSerializer.Serialize(serializer, item.w); + } + protected override Quaternion DoDeserialize(BinaryDeserializer deserializer) + { + var floatSerializer = FloatSerializer.Instance; + float x = floatSerializer.Deserialize(deserializer); + float y = floatSerializer.Deserialize(deserializer); + float z = floatSerializer.Deserialize(deserializer); + float w = floatSerializer.Deserialize(deserializer); + return new Quaternion(x, y, z, w); + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/QuaternionSerializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/QuaternionSerializer.cs.meta new file mode 100644 index 0000000..98c301e --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/QuaternionSerializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1bc606787a25a43449caf26ec24257a7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ResolutionSerializer.cs b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ResolutionSerializer.cs new file mode 100644 index 0000000..f4f9ac7 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ResolutionSerializer.cs @@ -0,0 +1,32 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using UnityEngine; + +namespace Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers +{ + public sealed class ResolutionSerializer: + BaseItemSerializer + { + public static readonly ResolutionSerializer Instance = new ResolutionSerializer(); + + private ResolutionSerializer() + { + } + + protected override void DoSerialize(BinarySerializer serializer, Resolution item) + { + var int32Serializer = CompressedInt32Serializer.Instance; + int32Serializer.Serialize(serializer, item.width); + int32Serializer.Serialize(serializer, item.height); + } + protected override Resolution DoDeserialize(BinaryDeserializer deserializer) + { + var int32Serializer = CompressedInt32Serializer.Instance; + Int32 width = int32Serializer.Deserialize(deserializer); + Int32 height = int32Serializer.Deserialize(deserializer); + + return new Resolution { width = width, height = height }; + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ResolutionSerializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ResolutionSerializer.cs.meta new file mode 100644 index 0000000..dd961e4 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/ResolutionSerializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 803adf1fb2a964482ab46cc6c6ac2df8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/SByteSerializer.cs b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/SByteSerializer.cs new file mode 100644 index 0000000..061dda1 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/SByteSerializer.cs @@ -0,0 +1,33 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.Utilities.Extensions; + +namespace Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers +{ + public sealed class SByteSerializer: + BaseItemSerializer + { + public static readonly SByteSerializer Instance = new SByteSerializer(); + + private SByteSerializer() + { + } + + protected override void DoSerialize(BinarySerializer serializer, sbyte item) + { + unchecked + { + serializer.Stream.WriteByte((byte)item); + } + } + protected override sbyte DoDeserialize(BinaryDeserializer deserializer) + { + unchecked + { + return (sbyte)deserializer.Stream.ReadByteOrThrow(); + } + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/SByteSerializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/SByteSerializer.cs.meta new file mode 100644 index 0000000..01da80f --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/SByteSerializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7c5bcf330ee2745d8a5ea54f57c0df4a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/SimpleSerializableSerializer.cs b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/SimpleSerializableSerializer.cs new file mode 100644 index 0000000..36e8171 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/SimpleSerializableSerializer.cs @@ -0,0 +1,177 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Runtime.Serialization; + +namespace Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers +{ + /// + /// Serializes/deserializes objects of classes that have the [Serializable] attribute by + /// serializing/deserializing all their fields. This doesn't work with types that implement + /// ISerializable (those types aren't "simple serializables"). + /// + public sealed class SimpleSerializableSerializer: + IItemSerializer + { + private static readonly ConcurrentDictionary _serializers = + new ConcurrentDictionary(); + + internal static readonly Comparison _fieldComparison = + (a, b) => string.Compare(a.Name, b.Name, StringComparison.InvariantCulture); + + private static readonly Func _createSerializerFunc = + (type) => new SimpleSerializableSerializer(type); + + public static SimpleSerializableSerializer ForType(Type type) + { + if (type == null) + throw new ArgumentNullException(nameof(type)); + + var result = _serializers.GetOrAdd(type, _createSerializerFunc); + return result; + } + + public static void RegisterSerializerForAllSimpleSerializablesOf(Assembly assembly) + { + if (assembly == null) + throw new ArgumentNullException(nameof(assembly)); + + foreach(var type in assembly.GetTypes()) + { + if (!type.IsSerializable) + continue; + + if (type.IsEnum) + continue; + + if (type.IsAbstract) + continue; + + // Types that implement ISerializable aren't "simple" serializable types. + if (typeof(ISerializable).IsAssignableFrom(type)) + continue; + + // Nothing to do if there's a serializer for that type already registered. + if (GlobalSerializer.TryGetItemSerializer(type) != null) + continue; + + var serializer = ForType(type); + GlobalSerializer.RegisterUntypedItemSerializer(serializer); + } + } + + private readonly Type _typeToSerialize; + private readonly FieldInfo[] _fields; + + private SimpleSerializableSerializer(Type typeToSerialize) + { + if (typeToSerialize == null) + throw new ArgumentNullException(nameof(typeToSerialize)); + + if (typeToSerialize.IsEnum) + { + var message = "Type " + typeToSerialize.FullName + " is an enum. Use EnumSerializer instead."; + throw new ArgumentException(message, nameof(typeToSerialize)); + } + + if (!typeToSerialize.IsSerializable) + { + string msg = "The type " + typeToSerialize.FullName + " is not [Serializable]."; + throw new InvalidOperationException(msg); + } + + if (typeof(ISerializable).IsAssignableFrom(typeToSerialize)) + { + string msg = + "This serializer is for simple serializable types (that is, types that don't implement " + + "ISerializable), but type " + typeToSerialize.FullName + " is not a simple " + + "serializable type."; + + throw new InvalidOperationException(msg); + } + + // By default we would want to get all the field hierarchy at once, but it actually does + // something quite odd on iOS... it returns all the fields, but aside from the fields at + // the latest level, all the fields from base will always return null or default when + // we try to get their values. So, we get Declared only fields for each level of the hierarchy + // and this works fine. + var flags = + BindingFlags.Public | + BindingFlags.NonPublic | + BindingFlags.Instance | + BindingFlags.DeclaredOnly; + + var allFields = new List(); + + var currentType = typeToSerialize; + while (currentType != null) + { + var fieldsAtThisLevel = currentType.GetFields(flags); + + // Add all fields that aren't marked as NonSerialized. + foreach(var field in fieldsAtThisLevel) + if (field.GetCustomAttributes(typeof(NonSerializedAttribute), true).Length == 0) + allFields.Add(field); + + currentType = currentType.BaseType; + } + + allFields.Sort(SimpleSerializableSerializer._fieldComparison); + + _typeToSerialize = typeToSerialize; + _fields = allFields.ToArray(); + } + + public Type DataType + { + get + { + return _typeToSerialize; + } + } + + public void Serialize(BinarySerializer serializer, object item) + { + if (serializer == null) + throw new ArgumentNullException(nameof(serializer)); + + if (item == null) + throw new ArgumentNullException(nameof(item)); + + var values = FormatterServices.GetObjectData(item, _fields); + ArraySerializer.Instance.Serialize(serializer, values); + } + + public object Deserialize(BinaryDeserializer deserializer) + { + if (deserializer == null) + throw new ArgumentNullException(nameof(deserializer)); + + var values = ArraySerializer.Instance.Deserialize(deserializer); + + if (_fields.Length != values.Length) + { + var message = + "The number of values to deserialize does not match the number of known fields for " + + "type " + _typeToSerialize.FullName + ".\n Fields in the type: " + _fields.Length + + "\n Values to deserialize: " + values.Length + "."; + + throw new InvalidOperationException(message); + } + + object result = FormatterServices.GetSafeUninitializedObject(_typeToSerialize); + FormatterServices.PopulateObjectMembers(result, _fields, values); + return result; + } + } + + public static class SimpleSerializableSerializer + { + public static readonly IItemSerializer Instance = + new _UntypedToTypedSerializerAdapter(SimpleSerializableSerializer.ForType(typeof(T))); + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/SimpleSerializableSerializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/SimpleSerializableSerializer.cs.meta new file mode 100644 index 0000000..a49b2d1 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/SimpleSerializableSerializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 52eb12b56cde0457b80373898c2a5259 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/StringSerializer.cs b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/StringSerializer.cs new file mode 100644 index 0000000..1fdb450 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/StringSerializer.cs @@ -0,0 +1,62 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Text; + +using Niantic.ARDK.Utilities.Extensions; +using Niantic.ARDK.Utilities.BinarySerialization.Contexts; + +namespace Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers +{ + public sealed class StringSerializer: + BaseItemSerializer + { + public static readonly StringSerializer Instance = new StringSerializer(); + + private StringSerializer() + { + } + + protected override void DoSerialize(BinarySerializer serializer, string item) + { + int length = item.Length; + + if (length == 0) + { + CompressedUInt32Serializer.Instance.Serialize(serializer, 0); + return; + } + + var encoder = Encoding.UTF8; + var bytes = encoder.GetBytes(item); + length = bytes.Length; + + var arrayLengthLimiter = serializer.GetContext(); + arrayLengthLimiter.ReserveOrThrow(length); + + CompressedUInt32Serializer.Instance.Serialize(serializer, (UInt32)length); + serializer.Stream.Write(bytes, 0, bytes.Length); + } + + protected override string DoDeserialize(BinaryDeserializer deserializer) + { + UInt32 unsignedLength = CompressedUInt32Serializer.Instance.Deserialize(deserializer); + + // A length 0 means an empty string. Null is not supported by item serializers, being the + // responsibility of the global serializer (or the array serializer or the like). + if (unsignedLength == 0) + return ""; + + Int32 length = checked((Int32)unsignedLength); + var arrayLengthLimiter = deserializer.GetContext(); + arrayLengthLimiter.ReserveOrThrow(length); + + byte[] bytes = new byte[length]; + deserializer.Stream.ReadOrThrow(bytes, 0, length); + + var encoder = Encoding.UTF8; + var result = encoder.GetString(bytes); + return result; + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/StringSerializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/StringSerializer.cs.meta new file mode 100644 index 0000000..0e92e14 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/StringSerializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 85f07e7cd4c284319acd229e096a292f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/UInt16Serializer.cs b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/UInt16Serializer.cs new file mode 100644 index 0000000..8f5b19c --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/UInt16Serializer.cs @@ -0,0 +1,38 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.IO; + +using Niantic.ARDK.Utilities.Extensions; + +namespace Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers +{ + + public sealed class UInt16Serializer: + BaseItemSerializer + { + public static readonly UInt16Serializer Instance = new UInt16Serializer(); + + private UInt16Serializer() + { + } + + protected override void DoSerialize(BinarySerializer serializer, UInt16 item) + { + unchecked + { + var stream = serializer.Stream; + stream.WriteByte((byte)(item >> 8)); + stream.WriteByte((byte)item); + } + } + protected override UInt16 DoDeserialize(BinaryDeserializer deserializer) + { + var stream = deserializer.Stream; + UInt16 byte1 = stream.ReadByteOrThrow(); + UInt16 byte2 = stream.ReadByteOrThrow(); + + return (UInt16)((byte1 << 8) | byte2); + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/UInt16Serializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/UInt16Serializer.cs.meta new file mode 100644 index 0000000..fc19598 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/UInt16Serializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 57add15b094b74d53b61dab0896ee76b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/Vector2Serializer.cs b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/Vector2Serializer.cs new file mode 100644 index 0000000..4cb6d23 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/Vector2Serializer.cs @@ -0,0 +1,31 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using UnityEngine; + +namespace Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers { + + public sealed class Vector2Serializer: + BaseItemSerializer + { + public static readonly Vector2Serializer Instance = new Vector2Serializer(); + + private Vector2Serializer() + { + } + + protected override void DoSerialize(BinarySerializer serializer, Vector2 item) + { + var floatSerializer = FloatSerializer.Instance; + floatSerializer.Serialize(serializer, item.x); + floatSerializer.Serialize(serializer, item.y); + } + protected override Vector2 DoDeserialize(BinaryDeserializer deserializer) + { + var floatSerializer = FloatSerializer.Instance; + float x = floatSerializer.Deserialize(deserializer); + float y = floatSerializer.Deserialize(deserializer); + return new Vector2(x, y); + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/Vector2Serializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/Vector2Serializer.cs.meta new file mode 100644 index 0000000..07ae972 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/Vector2Serializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4745069be78ea47ad8043a0c88b6ddd1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/Vector3Serializer.cs b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/Vector3Serializer.cs new file mode 100644 index 0000000..84c09f2 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/Vector3Serializer.cs @@ -0,0 +1,33 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using UnityEngine; + +namespace Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers { + + public sealed class Vector3Serializer: + BaseItemSerializer + { + public static readonly Vector3Serializer Instance = new Vector3Serializer(); + + private Vector3Serializer() + { + } + + protected override void DoSerialize(BinarySerializer serializer, Vector3 item) + { + var floatSerializer = FloatSerializer.Instance; + floatSerializer.Serialize(serializer, item.x); + floatSerializer.Serialize(serializer, item.y); + floatSerializer.Serialize(serializer, item.z); + } + protected override Vector3 DoDeserialize(BinaryDeserializer deserializer) + { + var floatSerializer = FloatSerializer.Instance; + float x = floatSerializer.Deserialize(deserializer); + float y = floatSerializer.Deserialize(deserializer); + float z = floatSerializer.Deserialize(deserializer); + return new Vector3(x, y, z); + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/Vector3Serializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/Vector3Serializer.cs.meta new file mode 100644 index 0000000..3548267 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/Vector3Serializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bfebd88c3047f425c98f52fb2b9f752e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/Vector4Serializer.cs b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/Vector4Serializer.cs new file mode 100644 index 0000000..71b0c6f --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/Vector4Serializer.cs @@ -0,0 +1,35 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using UnityEngine; + +namespace Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers { + + public sealed class Vector4Serializer: + BaseItemSerializer + { + public static readonly Vector4Serializer Instance = new Vector4Serializer(); + + private Vector4Serializer() + { + } + + protected override void DoSerialize(BinarySerializer serializer, Vector4 item) + { + var floatSerializer = FloatSerializer.Instance; + floatSerializer.Serialize(serializer, item.x); + floatSerializer.Serialize(serializer, item.y); + floatSerializer.Serialize(serializer, item.z); + floatSerializer.Serialize(serializer, item.w); + } + protected override Vector4 DoDeserialize(BinaryDeserializer deserializer) + { + var floatSerializer = FloatSerializer.Instance; + float x = floatSerializer.Deserialize(deserializer); + float y = floatSerializer.Deserialize(deserializer); + float z = floatSerializer.Deserialize(deserializer); + float w = floatSerializer.Deserialize(deserializer); + return new Vector4(x, y, z, w); + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/Vector4Serializer.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/Vector4Serializer.cs.meta new file mode 100644 index 0000000..3fc51f6 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/Vector4Serializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8089beb6f037244c7a69b453ac80a23d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/_UntypedToTypedSerializerAdapter.cs b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/_UntypedToTypedSerializerAdapter.cs new file mode 100644 index 0000000..671d936 --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/_UntypedToTypedSerializerAdapter.cs @@ -0,0 +1,31 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.IO; + +using Niantic.ARDK.Utilities.Extensions; +using Niantic.ARDK.Utilities.BinarySerialization.Contexts; +using Niantic.ARDK.Utilities.Collections; + +namespace Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers +{ + internal sealed class _UntypedToTypedSerializerAdapter: + BaseItemSerializer + { + private readonly IItemSerializer _untypedSerializer; + internal _UntypedToTypedSerializerAdapter(IItemSerializer untypedSerializer) + { + _untypedSerializer = untypedSerializer; + } + + protected override void DoSerialize(BinarySerializer serializer, T item) + { + _untypedSerializer.Serialize(serializer, item); + } + protected override T DoDeserialize(BinaryDeserializer deserializer) + { + object result = _untypedSerializer.Deserialize(deserializer); + return (T)result; + } + } +} diff --git a/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/_UntypedToTypedSerializerAdapter.cs.meta b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/_UntypedToTypedSerializerAdapter.cs.meta new file mode 100644 index 0000000..5a8884b --- /dev/null +++ b/Assets/ARDK/Utilities/BinarySerialization/ItemSerializers/_UntypedToTypedSerializerAdapter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b035150f80f4c4285b0f7879cafd4feb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/Collections.meta b/Assets/ARDK/Utilities/Collections.meta new file mode 100644 index 0000000..be26847 --- /dev/null +++ b/Assets/ARDK/Utilities/Collections.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 89a33bee1307247489b8b252218e22e9 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/Collections/ARDKReadOnlyCollection.cs b/Assets/ARDK/Utilities/Collections/ARDKReadOnlyCollection.cs new file mode 100644 index 0000000..93b8772 --- /dev/null +++ b/Assets/ARDK/Utilities/Collections/ARDKReadOnlyCollection.cs @@ -0,0 +1,100 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace Niantic.ARDK.Utilities.Collections +{ + /// + /// Helper class to create new ARDKReadOnlyCollection<T> instances by using type-inference. + /// That is: var readOnlySet = hashSet.AsArdkReadOnly(); + /// + public static class ARDKReadOnlyCollection + { + public static ARDKReadOnlyCollection AsArdkReadOnly(this ICollection mutableCollection) + { + return new ARDKReadOnlyCollection(mutableCollection); + } + } + + /// + /// Represents a read-only accessor to a mutable collection, similar to what ReadOnlyCollection + /// does to lists and arrays, but being just a "collection" (the .NET ReadOnlyCollection should be + /// named ReadOnlyList). + /// Instances of this class cannot modify the collection they point to, yet the original + /// collection can still be modified by anyone having a reference to it (and any changes will be + /// visible by instances of this class). + /// + /// + /// This class implements the mutable ICollection<T> (but throws on any mutation method) to + /// support the fast LINQ operations. LINQ cast only to the mutable interfaces, not to the + /// read-only ones. + /// + public sealed class ARDKReadOnlyCollection: + IReadOnlyCollection, + ICollection + { + private readonly ICollection _collection; + + public ARDKReadOnlyCollection(ICollection mutableCollection) + { + if (mutableCollection == null) + throw new ArgumentNullException(nameof(mutableCollection)); + + _collection = mutableCollection; + } + + public int Count + { + get + { + return _collection.Count; + } + } + + public bool Contains(T item) + { + return _collection.Contains(item); + } + + public void CopyTo(T[] array, int arrayIndex) + { + _collection.CopyTo(array, arrayIndex); + } + + public IEnumerator GetEnumerator() + { + return _collection.GetEnumerator(); + } + + // Explicit IEnumerable implementation. + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + // Explicit ICollection implementation. + bool ICollection.IsReadOnly + { + get { + return true; + } + } + + void ICollection.Clear() + { + throw new NotSupportedException("This collection is read-only."); + } + + void ICollection.Add(T item) + { + throw new NotSupportedException("This collection is read-only."); + } + + bool ICollection.Remove(T item) + { + throw new NotSupportedException("This collection is read-only."); + } + } +} diff --git a/Assets/ARDK/Utilities/Collections/ARDKReadOnlyCollection.cs.meta b/Assets/ARDK/Utilities/Collections/ARDKReadOnlyCollection.cs.meta new file mode 100644 index 0000000..6725b83 --- /dev/null +++ b/Assets/ARDK/Utilities/Collections/ARDKReadOnlyCollection.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8f237284f51694c749140a1ffe00eceb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/Collections/EmptyArdkReadOnlyCollection.cs b/Assets/ARDK/Utilities/Collections/EmptyArdkReadOnlyCollection.cs new file mode 100644 index 0000000..bd3ef77 --- /dev/null +++ b/Assets/ARDK/Utilities/Collections/EmptyArdkReadOnlyCollection.cs @@ -0,0 +1,10 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.Utilities.Collections +{ + public static class EmptyArdkReadOnlyCollection + { + public static readonly ARDKReadOnlyCollection Instance = + EmptyArray.Instance.AsArdkReadOnly(); + } +} diff --git a/Assets/ARDK/Utilities/Collections/EmptyArdkReadOnlyCollection.cs.meta b/Assets/ARDK/Utilities/Collections/EmptyArdkReadOnlyCollection.cs.meta new file mode 100644 index 0000000..7064b2d --- /dev/null +++ b/Assets/ARDK/Utilities/Collections/EmptyArdkReadOnlyCollection.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5c1fb2c455f14bf3818f6dad3713e22c +timeCreated: 1594230240 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/Collections/EmptyArray.cs b/Assets/ARDK/Utilities/Collections/EmptyArray.cs new file mode 100644 index 0000000..c667d72 --- /dev/null +++ b/Assets/ARDK/Utilities/Collections/EmptyArray.cs @@ -0,0 +1,12 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.Utilities.Collections +{ + /// + /// Generic class that generates a single, reusable instance of an empty array of type T. + /// + public static class EmptyArray + { + public static readonly T[] Instance = new T[0]; + } +} diff --git a/Assets/ARDK/Utilities/Collections/EmptyArray.cs.meta b/Assets/ARDK/Utilities/Collections/EmptyArray.cs.meta new file mode 100644 index 0000000..15fbf8f --- /dev/null +++ b/Assets/ARDK/Utilities/Collections/EmptyArray.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 381ddc88febb4cd7a44b9dac6172d097 +timeCreated: 1573502224 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/Collections/EmptyReadOnlyCollection.cs b/Assets/ARDK/Utilities/Collections/EmptyReadOnlyCollection.cs new file mode 100644 index 0000000..90fea5a --- /dev/null +++ b/Assets/ARDK/Utilities/Collections/EmptyReadOnlyCollection.cs @@ -0,0 +1,12 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.Collections.ObjectModel; + +namespace Niantic.ARDK.Utilities.Collections +{ + public static class EmptyReadOnlyCollection + { + public static readonly ReadOnlyCollection Instance = + new ReadOnlyCollection(EmptyArray.Instance); + } +} diff --git a/Assets/ARDK/Utilities/Collections/EmptyReadOnlyCollection.cs.meta b/Assets/ARDK/Utilities/Collections/EmptyReadOnlyCollection.cs.meta new file mode 100644 index 0000000..41b0f3e --- /dev/null +++ b/Assets/ARDK/Utilities/Collections/EmptyReadOnlyCollection.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 49d39c0871a54411b8c64ec1e010398c +timeCreated: 1592593459 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/Collections/_ArrayFromElement.cs b/Assets/ARDK/Utilities/Collections/_ArrayFromElement.cs new file mode 100644 index 0000000..815491e --- /dev/null +++ b/Assets/ARDK/Utilities/Collections/_ArrayFromElement.cs @@ -0,0 +1,12 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.Utilities.Collections +{ + internal static class _ArrayFromElement + { + public static T[] Create(T element) + { + return new T[] { element }; + } + } +} diff --git a/Assets/ARDK/Utilities/Collections/_ArrayFromElement.cs.meta b/Assets/ARDK/Utilities/Collections/_ArrayFromElement.cs.meta new file mode 100644 index 0000000..56e23b6 --- /dev/null +++ b/Assets/ARDK/Utilities/Collections/_ArrayFromElement.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 0e0c3eeb9fd344a7bc4526b2068fa891 +timeCreated: 1595985544 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/Collections/_EmptyReadOnlyDictionary.cs b/Assets/ARDK/Utilities/Collections/_EmptyReadOnlyDictionary.cs new file mode 100644 index 0000000..3508029 --- /dev/null +++ b/Assets/ARDK/Utilities/Collections/_EmptyReadOnlyDictionary.cs @@ -0,0 +1,12 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.Collections.Generic; + +namespace Niantic.ARDK.Utilities.Collections +{ + internal sealed class _EmptyReadOnlyDictionary + { + public static readonly _ReadOnlyDictionary Instance = + new _ReadOnlyDictionary(new Dictionary()); + } +} diff --git a/Assets/ARDK/Utilities/Collections/_EmptyReadOnlyDictionary.cs.meta b/Assets/ARDK/Utilities/Collections/_EmptyReadOnlyDictionary.cs.meta new file mode 100644 index 0000000..0b072b5 --- /dev/null +++ b/Assets/ARDK/Utilities/Collections/_EmptyReadOnlyDictionary.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b14c5f1ec174645b2829495287d5a077 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/Collections/_ReadOnlyCollectionExtensions.cs b/Assets/ARDK/Utilities/Collections/_ReadOnlyCollectionExtensions.cs new file mode 100644 index 0000000..12fe731 --- /dev/null +++ b/Assets/ARDK/Utilities/Collections/_ReadOnlyCollectionExtensions.cs @@ -0,0 +1,17 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.Collections.ObjectModel; + +namespace Niantic.ARDK.Utilities.Collections +{ + internal static class _ReadOnlyCollectionExtensions + { + public static ReadOnlyCollection AsNonNullReadOnly(this T[] source) + { + if (source == null || source.Length == 0) + return EmptyReadOnlyCollection.Instance; + + return new ReadOnlyCollection(source); + } + } +} diff --git a/Assets/ARDK/Utilities/Collections/_ReadOnlyCollectionExtensions.cs.meta b/Assets/ARDK/Utilities/Collections/_ReadOnlyCollectionExtensions.cs.meta new file mode 100644 index 0000000..d227ac8 --- /dev/null +++ b/Assets/ARDK/Utilities/Collections/_ReadOnlyCollectionExtensions.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 72af934674a041a09d372ac9a2dbdbf2 +timeCreated: 1594917670 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/Collections/_ReadOnlyDictionary.cs b/Assets/ARDK/Utilities/Collections/_ReadOnlyDictionary.cs new file mode 100644 index 0000000..2c0eea5 --- /dev/null +++ b/Assets/ARDK/Utilities/Collections/_ReadOnlyDictionary.cs @@ -0,0 +1,371 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +// Public domain from: https://blogs.cuttingedge.it/steven/posts/2007/readonlydictionary/ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Threading; + +namespace Niantic.ARDK.Utilities.Collections +{ + /// + /// Provides the base class for a generic read-only dictionary. + /// + /// + /// The type of keys in the dictionary. + /// + /// + /// The type of values in the dictionary. + /// + /// + /// + /// An instance of the _ReadOnlyDictionary generic class is + /// always read-only. A dictionary that is read-only is simply a + /// dictionary with a wrapper that prevents modifying the + /// dictionary; therefore, if changes are made to the underlying + /// dictionary, the read-only dictionary reflects those changes. + /// See for a modifiable version of + /// this class. + /// + /// + /// Notes to Implementers This base class is provided to + /// make it easier for implementers to create a generic read-only + /// custom dictionary. Implementers are encouraged to extend this + /// base class instead of creating their own. + /// + /// + [Serializable] + [DebuggerDisplay("Count = {" + nameof(Count) + "}")] + [ComVisible(false)] + [DebuggerTypeProxy(typeof(ReadOnlyDictionaryDebugView<,>))] + internal sealed class _ReadOnlyDictionary: + IDictionary, + IReadOnlyDictionary, + ICollection + { + private readonly IDictionary _source; + private object _syncRoot; + + /// + /// Initializes a new instance of the + /// class that wraps + /// the supplied . + /// + /// The + /// that will be wrapped. + /// + /// Thrown when the dictionary is null. + /// + public _ReadOnlyDictionary(IDictionary dictionaryToWrap) + { + if (dictionaryToWrap == null) + throw new ArgumentNullException(nameof(dictionaryToWrap)); + + _source = dictionaryToWrap; + } + + /// + /// Gets the number of key/value pairs contained in the + /// . + /// + /// The number of key/value pairs. + /// The number of key/value pairs contained in the + /// . + public int Count + { + get { return _source.Count; } + } + + /// Gets a collection containing the keys in the + /// . + /// A + /// containing the keys. + /// A + /// + /// containing the keys in the + /// . + /// + public ICollection Keys + { + get { return _source.Keys; } + } + + /// + /// Gets a collection containing the values of the + /// . + /// + /// The collection of values. + public ICollection Values + { + get { return _source.Values; } + } + + /// Gets a value indicating whether the dictionary is read-only. + /// This value will always be true. + bool ICollection>.IsReadOnly + { + get { return true; } + } + + /// + /// Gets a value indicating whether access to the dictionary + /// is synchronized (thread safe). + /// + bool ICollection.IsSynchronized + { + get { return false; } + } + + /// + /// Gets an object that can be used to synchronize access to dictionary. + /// + object ICollection.SyncRoot + { + get + { + if (_syncRoot != null) + return _syncRoot; + + var collection = _source as ICollection; + + if (collection != null) + _syncRoot = collection.SyncRoot; + else + Interlocked.CompareExchange(ref _syncRoot, new object(), null); + + return _syncRoot; + } + } + + /// + /// Gets or sets the value associated with the specified key. + /// + /// + /// The value associated with the specified key. If the specified key + /// is not found, a get operation throws a + /// , + /// and a set operation creates a new element with the specified key. + /// + /// The key of the value to get or set. + /// + /// Thrown when the key is null. + /// + /// + /// The property is retrieved and key does not exist in the collection. + /// + public TValue this[TKey key] + { + get { return _source[key]; } + set { ThrowNotSupportedException(); } + } + + /// This method is not supported by the + /// . + /// + /// The object to use as the key of the element to add. + /// + /// The object to use as the value of the element to add. + void IDictionary.Add(TKey key, TValue value) + { + ThrowNotSupportedException(); + } + + /// Determines whether the + /// contains the specified key. + /// + /// True if the contains + /// an element with the specified key; otherwise, false. + /// + /// The key to locate in the + /// . + /// + /// Thrown when the key is null. + /// + public bool ContainsKey(TKey key) + { + return _source.ContainsKey(key); + } + + /// + /// This method is not supported by the . + /// + /// The key of the element to remove. + /// + /// True if the element is successfully removed; otherwise, false. + /// + bool IDictionary.Remove(TKey key) + { + ThrowNotSupportedException(); + + return false; + } + + /// + /// Gets the value associated with the specified key. + /// + /// The key of the value to get. + /// When this method returns, contains the value + /// associated with the specified key, if the key is found; + /// otherwise, the default value for the type of the value parameter. + /// This parameter is passed uninitialized. + /// + /// true if the contains + /// an element with the specified key; otherwise, false. + /// + public bool TryGetValue(TKey key, out TValue value) + { + return _source.TryGetValue(key, out value); + } + + /// This method is not supported by the + /// . + /// + /// The object to add to the . + /// + void ICollection>.Add(KeyValuePair item) + { + ThrowNotSupportedException(); + } + + /// This method is not supported by the + /// . + void ICollection>.Clear() + { + ThrowNotSupportedException(); + } + + /// + /// Determines whether the contains a + /// specific value. + /// + /// + /// The object to locate in the . + /// + /// + /// true if item is found in the ICollection; + /// otherwise, false. + /// + bool ICollection>.Contains(KeyValuePair item) + { + ICollection> collection = _source; + + return collection.Contains(item); + } + + /// + /// Copies the elements of the ICollection to an Array, starting at a + /// particular Array index. + /// + /// The one-dimensional Array that is the + /// destination of the elements copied from ICollection. + /// The Array must have zero-based indexing. + /// + /// + /// The zero-based index in array at which copying begins. + /// + void ICollection>.CopyTo + ( + KeyValuePair[] array, + int arrayIndex + ) + { + ICollection> collection = _source; + collection.CopyTo(array, arrayIndex); + } + + /// This method is not supported by the + /// . + /// + /// The object to remove from the ICollection. + /// + /// Will never return a value. + bool ICollection>.Remove(KeyValuePair item) + { + ThrowNotSupportedException(); + + return false; + } + + /// + /// Returns an enumerator that iterates through the collection. + /// + /// + /// A IEnumerator that can be used to iterate through the collection. + /// + IEnumerator> + IEnumerable>.GetEnumerator() + { + IEnumerable> enumerator = _source; + + return enumerator.GetEnumerator(); + } + + /// + /// Returns an enumerator that iterates through a collection. + /// + /// + /// An IEnumerator that can be used to iterate through the collection. + /// + IEnumerator IEnumerable.GetEnumerator() + { + return _source.GetEnumerator(); + } + + /// + /// For a description of this member, see . + /// + /// + /// The one-dimensional Array that is the destination of the elements copied from + /// ICollection. The Array must have zero-based indexing. + /// + /// + /// The zero-based index in Array at which copying begins. + /// + void ICollection.CopyTo(Array array, int index) + { + ICollection collection = new List>(_source); + collection.CopyTo(array, index); + } + + IEnumerable IReadOnlyDictionary.Keys + { + get { return Keys; } + } + + IEnumerable IReadOnlyDictionary.Values + { + get { return Values; } + } + + private static void ThrowNotSupportedException() + { + throw new NotSupportedException("This Dictionary is read-only"); + } + } + + internal sealed class ReadOnlyDictionaryDebugView + { + private readonly IDictionary _dict; + + public ReadOnlyDictionaryDebugView(_ReadOnlyDictionary dictionary) + { + if (dictionary == null) + throw new ArgumentNullException(nameof(dictionary)); + + _dict = dictionary; + } + + [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] + public KeyValuePair[] Items + { + get + { + var array = new KeyValuePair[_dict.Count]; + _dict.CopyTo(array, 0); + return array; + } + } + } +} diff --git a/Assets/ARDK/Utilities/Collections/_ReadOnlyDictionary.cs.meta b/Assets/ARDK/Utilities/Collections/_ReadOnlyDictionary.cs.meta new file mode 100644 index 0000000..7175d45 --- /dev/null +++ b/Assets/ARDK/Utilities/Collections/_ReadOnlyDictionary.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c81bb87a63fa462e86b40a8a96571fa0 +timeCreated: 1553277308 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/Collections/_WeakValueDictionary.cs b/Assets/ARDK/Utilities/Collections/_WeakValueDictionary.cs new file mode 100644 index 0000000..2e7bd28 --- /dev/null +++ b/Assets/ARDK/Utilities/Collections/_WeakValueDictionary.cs @@ -0,0 +1,189 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections; +using System.Collections.Concurrent; + +using UnityEngine; + +namespace Niantic.ARDK.Utilities +{ + // A class that works like a dictionary but allows the values to be collected, effectively + // removing the entire pair from the dictionary when that happens. + internal sealed class _WeakValueDictionary: + IDisposable, IEnumerable + where + TValue: class + { + private static readonly Func _createWeakReference = + (_) => new WeakReference(null); + + internal ConcurrentDictionary _innerDictionary = + new ConcurrentDictionary(); + + internal _WeakValueDictionary() + { + _GcObserver._GcHappened += _ClearCollectedValues; + } + + public void Dispose() + { + _GcObserver._GcHappened -= _ClearCollectedValues; + _innerDictionary = null; + } + + public IEnumerator GetEnumerator() + { + return _innerDictionary.GetEnumerator(); + } + + // Aside from tests and individual checks, using Count is not really safe, as we might + // check that Count is bigger than zero and, at next line, it is 0 already because a GC + // happened between those to calls. + public int Count + { + get { return _innerDictionary.Count; } + } + + // This method removes all the key/value pairs for those items that were already collected. + // The fact that WeakReferences allow their values to be collected might still cause memory + // leaks if we never remove the WeakReferences themselves from the dictionaries, as those + // dictionaries will just grow and will not allow either the key, or the WeakReference, to die. + private void _ClearCollectedValues() + { + foreach (var pair in _innerDictionary) + { + var weakReference = pair.Value; + + // This double-checked "is-alive" condition exists for the following reason: + // Even if we are using a ConcurrentDictionary and WeakReferences are thread-safe, there is + // a chance that we check a WeakReference is dead but, just "before" removing it, another + // call to TryAdd or GetOrAdd was made, effectively making the WeakReference alive again. + // So, to avoid any issues, if the WeakReference is not alive, we lock it, check that it + // is still not alive, and then remove it while holding the lock. + if (!weakReference.IsAlive) + lock (weakReference) + if (!weakReference.IsAlive) + _innerDictionary.TryRemove(pair.Key, out _); + } + } + + public bool TryAdd(TKey key, TValue value) + { + if (key == null) + throw new ArgumentNullException(nameof(key)); + + var weakReference = _innerDictionary.GetOrAdd(key, _createWeakReference); + + if (weakReference.IsAlive) + return false; + + lock (weakReference) + { + if (weakReference.IsAlive) + return false; + + weakReference.Target = value; + + // In the expected case, we will find a WeakReference for our key, which is the exact + // WeakReference we just set. + WeakReference oldWeakReference; + if (_innerDictionary.TryGetValue(key, out oldWeakReference)) + return oldWeakReference == weakReference; + + // If that's not the case, that means that while we found a WeakReference and decided to set + // it, another thread decided to remove our weak-reference. It doesn't matter if they added + // a different WeakReference or not. We are just going to try to re-add our weakReference, + // and return if we succeeded (so our weakReference is the valid one) or not (so, the new + // one that was added is the one that stays and ours is useless). + return _innerDictionary.TryAdd(key, weakReference); + } + } + + public TValue GetOrAdd(TKey key, Func createValue) + { + if (key == null) + throw new ArgumentNullException(nameof(key)); + + while (true) + { + // NO-WEAK-REFERENCE-YET. + var weakReference = _innerDictionary.GetOrAdd(key, _createWeakReference); + + while (true) + { + // CHECKING-EXISTING-WEAK-REFERENCE + var untypedResult = weakReference.Target; + if (untypedResult != null) + return (TValue)untypedResult; + + lock (weakReference) + { + // Check again as a value might have been added while we tried to lock. + untypedResult = weakReference.Target; + if (untypedResult != null) + return (TValue)untypedResult; + + // This might look as a very odd thing to do, but we want to guarantee that we do not + // created duplicated values when dealing with our own collection mechanism. So, if a + // weak-reference was removed, we need to try to re-add it. If we can't, we try to get + // the existing one by letting the loop run. + WeakReference existingWeakReference; + _innerDictionary.TryGetValue(key, out existingWeakReference); + if (existingWeakReference != weakReference) + { + // If the existing weak reference is not null, that means we simply should ignore + // ours. + if (existingWeakReference != null) + { + // Changing weakReference here shouldn't affect the lock/unlock logic... C# and + // .NET are prepared to lock/unlock the same object even if the variable contents + // changed. In fact the disabled warning tells us that the unlock will happen on the + // original value, which is what we want. + // So, here we just want to go back to where untypedResult is set using the new + // weakRefernce value. That is, we go back to (CHECKING-EXISTING-WEAK-REFERENCE). +#pragma warning disable CS0728 + weakReference = existingWeakReference; +#pragma warning restore CS0728 + continue; + } + + // As the existing was null, we try to re-add it. If we can, we proceed, if not, we + // need to retry the entire process. + if (!_innerDictionary.TryAdd(key, weakReference)) + break; // Means we will evaluate weakReference again. Go to NO-WEAK-REFERENCE-YET. + } + + // If we got to this point, our weakReference is guaranteed to still be in the + // dictionary and it cannot be removed as to remove it, we need to lock it, and we + // already hold the lock. So, from now on we just create and set the value that we are + // going to return. + var result = createValue(key); + weakReference.Target = result; + return result; + } + } + } + } + + public TValue TryGetValue(TKey key) + { + if (key == null) + throw new ArgumentNullException(nameof(key)); + + WeakReference weakReference; + if (!_innerDictionary.TryGetValue(key, out weakReference)) + return null; + + return (TValue)weakReference.Target; + } + + public bool Remove(TKey key) + { + if (key == null) + throw new ArgumentNullException(nameof(key)); + + return _innerDictionary.TryRemove(key, out _); + } + } +} diff --git a/Assets/ARDK/Utilities/Collections/_WeakValueDictionary.cs.meta b/Assets/ARDK/Utilities/Collections/_WeakValueDictionary.cs.meta new file mode 100644 index 0000000..e999ac9 --- /dev/null +++ b/Assets/ARDK/Utilities/Collections/_WeakValueDictionary.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b67ef421fe42145c78a98ae033fabb7f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/Extensions.meta b/Assets/ARDK/Utilities/Extensions.meta new file mode 100644 index 0000000..022cacb --- /dev/null +++ b/Assets/ARDK/Utilities/Extensions.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 0a75144ec22224ab7977756b09059d86 +folderAsset: yes +timeCreated: 1547253670 +licenseType: Pro +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/Extensions/_AssetDatabaseExtension.cs b/Assets/ARDK/Utilities/Extensions/_AssetDatabaseExtension.cs new file mode 100644 index 0000000..51b5291 --- /dev/null +++ b/Assets/ARDK/Utilities/Extensions/_AssetDatabaseExtension.cs @@ -0,0 +1,74 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +#if UNITY_EDITOR +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +namespace Niantic.ARDK.Utilities.Extensions +{ + internal static class _AssetDatabaseExtension + { + public struct Prefab + { + public string Guid; + public string Name; + + public Prefab(string guid, string name) + { + Guid = guid; + Name = name; + } + } + + /// Search the asset database for prefabs. + public static Prefab[] FindPrefabsWithComponent(params string[] searchInFolders) + { + var prefabs = new List(); + + if (searchInFolders.Length == 0) + searchInFolders = new string[] { "Assets" }; + + var guids = AssetDatabase.FindAssets("t:prefab", searchInFolders); + + foreach (var guid in guids) + { + var path = AssetDatabase.GUIDToAssetPath(guid); + var asset = AssetDatabase.LoadMainAssetAtPath(path); + + var prefab = asset as GameObject; + if (prefab == null) + continue; + + var comp = prefab.GetComponent(); + if (comp != null) + { + prefabs.Add(new Prefab(guid, asset.name)); + } + } + + return prefabs.ToArray(); + } + + + public static T[] FindAssets(params string[] searchInFolders) + where T: class + { + var assets = new List(); + + if (searchInFolders.Length == 0) + searchInFolders = new string[] { "Assets" }; + + var guids = AssetDatabase.FindAssets("t:" + typeof(T), searchInFolders); + + foreach (var guid in guids) + { + var path = AssetDatabase.GUIDToAssetPath(guid); + var asset = AssetDatabase.LoadMainAssetAtPath(path); + assets.Add(asset as T); + } + + return assets.ToArray(); + } + } +} +#endif \ No newline at end of file diff --git a/Assets/ARDK/Utilities/Extensions/_AssetDatabaseExtension.cs.meta b/Assets/ARDK/Utilities/Extensions/_AssetDatabaseExtension.cs.meta new file mode 100644 index 0000000..442ed51 --- /dev/null +++ b/Assets/ARDK/Utilities/Extensions/_AssetDatabaseExtension.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 0bb2a9f082e349b7bb996a891d3b1db7 +timeCreated: 1644252052 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/Extensions/_DictionaryExtensions.cs b/Assets/ARDK/Utilities/Extensions/_DictionaryExtensions.cs new file mode 100644 index 0000000..cb42349 --- /dev/null +++ b/Assets/ARDK/Utilities/Extensions/_DictionaryExtensions.cs @@ -0,0 +1,94 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; + +namespace Niantic.ARDK.Utilities.Extensions +{ + /// Offers alternative get behaviours for dictionaries + internal static class _DictionaryExtensions + { + /// + /// Gets a value from a dictionary, or gives the default(TValue) if it cannot be found. + /// + public static TValue GetOrDefault(this Dictionary dict, TKey key) + { + TValue value; + dict.TryGetValue(key, out value); + return value; + } + + /// Gets a value from a dictionary, or gives the default if it cannot be found. + public static TValue GetOrDefault + ( + this Dictionary dict, + TKey key, + Func defaultFetcher + ) + { + TValue value; + + if (dict.TryGetValue(key, out value)) + return value; + + return defaultFetcher != null ? defaultFetcher() : default(TValue); + } + + /// Gets a value from a dictionary, or creates a new value. + /// The new value will be inserted into the dictionary. + public static TValue GetOrInsert + ( + this Dictionary dict, + TKey key, + Func creator + ) + { + TValue value; + + if (!dict.TryGetValue(key, out value)) + { + value = creator(); + dict.Add(key, value); + } + + return value; + } + + /// Gets a value from a dictionary, or inserts the provided new value. + /// The new value will be inserted into the dictionary. + public static TValue GetOrInsert + ( + this Dictionary dict, + TKey key, + TValue valueToInsert + ) + { + TValue value; + + if (!dict.TryGetValue(key, out value)) + { + value = valueToInsert; + dict.Add(key, value); + } + + return value; + } + + /// Gets a value from a dictionary, or creates a new value using its default constructor. + /// The new value will be inserted into the dictionary. + public static TValue GetOrInsertNew(this Dictionary dict, TKey key) + where + TValue: new() + { + TValue value; + + if (!dict.TryGetValue(key, out value)) + { + value = new TValue(); + dict.Add(key, value); + } + + return value; + } + } +} diff --git a/Assets/ARDK/Utilities/Extensions/_DictionaryExtensions.cs.meta b/Assets/ARDK/Utilities/Extensions/_DictionaryExtensions.cs.meta new file mode 100644 index 0000000..3442636 --- /dev/null +++ b/Assets/ARDK/Utilities/Extensions/_DictionaryExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cd6a190216efa4e348d27285162b2632 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/Extensions/_GuidExtensions.cs b/Assets/ARDK/Utilities/Extensions/_GuidExtensions.cs new file mode 100644 index 0000000..522924e --- /dev/null +++ b/Assets/ARDK/Utilities/Extensions/_GuidExtensions.cs @@ -0,0 +1,22 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +namespace Niantic.ARDK.Utilities.Extensions +{ + /// Extends the behaviour of Guids + internal static class _GuidExtensions + { + /// Combine two Guids to deterministically create a new Guid + public static Guid Combine(this Guid guid, Guid other) + { + var bytesThis = guid.ToByteArray(); + var bytesOther = other.ToByteArray(); + + for (var i = 0; i < bytesThis.Length; i++) + bytesThis[i] ^= bytesOther[i]; + + return new Guid(bytesThis); + } + } +} diff --git a/Assets/ARDK/Utilities/Extensions/_GuidExtensions.cs.meta b/Assets/ARDK/Utilities/Extensions/_GuidExtensions.cs.meta new file mode 100644 index 0000000..0358f39 --- /dev/null +++ b/Assets/ARDK/Utilities/Extensions/_GuidExtensions.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c53dfa883bf64290bfba029f561dd83a +timeCreated: 1565395537 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/Extensions/_ObjectSerializationExtensions.cs b/Assets/ARDK/Utilities/Extensions/_ObjectSerializationExtensions.cs new file mode 100644 index 0000000..673fa44 --- /dev/null +++ b/Assets/ARDK/Utilities/Extensions/_ObjectSerializationExtensions.cs @@ -0,0 +1,37 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.IO; + +using Niantic.ARDK.Utilities.BinarySerialization; + +namespace Niantic.ARDK.Utilities.Extensions +{ + internal static class _ObjectSerializationExtensions + { + public static byte[] SerializeToArray(this object obj) + { + if (obj == null) + return null; + + using (var stream = new MemoryStream()) + { + GlobalSerializer.Serialize(stream, obj); + return stream.ToArray(); + } + } + + public static T DeserializeFromArray(this byte[] byteArray) + where + T: class + { + if (byteArray == null) + return null; + + using (var stream = new MemoryStream(byteArray)) + { + var obj = (T)GlobalSerializer.Deserialize(stream); + return obj; + } + } + } +} diff --git a/Assets/ARDK/Utilities/Extensions/_ObjectSerializationExtensions.cs.meta b/Assets/ARDK/Utilities/Extensions/_ObjectSerializationExtensions.cs.meta new file mode 100644 index 0000000..fa981ac --- /dev/null +++ b/Assets/ARDK/Utilities/Extensions/_ObjectSerializationExtensions.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 2007866630ff842a38821897c505441d +timeCreated: 1525206758 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/Extensions/_StreamExtensions.cs b/Assets/ARDK/Utilities/Extensions/_StreamExtensions.cs new file mode 100644 index 0000000..e1519d9 --- /dev/null +++ b/Assets/ARDK/Utilities/Extensions/_StreamExtensions.cs @@ -0,0 +1,60 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.IO; + +namespace Niantic.ARDK.Utilities.Extensions +{ + // Extensions to the Stream class. + // Considering Stream already throws in many situations, this class adds methods to either + // read data or throw, instead of returning magic values or similar. + internal static class _StreamExtensions + { + /// Reads a single byte from the stream, or throws if there are no more bytes to read. + /// This way, we don't need to deal with a possible -1 (returned as int) when for our + /// code the entire action should succeed or throw. + public static byte ReadByteOrThrow(this Stream stream) + { + if (stream == null) + throw new ArgumentNullException(nameof(stream)); + + int result = stream.ReadByte(); + if (result == -1) + throw new IOException("End of stream encountered when we still needed more data."); + + return (byte)result; + } + + /// Reads length bytes from stream, putting it into buffer, starting at startIndex. + /// Either the entire amount is read, or an exception is thrown, so there's no need to evaluate + /// results and update the startIndex/length in a future call, like it is required when using + /// the default stream.Read method. + public static void ReadOrThrow(this Stream stream, byte[] buffer, int startIndex, int length) + { + if (stream == null) + throw new ArgumentNullException(nameof(stream)); + + if (buffer == null) + throw new ArgumentNullException(nameof(buffer)); + + if (startIndex > buffer.Length || startIndex < 0) + throw new ArgumentOutOfRangeException(nameof(startIndex)); + + if (length < 0 || startIndex + length > buffer.Length) + throw new ArgumentOutOfRangeException(nameof(length)); + + while (length > 0) + { + int read = stream.Read(buffer, startIndex, length); + if (read == 0) + throw new IOException("Could not read the entire required buffer."); + + if (read < 0) + throw new IOException("Error reading the current buffer."); + + startIndex += read; + length -= read; + } + } + } +} diff --git a/Assets/ARDK/Utilities/Extensions/_StreamExtensions.cs.meta b/Assets/ARDK/Utilities/Extensions/_StreamExtensions.cs.meta new file mode 100644 index 0000000..18ef511 --- /dev/null +++ b/Assets/ARDK/Utilities/Extensions/_StreamExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e162a7d9d01694ab09c9ecbc5df460ea +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/Extensions/_TextureExtensions.cs b/Assets/ARDK/Utilities/Extensions/_TextureExtensions.cs new file mode 100644 index 0000000..3459ea7 --- /dev/null +++ b/Assets/ARDK/Utilities/Extensions/_TextureExtensions.cs @@ -0,0 +1,26 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using UnityEngine; + +namespace Niantic.ARDK.Utilities.Extensions +{ + /// Generates additional Texture2Ds that are not supported by default + internal static class _TextureExtensions + { + /// Generates a gray texture. + /// @note + /// This class is mainly used to generate a black texture in the YCbCr format. Set the + /// 'TextureY' field to Texture2D.black and the 'TextureCbCr' to this texture to get black. + public static Texture2D gray + { + get + { + var texture = new Texture2D(2, 2); + texture.SetPixels(new[] {Color.gray, Color.gray, Color.gray, Color.gray}); + texture.Apply(); + + return texture; + } + } + } +} diff --git a/Assets/ARDK/Utilities/Extensions/_TextureExtensions.cs.meta b/Assets/ARDK/Utilities/Extensions/_TextureExtensions.cs.meta new file mode 100644 index 0000000..dbdc75a --- /dev/null +++ b/Assets/ARDK/Utilities/Extensions/_TextureExtensions.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: bffb9b582c4f457b88309c31e7386ed7 +timeCreated: 1547511219 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/Input.meta b/Assets/ARDK/Utilities/Input.meta new file mode 100644 index 0000000..65ceaf7 --- /dev/null +++ b/Assets/ARDK/Utilities/Input.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 652479a39b8214260ba6114a43ea15ae +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/Input/InputSystem.meta b/Assets/ARDK/Utilities/Input/InputSystem.meta new file mode 100644 index 0000000..d04b260 --- /dev/null +++ b/Assets/ARDK/Utilities/Input/InputSystem.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b3658fee1408f4417892b096aa0ae2ed +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/Input/InputSystem/InputInteractionHandler.cs b/Assets/ARDK/Utilities/Input/InputSystem/InputInteractionHandler.cs new file mode 100644 index 0000000..68a2ccc --- /dev/null +++ b/Assets/ARDK/Utilities/Input/InputSystem/InputInteractionHandler.cs @@ -0,0 +1,38 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +#if ENABLE_INPUT_SYSTEM +using UnityEngine; +using UnityEngine.InputSystem; + +namespace Niantic.ARDK.Utilities.Input.InputSystem +{ + public class InputInteractionHandler : MonoBehaviour + { + private InputInteractions _inputInteractions; + + public delegate void StartPrimaryTouch(Vector2 position); + public event StartPrimaryTouch OnStartPrimaryTouch; + + private void Awake() + { + _inputInteractions = new InputInteractions(); + _inputInteractions.Player.LeftClick.performed += StartTouchOnDetection; + } + + private void StartTouchOnDetection(InputAction.CallbackContext obj) + { + var position = _inputInteractions.Player.TouchPosition.ReadValue(); + OnStartPrimaryTouch?.Invoke(position); + } + + private void OnEnable() + { + _inputInteractions.Enable(); + } + + private void OnDisable() + { + _inputInteractions.Disable(); + } + } +} +#endif \ No newline at end of file diff --git a/Assets/ARDK/Utilities/Input/InputSystem/InputInteractionHandler.cs.meta b/Assets/ARDK/Utilities/Input/InputSystem/InputInteractionHandler.cs.meta new file mode 100644 index 0000000..9ec2a90 --- /dev/null +++ b/Assets/ARDK/Utilities/Input/InputSystem/InputInteractionHandler.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: aa2379b82e4cf437084eda5f43e5010f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/Input/InputSystem/InputInteractions.cs b/Assets/ARDK/Utilities/Input/InputSystem/InputInteractions.cs new file mode 100644 index 0000000..16e27d9 --- /dev/null +++ b/Assets/ARDK/Utilities/Input/InputSystem/InputInteractions.cs @@ -0,0 +1,282 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +//------------------------------------------------------------------------------ +// +// This code was auto-generated by com.unity.inputsystem:InputActionCodeGenerator +// version 1.3.0 +// from Assets/ARDK/Utilities/Input/InputSystem/InputInteractions.inputactions +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ +#if ENABLE_INPUT_SYSTEM + +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine.InputSystem; +using UnityEngine.InputSystem.Utilities; + +namespace Niantic.ARDK.Utilities.Input.InputSystem +{ + public partial class @InputInteractions : IInputActionCollection2, IDisposable + { + public InputActionAsset asset { get; } + public @InputInteractions() + { + asset = InputActionAsset.FromJson(@"{ + ""name"": ""InputInteractions"", + ""maps"": [ + { + ""name"": ""Player"", + ""id"": ""d231b2ca-f5c1-4a92-8cc6-173aef1526e9"", + ""actions"": [ + { + ""name"": ""Point"", + ""type"": ""Value"", + ""id"": ""a1fa0d4f-297a-46aa-9a33-cfe41443f9e8"", + ""expectedControlType"": ""Vector2"", + ""processors"": """", + ""interactions"": """", + ""initialStateCheck"": true + }, + { + ""name"": ""LeftClick"", + ""type"": ""PassThrough"", + ""id"": ""9b7465e1-cad9-4078-a8b0-688ff9a2da35"", + ""expectedControlType"": ""Button"", + ""processors"": """", + ""interactions"": """", + ""initialStateCheck"": false + }, + { + ""name"": ""RightClick"", + ""type"": ""PassThrough"", + ""id"": ""dcc106e1-eb80-4bb2-91a4-ecf60546c4ab"", + ""expectedControlType"": ""Button"", + ""processors"": """", + ""interactions"": """", + ""initialStateCheck"": false + }, + { + ""name"": ""TouchPosition"", + ""type"": ""PassThrough"", + ""id"": ""e0441f73-83f6-451b-ba30-1d91c0246619"", + ""expectedControlType"": ""Vector2"", + ""processors"": """", + ""interactions"": """", + ""initialStateCheck"": false + } + ], + ""bindings"": [ + { + ""name"": """", + ""id"": ""aa86c666-6a12-4426-8a14-94ace7013c6e"", + ""path"": ""/position"", + ""interactions"": """", + ""processors"": """", + ""groups"": """", + ""action"": ""Point"", + ""isComposite"": false, + ""isPartOfComposite"": false + }, + { + ""name"": """", + ""id"": ""0dffa5e1-8411-487d-baba-c1169779f7f6"", + ""path"": ""/position"", + ""interactions"": """", + ""processors"": """", + ""groups"": """", + ""action"": ""Point"", + ""isComposite"": false, + ""isPartOfComposite"": false + }, + { + ""name"": """", + ""id"": ""1290515d-73b0-4d57-ac3d-5dd8dbdb659a"", + ""path"": ""/leftButton"", + ""interactions"": """", + ""processors"": """", + ""groups"": """", + ""action"": ""LeftClick"", + ""isComposite"": false, + ""isPartOfComposite"": false + }, + { + ""name"": """", + ""id"": ""b62a7e47-06c6-404d-89e0-794908d46761"", + ""path"": ""/Press"", + ""interactions"": """", + ""processors"": """", + ""groups"": """", + ""action"": ""LeftClick"", + ""isComposite"": false, + ""isPartOfComposite"": false + }, + { + ""name"": """", + ""id"": ""132a1b09-41e3-4845-b6a5-f0cbbc9cf634"", + ""path"": ""/rightButton"", + ""interactions"": """", + ""processors"": """", + ""groups"": """", + ""action"": ""RightClick"", + ""isComposite"": false, + ""isPartOfComposite"": false + }, + { + ""name"": """", + ""id"": ""1178a903-8e80-440d-8c73-8da1812feb40"", + ""path"": ""/primaryTouch/position"", + ""interactions"": """", + ""processors"": """", + ""groups"": """", + ""action"": ""TouchPosition"", + ""isComposite"": false, + ""isPartOfComposite"": false + }, + { + ""name"": """", + ""id"": ""dc59e80f-7900-4f79-9e71-91a14ea1c863"", + ""path"": ""/position"", + ""interactions"": """", + ""processors"": """", + ""groups"": """", + ""action"": ""TouchPosition"", + ""isComposite"": false, + ""isPartOfComposite"": false + } + ] + } + ], + ""controlSchemes"": [] +}"); + // Player + m_Player = asset.FindActionMap("Player", throwIfNotFound: true); + m_Player_Point = m_Player.FindAction("Point", throwIfNotFound: true); + m_Player_LeftClick = m_Player.FindAction("LeftClick", throwIfNotFound: true); + m_Player_RightClick = m_Player.FindAction("RightClick", throwIfNotFound: true); + m_Player_TouchPosition = m_Player.FindAction("TouchPosition", throwIfNotFound: true); + } + + public void Dispose() + { + UnityEngine.Object.Destroy(asset); + } + + public InputBinding? bindingMask + { + get => asset.bindingMask; + set => asset.bindingMask = value; + } + + public ReadOnlyArray? devices + { + get => asset.devices; + set => asset.devices = value; + } + + public ReadOnlyArray controlSchemes => asset.controlSchemes; + + public bool Contains(InputAction action) + { + return asset.Contains(action); + } + + public IEnumerator GetEnumerator() + { + return asset.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public void Enable() + { + asset.Enable(); + } + + public void Disable() + { + asset.Disable(); + } + public IEnumerable bindings => asset.bindings; + + public InputAction FindAction(string actionNameOrId, bool throwIfNotFound = false) + { + return asset.FindAction(actionNameOrId, throwIfNotFound); + } + public int FindBinding(InputBinding bindingMask, out InputAction action) + { + return asset.FindBinding(bindingMask, out action); + } + + // Player + private readonly InputActionMap m_Player; + private IPlayerActions m_PlayerActionsCallbackInterface; + private readonly InputAction m_Player_Point; + private readonly InputAction m_Player_LeftClick; + private readonly InputAction m_Player_RightClick; + private readonly InputAction m_Player_TouchPosition; + public struct PlayerActions + { + private @InputInteractions m_Wrapper; + public PlayerActions(@InputInteractions wrapper) { m_Wrapper = wrapper; } + public InputAction @Point => m_Wrapper.m_Player_Point; + public InputAction @LeftClick => m_Wrapper.m_Player_LeftClick; + public InputAction @RightClick => m_Wrapper.m_Player_RightClick; + public InputAction @TouchPosition => m_Wrapper.m_Player_TouchPosition; + public InputActionMap Get() { return m_Wrapper.m_Player; } + public void Enable() { Get().Enable(); } + public void Disable() { Get().Disable(); } + public bool enabled => Get().enabled; + public static implicit operator InputActionMap(PlayerActions set) { return set.Get(); } + public void SetCallbacks(IPlayerActions instance) + { + if (m_Wrapper.m_PlayerActionsCallbackInterface != null) + { + @Point.started -= m_Wrapper.m_PlayerActionsCallbackInterface.OnPoint; + @Point.performed -= m_Wrapper.m_PlayerActionsCallbackInterface.OnPoint; + @Point.canceled -= m_Wrapper.m_PlayerActionsCallbackInterface.OnPoint; + @LeftClick.started -= m_Wrapper.m_PlayerActionsCallbackInterface.OnLeftClick; + @LeftClick.performed -= m_Wrapper.m_PlayerActionsCallbackInterface.OnLeftClick; + @LeftClick.canceled -= m_Wrapper.m_PlayerActionsCallbackInterface.OnLeftClick; + @RightClick.started -= m_Wrapper.m_PlayerActionsCallbackInterface.OnRightClick; + @RightClick.performed -= m_Wrapper.m_PlayerActionsCallbackInterface.OnRightClick; + @RightClick.canceled -= m_Wrapper.m_PlayerActionsCallbackInterface.OnRightClick; + @TouchPosition.started -= m_Wrapper.m_PlayerActionsCallbackInterface.OnTouchPosition; + @TouchPosition.performed -= m_Wrapper.m_PlayerActionsCallbackInterface.OnTouchPosition; + @TouchPosition.canceled -= m_Wrapper.m_PlayerActionsCallbackInterface.OnTouchPosition; + } + m_Wrapper.m_PlayerActionsCallbackInterface = instance; + if (instance != null) + { + @Point.started += instance.OnPoint; + @Point.performed += instance.OnPoint; + @Point.canceled += instance.OnPoint; + @LeftClick.started += instance.OnLeftClick; + @LeftClick.performed += instance.OnLeftClick; + @LeftClick.canceled += instance.OnLeftClick; + @RightClick.started += instance.OnRightClick; + @RightClick.performed += instance.OnRightClick; + @RightClick.canceled += instance.OnRightClick; + @TouchPosition.started += instance.OnTouchPosition; + @TouchPosition.performed += instance.OnTouchPosition; + @TouchPosition.canceled += instance.OnTouchPosition; + } + } + } + public PlayerActions @Player => new PlayerActions(this); + public interface IPlayerActions + { + void OnPoint(InputAction.CallbackContext context); + void OnLeftClick(InputAction.CallbackContext context); + void OnRightClick(InputAction.CallbackContext context); + void OnTouchPosition(InputAction.CallbackContext context); + } + } +} + +#endif diff --git a/Assets/ARDK/Utilities/Input/InputSystem/InputInteractions.cs.meta b/Assets/ARDK/Utilities/Input/InputSystem/InputInteractions.cs.meta new file mode 100644 index 0000000..dad9b95 --- /dev/null +++ b/Assets/ARDK/Utilities/Input/InputSystem/InputInteractions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ea68fb06dc7f4463fa121bca60042dec +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/Input/InputSystem/InputInteractions.inputactions b/Assets/ARDK/Utilities/Input/InputSystem/InputInteractions.inputactions new file mode 100644 index 0000000..84ff867 --- /dev/null +++ b/Assets/ARDK/Utilities/Input/InputSystem/InputInteractions.inputactions @@ -0,0 +1,127 @@ +{ + "name": "InputInteractions", + "maps": [ + { + "name": "Player", + "id": "d231b2ca-f5c1-4a92-8cc6-173aef1526e9", + "actions": [ + { + "name": "Point", + "type": "Value", + "id": "a1fa0d4f-297a-46aa-9a33-cfe41443f9e8", + "expectedControlType": "Vector2", + "processors": "", + "interactions": "", + "initialStateCheck": true + }, + { + "name": "LeftClick", + "type": "PassThrough", + "id": "9b7465e1-cad9-4078-a8b0-688ff9a2da35", + "expectedControlType": "Button", + "processors": "", + "interactions": "", + "initialStateCheck": false + }, + { + "name": "RightClick", + "type": "PassThrough", + "id": "dcc106e1-eb80-4bb2-91a4-ecf60546c4ab", + "expectedControlType": "Button", + "processors": "", + "interactions": "", + "initialStateCheck": false + }, + { + "name": "TouchPosition", + "type": "PassThrough", + "id": "e0441f73-83f6-451b-ba30-1d91c0246619", + "expectedControlType": "Vector2", + "processors": "", + "interactions": "", + "initialStateCheck": false + } + ], + "bindings": [ + { + "name": "", + "id": "aa86c666-6a12-4426-8a14-94ace7013c6e", + "path": "/position", + "interactions": "", + "processors": "", + "groups": "", + "action": "Point", + "isComposite": false, + "isPartOfComposite": false + }, + { + "name": "", + "id": "0dffa5e1-8411-487d-baba-c1169779f7f6", + "path": "/position", + "interactions": "", + "processors": "", + "groups": "", + "action": "Point", + "isComposite": false, + "isPartOfComposite": false + }, + { + "name": "", + "id": "1290515d-73b0-4d57-ac3d-5dd8dbdb659a", + "path": "/leftButton", + "interactions": "", + "processors": "", + "groups": "", + "action": "LeftClick", + "isComposite": false, + "isPartOfComposite": false + }, + { + "name": "", + "id": "b62a7e47-06c6-404d-89e0-794908d46761", + "path": "/Press", + "interactions": "", + "processors": "", + "groups": "", + "action": "LeftClick", + "isComposite": false, + "isPartOfComposite": false + }, + { + "name": "", + "id": "132a1b09-41e3-4845-b6a5-f0cbbc9cf634", + "path": "/rightButton", + "interactions": "", + "processors": "", + "groups": "", + "action": "RightClick", + "isComposite": false, + "isPartOfComposite": false + }, + { + "name": "", + "id": "1178a903-8e80-440d-8c73-8da1812feb40", + "path": "/primaryTouch/position", + "interactions": "", + "processors": "", + "groups": "", + "action": "TouchPosition", + "isComposite": false, + "isPartOfComposite": false + }, + { + "name": "", + "id": "dc59e80f-7900-4f79-9e71-91a14ea1c863", + "path": "/position", + "interactions": "", + "processors": "", + "groups": "", + "action": "TouchPosition", + "isComposite": false, + "isPartOfComposite": false + } + ] + } + ], + "controlSchemes": [] +} \ No newline at end of file diff --git a/Assets/ARDK/Utilities/Input/InputSystem/InputInteractions.inputactions.meta b/Assets/ARDK/Utilities/Input/InputSystem/InputInteractions.inputactions.meta new file mode 100644 index 0000000..d034759 --- /dev/null +++ b/Assets/ARDK/Utilities/Input/InputSystem/InputInteractions.inputactions.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: db2e6a4dc658147b2aaa6c35ed3b3807 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 11500000, guid: 8404be70184654265930450def6a9037, type: 3} + generateWrapperCode: 0 + wrapperCodePath: + wrapperClassName: + wrapperCodeNamespace: Niantic.ARDK.Utilities.Input.InputSystem diff --git a/Assets/ARDK/Utilities/Input/Legacy.meta b/Assets/ARDK/Utilities/Input/Legacy.meta new file mode 100644 index 0000000..a065217 --- /dev/null +++ b/Assets/ARDK/Utilities/Input/Legacy.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9d429391cd3994cbebe29f0bb3f85ab7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/Input/Legacy/PlatformAgnosticInput.cs b/Assets/ARDK/Utilities/Input/Legacy/PlatformAgnosticInput.cs new file mode 100644 index 0000000..f58b684 --- /dev/null +++ b/Assets/ARDK/Utilities/Input/Legacy/PlatformAgnosticInput.cs @@ -0,0 +1,145 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +#if ENABLE_LEGACY_INPUT_MANAGER +using System.Collections.Generic; + +using UnityEngine; +using UnityEngine.EventSystems; + +namespace Niantic.ARDK.Utilities.Input.Legacy +{ + /// Cross-platform class that unifies Unity's mouse and Touch input APIs. + /// @note + /// When run in the Unity Editor, the class will convert mouse input changes into touch input. + /// When run natively on a mobile device, the class will simply surface Input.GetTouch, + /// Input.touchCount, etc. + public static class PlatformAgnosticInput + { + // (Basically) a state machine used to track mouse drags, persistent touches, etc. + private class MouseEventBuffer + { + public void Update(TouchPhase touchPhase, Vector2 mousePosition) + { + if (_lastFrame == Time.frameCount) + return; // Already updated this frame + + _lastFrame = Time.frameCount; + + _touchPhase = touchPhase; + + switch (touchPhase) + { + case TouchPhase.Began: + _currentDelta = Vector2.zero; + _priorPosition = mousePosition; + break; + + default: + // Movement. + _currentDelta = mousePosition - _priorPosition; + _priorPosition = mousePosition; + if (touchPhase == TouchPhase.Moved) + { + _touchPhase = + (_currentDelta == Vector2.zero) + ? TouchPhase.Stationary + : TouchPhase.Moved; + } + + break; + } + } + + public Touch GetTouch() + { + var touch = + new Touch + { + fingerId = 1, + phase = _touchPhase, + position = _priorPosition, + deltaPosition = _currentDelta + }; + + return touch; + } + + private TouchPhase _touchPhase; + private Vector2 _priorPosition; + private Vector2 _currentDelta; + + private int _lastFrame; + } + + private static readonly MouseEventBuffer _mouseEventBuffer = new MouseEventBuffer(); + + + /// The number of touches. + public static int touchCount + { + get + { + if (Application.isMobilePlatform) + return UnityEngine.Input.touchCount; + + var m0 = KeyCode.Mouse0; + return (UnityEngine.Input.GetKey(m0) || UnityEngine.Input.GetKeyDown(m0) || UnityEngine.Input.GetKeyUp(m0)) ? 1 : 0; + } + } + + /// Call to obtain the status of a finger touching the screen. + /// @param index + /// The touch input on the device screen. If touchCount is greater than zero, this parameter + /// sets which screen touch to check. Use zero to obtain the first screen touch. + /// @returns Touch details as a struct. + public static Touch GetTouch(int index) + { + return Application.isMobilePlatform ? UnityEngine.Input.GetTouch(index) : _TouchFromMouse(); + } + + /// Determines if a specific touch is over any UI raycast targets. + /// Useful for discounting screen touches before processing them as gestures. + public static bool IsTouchOverUIObject(this Touch touch) + { + var eventDataCurrentPosition = + new PointerEventData(EventSystem.current) + { + position = new Vector2(touch.position.x, touch.position.y) + }; + + var results = new List(); + EventSystem.current.RaycastAll(eventDataCurrentPosition, results); + return results.Count > 0; + } + + private static Touch _TouchFromMouse() + { + var m0 = KeyCode.Mouse0; + var touch = new Touch(); + + // Send different state changes depending on the Mouse Click state... + if (UnityEngine.Input.GetKeyDown(m0)) + { + _mouseEventBuffer.Update(TouchPhase.Began, UnityEngine.Input.mousePosition); + touch = _mouseEventBuffer.GetTouch(); + } + else if (UnityEngine.Input.GetKeyUp(m0)) + { + _mouseEventBuffer.Update(TouchPhase.Ended, UnityEngine.Input.mousePosition); + touch = _mouseEventBuffer.GetTouch(); + } + else if (UnityEngine.Input.GetKey(m0)) + { + _mouseEventBuffer.Update(TouchPhase.Moved, UnityEngine.Input.mousePosition); + touch = _mouseEventBuffer.GetTouch(); + } + else + { + touch.phase = TouchPhase.Canceled; + } + + return touch; + } + } + +} +#endif diff --git a/Assets/ARDK/Utilities/Input/Legacy/PlatformAgnosticInput.cs.meta b/Assets/ARDK/Utilities/Input/Legacy/PlatformAgnosticInput.cs.meta new file mode 100644 index 0000000..48e66a6 --- /dev/null +++ b/Assets/ARDK/Utilities/Input/Legacy/PlatformAgnosticInput.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 9225a8912128a47f6885b7581243efa4 +timeCreated: 1527614704 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/Logging.meta b/Assets/ARDK/Utilities/Logging.meta new file mode 100644 index 0000000..df826d4 --- /dev/null +++ b/Assets/ARDK/Utilities/Logging.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e25c9fd34c384f7e8b6bba9a44192064 +timeCreated: 1597702257 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/Logging/ARLog.cs b/Assets/ARDK/Utilities/Logging/ARLog.cs new file mode 100644 index 0000000..ae9d8fe --- /dev/null +++ b/Assets/ARDK/Utilities/Logging/ARLog.cs @@ -0,0 +1,335 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Collections.Concurrent; +using System.Diagnostics; + +/// @namespace Niantic.ARDK.Utilities.Logging +/// @brief Handles debug logging for ARDK systems +namespace Niantic.ARDK.Utilities.Logging +{ + /// + /// Provides a common log for ARDK systems. + /// + public static class ARLog + { + private const string ARDK_LogMessage = "#{0}#: {1}"; + + private static IARLogHandler _logHandler = UnityARLogHandler.Instance; + /// + /// Gets or sets the log handler used by ARLog. + /// @note If no handler is set or null is passed in, ARLog will default to using UnityEngine's + /// Debug.Log. + /// + public static IARLogHandler LogHandler + { + get { return _logHandler; } + set + { + _StaticMemberValidator._FieldContainsSpecificValueWhenScopeEnds + ( + () => _logHandler, + UnityARLogHandler.Instance + ); + + if (value == null) + value = UnityARLogHandler.Instance; + + _logHandler = value; + } + } + + /// + /// Whether or not to enable logs that print every frame (peer messages, frame updates, etc) + /// Enabling this will decrease performance, as printing multiple logs per frame is expensive + /// + public static bool PerFrameLogsEnabled { get; set; } + + /// + /// Prints a debug level log. + /// + /// Log to print + /// Whether the log will occur every frame + [Conditional("ARDK_DEBUG")] + internal static void _Debug(string log, bool perFrame = false) + { + if(perFrame && !PerFrameLogsEnabled) + return; + + var caller = _GetCallerFromStack(2); + if (!_IsFeatureEnabled(caller)) + return; + + var str = String.Format(ARDK_LogMessage, caller, log); + _logHandler.Debug(str); + } + + /// + /// Prints a debug level log with String.Format. + /// + /// Formatted string to print + /// Whether the log will occur every frame + /// List of objects to format into the log + [Conditional("ARDK_DEBUG")] + internal static void _DebugFormat(string log, bool perFrame = false, params object[] objs) + { + if(perFrame && !PerFrameLogsEnabled) + return; + + var caller = _GetCallerFromStack(2); + if (!_IsFeatureEnabled(caller)) + return; + + var logFormat = String.Format(log, objs); + var str = String.Format(ARDK_LogMessage, caller, logFormat); + _logHandler.Debug(str); + } + + /// + /// Prints a warning level log. + /// + /// Warning to print + /// Whether the log will occur every frame + [Conditional("ARDK_DEBUG")] + internal static void _Warn(string log, bool perFrame = false) + { + if(perFrame && !PerFrameLogsEnabled) + return; + + var caller = _GetCallerFromStack(2); + if (!_IsFeatureEnabled(caller)) + return; + + var str = String.Format(ARDK_LogMessage, caller, log); + _logHandler.Warn(str); + } + + /// + /// Prints a warning level log with String.Format. + /// + /// Formatted string to print + /// Whether the log will occur every frame + /// List of objects to format into the log + [Conditional("ARDK_DEBUG")] + internal static void _WarnFormat(string log, bool perFrame = false, params object[] objs) + { + if(perFrame && !PerFrameLogsEnabled) + return; + + var caller = _GetCallerFromStack(2); + if (!_IsFeatureEnabled(caller)) + return; + + var logFormat = String.Format(log, objs); + var str = String.Format(ARDK_LogMessage, caller, logFormat); + _logHandler.Warn(str); + } + + /// + /// Prints a release level log. + /// + /// Log to print + /// Whether the log will occur every frame + internal static void _Release(string log, bool perFrame = false) + { + if(perFrame && !PerFrameLogsEnabled) + return; + + var caller = _GetCallerFromStack(2); + + var str = String.Format(ARDK_LogMessage, caller, log); + _logHandler.Release(str); + } + + /// + /// Prints a release level log with String.Format. + /// + /// Formatted string to print + /// Whether the log will occur every frame + /// List of objects to format into the log + internal static void _ReleaseFormat(string log, bool perFrame = false, params object[] objs) + { + if(perFrame && !PerFrameLogsEnabled) + return; + + var caller = _GetCallerFromStack(2); + + var logFormat = String.Format(log, objs); + var str = String.Format(ARDK_LogMessage, caller, logFormat); + _logHandler.Release(str); + } + + /// + /// Prints a release level warning log. + /// + /// Log to print + internal static void _WarnRelease(string log) + { + var caller = _GetCallerFromStack(2); + + var str = String.Format(ARDK_LogMessage, caller, log); + _logHandler.Warn(str); + } + + /// + /// Prints a release level warning log with String.Format. + /// + /// Formatted string to print + /// List of objects to format into the log + internal static void _WarnFormatRelease(string log, params object[] objs) + { + var caller = _GetCallerFromStack(2); + + var logFormat = String.Format(log, objs); + var str = String.Format(ARDK_LogMessage, caller, logFormat); + _logHandler.Warn(str); + } + + /// + /// Prints an error log. + /// + /// Error to print + internal static void _Error(string log) + { + var caller = _GetCallerFromStack(2); + + var str = String.Format(ARDK_LogMessage, caller, log); + _logHandler.Error(str); + } + + /// + /// Prints an error log with String.Format. + /// + /// Formatted error to print + /// List of objects to format into the log + internal static void _ErrorFormat(string log, params object[] objs) + { + var caller = _GetCallerFromStack(2); + + var logFormat = String.Format(log, objs); + var str = String.Format(ARDK_LogMessage, caller, logFormat); + _logHandler.Error(str); + } + + /// + /// Prints the contents of an exception and the provided context. Does not rethrow the exception + /// or halt execution. + /// + /// Exception to print + /// Context for the exception + internal static void _Exception(Exception exception, object context = null) + { + var message = "{0} from context: {1}"; + var str = String.Format(message, exception, context); + + _logHandler.Error(str); + } + + /// + /// Enable logging for a specific feature + /// + /// Feature to log + public static void EnableLogFeature(string feature) + { + _StaticMemberValidator._CollectionIsEmptyWhenScopeEnds(() => _enabledFeatures); + + var changed = _enabledFeatures.TryAdd(feature, true); + if (changed) + _cachedFeatureEnabledChecks.Clear(); + } + + /// + /// Enable logging for a set of features + /// + /// Features to log + public static void EnableLogFeatures(IEnumerable features) + { + _StaticMemberValidator._CollectionIsEmptyWhenScopeEnds(() => _enabledFeatures); + + bool changed = false; + foreach (var feature in features) + if (_enabledFeatures.TryAdd(feature, true)) + changed = true; + + if (changed) + _cachedFeatureEnabledChecks.Clear(); + } + + /// + /// Disable logging for a feature + /// + /// Feature to no longer log + public static void DisableLogFeature(string feature) + { + var changed = _enabledFeatures.TryRemove(feature, out _); + if(changed) + _cachedFeatureEnabledChecks.Clear(); + } + + /// + /// Disable logging for a set of features + /// + /// Features to no longer log + public static void DisableLogFeatures(IEnumerable features) + { + var changed = false; + + foreach (var feature in features) + if (_enabledFeatures.TryRemove(feature, out _)) + changed = true; + + if (changed) + _cachedFeatureEnabledChecks.Clear(); + } + + private static readonly ConcurrentDictionary _cachedFeatureEnabledChecks = + new ConcurrentDictionary(); + + // ConcurrentDictionary works better than a list for its lock free reading. + // Using a list + Contains instead of trie/radix tree to merge the API for now + // TODO: implement a fast multistring search solution + private static readonly ConcurrentDictionary _enabledFeatures = + new ConcurrentDictionary(); + + private static readonly Func _checkEnabledFeaturesDelegate = + (caller) => + { + foreach (var enabledFeature in _enabledFeatures.Keys) + if (caller.StartsWith(enabledFeature)) + return true; + + return false; + }; + + /// + /// Determine if the specified caller should display its logs + /// + /// + /// + private static bool _IsFeatureEnabled(string caller) + { + return _cachedFeatureEnabledChecks.GetOrAdd(caller, _checkEnabledFeaturesDelegate); + } + + /// + /// Gets the full name (Namespace.Class) of the method calling this. + /// + /// Level of nested-ness of this call. For example, to get the direct + /// caller of this method, the level would be 1. To get the caller that calls this through + /// a helper, the level would be 2. + /// A string with the full name of the calling class, or "Niantic.ARDK" if something fails + private static string _GetCallerFromStack(int nestedLevel) + { + // Get the frame above the current one (the caller of this method) + var callerFrame = new StackFrame(nestedLevel, false); + + var caller = callerFrame?.GetMethod()?.ReflectedType; + + if (caller == null) + return "Niantic.ARDK"; + + return caller.FullName; + } + } +} diff --git a/Assets/ARDK/Utilities/Logging/ARLog.cs.meta b/Assets/ARDK/Utilities/Logging/ARLog.cs.meta new file mode 100644 index 0000000..ff6954e --- /dev/null +++ b/Assets/ARDK/Utilities/Logging/ARLog.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 02167ccd14ba41c8a6b595cdebfb2154 +timeCreated: 1597702263 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/Logging/LogHandler.meta b/Assets/ARDK/Utilities/Logging/LogHandler.meta new file mode 100644 index 0000000..8a79acb --- /dev/null +++ b/Assets/ARDK/Utilities/Logging/LogHandler.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 26d64372b28c4c8e85f9a6fd8af86811 +timeCreated: 1597704300 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/Logging/LogHandler/IARLogHandler.cs b/Assets/ARDK/Utilities/Logging/LogHandler/IARLogHandler.cs new file mode 100644 index 0000000..94f2395 --- /dev/null +++ b/Assets/ARDK/Utilities/Logging/LogHandler/IARLogHandler.cs @@ -0,0 +1,35 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.Utilities.Logging +{ + /// + /// Interface for a log handler used by the ARLog. Implement this class to provide + /// alternative logging behaviour. + /// + public interface IARLogHandler + { + /// + /// Debug level log, only enabled if #ARDK_DEBUG is defined + /// + /// Log to print + void Debug(string log); + + /// + /// Warning level log, only enabled if #ARDK_DEBUG is defined + /// + /// Warning to print + void Warn(string warning); + + /// + /// Release level log, will still check against enabled features + /// + /// Log to print + void Release(string log); + + /// + /// Error level log, will always print + /// + /// Error to print + void Error(string error); + } +} diff --git a/Assets/ARDK/Utilities/Logging/LogHandler/IARLogHandler.cs.meta b/Assets/ARDK/Utilities/Logging/LogHandler/IARLogHandler.cs.meta new file mode 100644 index 0000000..40d80fd --- /dev/null +++ b/Assets/ARDK/Utilities/Logging/LogHandler/IARLogHandler.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 48f7e7384cf64e52b9d237ecaeea7e7c +timeCreated: 1597702651 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/Logging/LogHandler/UnityARLogHandler.cs b/Assets/ARDK/Utilities/Logging/LogHandler/UnityARLogHandler.cs new file mode 100644 index 0000000..ea141a7 --- /dev/null +++ b/Assets/ARDK/Utilities/Logging/LogHandler/UnityARLogHandler.cs @@ -0,0 +1,44 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using UnityEngine; + +namespace Niantic.ARDK.Utilities.Logging +{ + /// + /// Implementation of IARLogHandler that uses UnityEngine.Debug as its target + /// + public sealed class UnityARLogHandler: + IARLogHandler + { + /// Gets the singleton instance of this log handler. + public static readonly UnityARLogHandler Instance = new UnityARLogHandler(); + + private UnityARLogHandler() + { + } + + /// + public void Debug(string log) + { + UnityEngine.Debug.Log(log); + } + + /// + public void Warn(string log) + { + UnityEngine.Debug.LogWarning(log); + } + + /// + public void Release(string log) + { + UnityEngine.Debug.Log(log); + } + + /// + public void Error(string log) + { + UnityEngine.Debug.LogError(log); + } + } +} diff --git a/Assets/ARDK/Utilities/Logging/LogHandler/UnityARLogHandler.cs.meta b/Assets/ARDK/Utilities/Logging/LogHandler/UnityARLogHandler.cs.meta new file mode 100644 index 0000000..5b7d2a2 --- /dev/null +++ b/Assets/ARDK/Utilities/Logging/LogHandler/UnityARLogHandler.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5b05053dfe41471c8f0d97255eda4582 +timeCreated: 1597704312 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/Marker.meta b/Assets/ARDK/Utilities/Marker.meta new file mode 100644 index 0000000..aaf0dd6 --- /dev/null +++ b/Assets/ARDK/Utilities/Marker.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1fd3b464d38474335b517f1af8b871d6 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/Marker/ImageDataUtils.cs b/Assets/ARDK/Utilities/Marker/ImageDataUtils.cs new file mode 100644 index 0000000..e08e3e3 --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/ImageDataUtils.cs @@ -0,0 +1,67 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using UnityEngine; + +namespace Niantic.ARDK.Utilities.Marker +{ + /// @note This is part of an experimental feature that is not advised to be used in release builds. + public class ImageDataUtils + { + public enum TransformType + { + FlipHorizontal, + FlipVertical, + RotateClockwise, + RotateCounterclockwise + } + + public static T[] Transform(T[] original, TransformType type, int width, int height) + { + if (original.Length != width * height) + { + Debug.LogError("Dimensions of transformed array must match length of the original array."); + return null; + } + + var newCol = 0; + var newRow = 0; + var newWidth = width; + + var transformed = new T[original.Length]; + for (var col = 0; col < width; col++) + { + for (var row = 0; row < height; row++) + { + switch (type) + { + case TransformType.FlipVertical: + newCol = width - 1 - col; + newRow = row; + break; + + case TransformType.FlipHorizontal: + newCol = col; + newRow = height - 1 - row; + break; + + case TransformType.RotateClockwise: + newCol = height - 1 - row; + newRow = col; + newWidth = height; + break; + + case TransformType.RotateCounterclockwise: + newCol = row; + newRow = width - 1 - col; + newWidth = height; + break; + } + + transformed[newCol + (newRow * newWidth)] = original[col + (row * width)]; + } + } + + return transformed; + } + } +} diff --git a/Assets/ARDK/Utilities/Marker/ImageDataUtils.cs.meta b/Assets/ARDK/Utilities/Marker/ImageDataUtils.cs.meta new file mode 100644 index 0000000..626df48 --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/ImageDataUtils.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e262b195cee4408c9992517b8beda140 +timeCreated: 1576879942 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/Marker/Metadata.meta b/Assets/ARDK/Utilities/Marker/Metadata.meta new file mode 100644 index 0000000..17a61e0 --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/Metadata.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e35bf077066946b4bcf07b83c56e9b4a +timeCreated: 1583276009 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/Marker/Metadata/BasicMetadataSerializer.cs b/Assets/ARDK/Utilities/Marker/Metadata/BasicMetadataSerializer.cs new file mode 100644 index 0000000..6aef11b --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/Metadata/BasicMetadataSerializer.cs @@ -0,0 +1,72 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Linq; +using System.IO; + +using Niantic.ARDK.Utilities.Extensions; +using Niantic.ARDK.Networking.HLAPI.Data; +using Niantic.ARDK.Utilities.BinarySerialization; +using Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers; + +namespace Niantic.ARDK.Utilities.Marker +{ + /// Default IMetadataSerializer implementation for serializing and deserializing + /// MarkerMetadata as + /// 1. string SessionIdentifier + /// 2. MarkerSource Source + /// 3. byte[] Data (base) + public class BasicMetadataSerializer: + IMetadataSerializer + { + private static readonly BasicMetadataSerializer _instance = new BasicMetadataSerializer(); + + public static byte[] StaticSerialize(MarkerMetadata stationaryMetadata) + { + return _instance.Serialize(stationaryMetadata); + } + + public byte[] Serialize(MarkerMetadata metadata) + { + using (var stream = new MemoryStream(1024)) + { + using (var binarySerializer = new BinarySerializer(stream)) + { + StringSerializer.Instance.Serialize(binarySerializer, metadata.SessionIdentifier); + CompressedInt32Serializer.Instance.Serialize(binarySerializer, (int)metadata.Source); + CompressedInt32Serializer.Instance.Serialize(binarySerializer, metadata.Data.Length); + } + + var markerData = stream.ToArray(); + return markerData.Concat(metadata.Data).ToArray(); + } + } + + public static MarkerMetadata StaticDeserialize(byte[] data) + { + return _instance.Deserialize(data); + } + + public MarkerMetadata Deserialize(byte[] data) + { + using (var stream = new MemoryStream(data)) + { + using (var binaryDeserializer = new BinaryDeserializer(stream)) + { + var sessionIdentifier = StringSerializer.Instance.Deserialize(binaryDeserializer); + var source = CompressedInt32Serializer.Instance.Deserialize(binaryDeserializer); + + var remainingDataLen = + CompressedInt32Serializer.Instance.Deserialize(binaryDeserializer); + + var buffer = new byte[remainingDataLen]; + stream.ReadOrThrow(buffer, 0, remainingDataLen); + + var markerSource = (MarkerMetadata.MarkerSource)source; + var metadata = new MarkerMetadata(sessionIdentifier, markerSource, buffer); + return metadata; + } + } + } + } +} diff --git a/Assets/ARDK/Utilities/Marker/Metadata/BasicMetadataSerializer.cs.meta b/Assets/ARDK/Utilities/Marker/Metadata/BasicMetadataSerializer.cs.meta new file mode 100644 index 0000000..b78ae1e --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/Metadata/BasicMetadataSerializer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c4c3a779773d4832bd44d27684021cfd +timeCreated: 1583268043 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/Marker/Metadata/EmbeddedStationaryMetadataSerializer.cs b/Assets/ARDK/Utilities/Marker/Metadata/EmbeddedStationaryMetadataSerializer.cs new file mode 100644 index 0000000..9a52596 --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/Metadata/EmbeddedStationaryMetadataSerializer.cs @@ -0,0 +1,137 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.IO; + +using Niantic.ARDK.Utilities.Extensions; +using Niantic.ARDK.Networking.HLAPI.Data; +using Niantic.ARDK.Utilities.BinarySerialization; +using Niantic.ARDK.Utilities.BinarySerialization.ItemSerializers; + +using UnityEngine; + +namespace Niantic.ARDK.Utilities.Marker +{ + // TODO: This entire class seems unnecessary. + + /// Default IMetadataSerializer implementation for serializing and deserializing + /// StationaryMarkerMetadata as + /// 1. string SessionIdentifier (base) + /// 2. MarkerSource Source (base) + /// 3. Vector3 RealWorldTransform.Position + /// 4. Quaternion RealWorldTransform.Rotation + /// 5. Vector3[4] DetectionPointPositions + /// 6. byte[] Data (base) + /// @note StationaryMarkerMetadata that is serialized using this class can be deserialized using the + /// BasicMetadataSerializer. + public class EmbeddedStationaryMetadataSerializer: + IMetadataSerializer + { + private static readonly EmbeddedStationaryMetadataSerializer _instance = + new EmbeddedStationaryMetadataSerializer(); + + public static byte[] StaticSerialize(StationaryMarkerMetadata stationaryMetadata) + { + return _instance.Serialize(stationaryMetadata); + } + + private void WriteVector3(Vector3 inVector, byte[] buffer, int startIndex) + { + BitConverter.GetBytes(inVector.x).CopyTo(buffer, startIndex); + BitConverter.GetBytes(inVector.y).CopyTo(buffer, startIndex + 4); + BitConverter.GetBytes(inVector.z).CopyTo(buffer, startIndex + 8); + } + + public byte[] Serialize(MarkerMetadata metadata) + { + var stationaryMetadata = metadata as StationaryMarkerMetadata; + + if (stationaryMetadata == null) + { + Debug.LogError + ( + "EmbeddedStationaryMetadataSerializer can only be used to serialize " + + "StationaryMarkerMetadata objects" + ); + + return null; + } + + using (var memoryStream = new MemoryStream()) + { + using (var binarySerializer = new BinarySerializer(memoryStream)) + { + var realWorldTransform = stationaryMetadata.RealWorldTransform; + var detectionPoints = stationaryMetadata.DetectionPointPositions; + + var vector3Serializer = Vector3Serializer.Instance; + + vector3Serializer.Serialize(binarySerializer, realWorldTransform.ToPosition()); + + vector3Serializer.Serialize + (binarySerializer, realWorldTransform.ToRotation().eulerAngles); + + vector3Serializer.Serialize(binarySerializer, detectionPoints[0]); + vector3Serializer.Serialize(binarySerializer, detectionPoints[1]); + vector3Serializer.Serialize(binarySerializer, detectionPoints[2]); + vector3Serializer.Serialize(binarySerializer, detectionPoints[3]); + } + + var basicData = BasicMetadataSerializer.StaticSerialize(metadata); + var stationaryData = memoryStream.ToArray(); + + // TODO: We can possibly just serialize basicData first and avoid this copy. + // Not changing this login in this MR. + var allData = new byte[basicData.Length + stationaryData.Length]; + basicData.CopyTo(allData, 0); + stationaryData.CopyTo(allData, basicData.Length); + return allData; + } + } + + public static StationaryMarkerMetadata StaticDeserialize(byte[] data) + { + return (StationaryMarkerMetadata)_instance.Deserialize(data); + } + + public MarkerMetadata Deserialize(byte[] data) + { + using (var memoryStream = new MemoryStream(data)) + { + using (var binaryDeserializer = new BinaryDeserializer(memoryStream)) + { + var sessionIdentifier = StringSerializer.Instance.Deserialize(binaryDeserializer); + + // read the Source but don't need it + CompressedInt32Serializer.Instance.Deserialize(binaryDeserializer); + + var userDataLen = CompressedInt32Serializer.Instance.Deserialize(binaryDeserializer); + + var userData = new byte[userDataLen]; + memoryStream.ReadOrThrow(userData, 0, userDataLen); + + var vector3Deserializer = Vector3Serializer.Instance; + var worldPosition = vector3Deserializer.Deserialize(binaryDeserializer); + var worldRotationEuler = vector3Deserializer.Deserialize(binaryDeserializer); + var worldRotation = Quaternion.Euler(worldRotationEuler); + + var objectPoints = new Vector3[4]; + objectPoints[0] = vector3Deserializer.Deserialize(binaryDeserializer); + objectPoints[1] = vector3Deserializer.Deserialize(binaryDeserializer); + objectPoints[2] = vector3Deserializer.Deserialize(binaryDeserializer); + objectPoints[3] = vector3Deserializer.Deserialize(binaryDeserializer); + + var stationaryMetadata = new StationaryMarkerMetadata + ( + sessionIdentifier, + userData, + Matrix4x4.TRS(worldPosition, worldRotation, Vector3.one), + objectPoints + ); + + return stationaryMetadata; + } + } + } + } +} diff --git a/Assets/ARDK/Utilities/Marker/Metadata/EmbeddedStationaryMetadataSerializer.cs.meta b/Assets/ARDK/Utilities/Marker/Metadata/EmbeddedStationaryMetadataSerializer.cs.meta new file mode 100644 index 0000000..756a7da --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/Metadata/EmbeddedStationaryMetadataSerializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6458282465aca496b8ca533fa4cf83d5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/Marker/Metadata/IMetadataSerializer.cs b/Assets/ARDK/Utilities/Marker/Metadata/IMetadataSerializer.cs new file mode 100644 index 0000000..9d2dacd --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/Metadata/IMetadataSerializer.cs @@ -0,0 +1,12 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.Utilities.Marker +{ + /// @note This is part of an experimental feature that is not advised to be used in release builds. + public interface IMetadataSerializer + { + byte[] Serialize(MarkerMetadata stationaryMetadata); + + MarkerMetadata Deserialize(byte[] data); + } +} diff --git a/Assets/ARDK/Utilities/Marker/Metadata/IMetadataSerializer.cs.meta b/Assets/ARDK/Utilities/Marker/Metadata/IMetadataSerializer.cs.meta new file mode 100644 index 0000000..ce50abb --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/Metadata/IMetadataSerializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 97b6d034933944811bc50276907ca5c1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/Marker/Metadata/MarkerMetadata.cs b/Assets/ARDK/Utilities/Marker/Metadata/MarkerMetadata.cs new file mode 100644 index 0000000..a1ba03a --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/Metadata/MarkerMetadata.cs @@ -0,0 +1,69 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +namespace Niantic.ARDK.Utilities.Marker +{ + /// @note This is part of an experimental feature that is not advised to be used in release builds. + [Serializable] + public class MarkerMetadata + { + public enum MarkerSource + { + Device, + Stationary + } + + public MarkerSource Source { get; protected set; } + + public string SessionIdentifier; + + public byte[] Data; + + protected IMetadataSerializer Serializer { get; set; } + + protected MarkerMetadata() + { + } + + /// + /// Base constructor. + /// + /// Name of networking session scanners of this marker will join. + /// How this marker will be displayed + /// (On device or on something stationary in the real physical world). + /// Any user defined data that should be also embedded in the barcode. + /// Will use the BasicMetadataSerializer if this arg is left null. + public MarkerMetadata + ( + string sessionIdentifier, + MarkerSource source, + byte[] data, + IMetadataSerializer serializer = null + ) + { + SessionIdentifier = sessionIdentifier; + Source = source; + Data = data; + + Serializer = serializer ?? new BasicMetadataSerializer(); + } + + public byte[] Serialize() + { + return Serializer.Serialize(this); + } + + public override string ToString() + { + return + string.Format + ( + "MarkerMetadata (SessionIdentifier: {0}, Source: {1}, Data Length: {2})", + SessionIdentifier, + Source, + Data == null ? 0 : Data.Length + ); + } + } +} diff --git a/Assets/ARDK/Utilities/Marker/Metadata/MarkerMetadata.cs.meta b/Assets/ARDK/Utilities/Marker/Metadata/MarkerMetadata.cs.meta new file mode 100644 index 0000000..5471a11 --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/Metadata/MarkerMetadata.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0736f750c067e44d0825472b5e9a210c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/Marker/Metadata/StationaryMarkerMetadata.cs b/Assets/ARDK/Utilities/Marker/Metadata/StationaryMarkerMetadata.cs new file mode 100644 index 0000000..f95b405 --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/Metadata/StationaryMarkerMetadata.cs @@ -0,0 +1,72 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using UnityEngine; + +namespace Niantic.ARDK.Utilities.Marker +{ + [Serializable] + public class StationaryMarkerMetadata: + MarkerMetadata + { + public Matrix4x4 RealWorldTransform; + public Vector3[] DetectionPointPositions; + + [SerializeField] + private byte[] _combinedData; + + /// + /// StationaryMarkerMetadata will be embedded in markers that are displayed in a stationary + /// location in the real world. + /// + /// Name of networking session scanners of this marker will join. + /// Any user defined data that should be also embedded in the barcode. + /// Real world-space position (unit: meters) and orientation + /// of the marker relative to the origin of the shared AR space. + /// Real world-space positions (unit: meters) of the + /// marker points relative to the markerWorldTransform . + /// Will use the EmbeddedStationaryMetadataSerializer if this arg is left null. + public StationaryMarkerMetadata + ( + string sessionIdentifier, + byte[] data, + Matrix4x4 realWorldTransform, + Vector3[] detectionPointPositions, + IMetadataSerializer serializer = null + ) + { + throw new NotSupportedException("Stationary markers are not currently supported."); + + /** + SessionIdentifier = sessionIdentifier; + Source = MarkerSource.Stationary; + Data = data; + RealWorldTransform = realWorldTransform; + DetectionPointPositions = detectionPointPositions; + + Serializer = serializer ?? new EmbeddedStationaryMetadataSerializer(); + */ + } + + public override string ToString() + { + return + string.Format + ( + "StationaryMarkerMetadata (SessionIdentifier: {0}, Source: {1}, Data Length: {2}, " + + "World Transform P: {3} R: {4}, Points: [{5}, {6}, {7}, {8}])", + + SessionIdentifier, + Source, + Data == null ? 0 : Data.Length, + RealWorldTransform.ToPosition(), + RealWorldTransform.ToRotation().eulerAngles, + DetectionPointPositions[0].ToString("F4"), + DetectionPointPositions[1].ToString("F4"), + DetectionPointPositions[2].ToString("F4"), + DetectionPointPositions[3].ToString("F4") + ); + } + } +} diff --git a/Assets/ARDK/Utilities/Marker/Metadata/StationaryMarkerMetadata.cs.meta b/Assets/ARDK/Utilities/Marker/Metadata/StationaryMarkerMetadata.cs.meta new file mode 100644 index 0000000..416fd55 --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/Metadata/StationaryMarkerMetadata.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4667ae0e7d47941eab132876603e9bc9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/Marker/Parser.meta b/Assets/ARDK/Utilities/Marker/Parser.meta new file mode 100644 index 0000000..0b50e28 --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/Parser.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 30abfa0bb7b7a4f2baa113ce7e68ce2d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/Marker/Parser/BarcodeParserResult.cs b/Assets/ARDK/Utilities/Marker/Parser/BarcodeParserResult.cs new file mode 100644 index 0000000..7b49954 --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/Parser/BarcodeParserResult.cs @@ -0,0 +1,45 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.AR; +using UnityEngine; + +namespace Niantic.ARDK.Utilities.Marker +{ + public class BarcodeParserResult: + IParserResult + { + public byte[] Data { get; set; } + + public Vector2[] DetectedPoints { get; set; } + + public IARCamera ARCamera { get; set; } + + public double Timestamp + { + get + { + return _timestamp; + } + set + { + _timestamp = value; + } + } + + private double _timestamp = -1; + + public override string ToString() + { + return + string.Format + ( + "MarkerParserResult: [{0}, {1}, {2}, {3}], with data len {4}", + DetectedPoints == null ? "null" : DetectedPoints[0].ToString(), + DetectedPoints == null ? "null" : DetectedPoints[1].ToString(), + DetectedPoints == null ? "null" : DetectedPoints[2].ToString(), + DetectedPoints == null ? "null" : DetectedPoints[3].ToString(), + Data == null ? 0 : Data.Length + ); + } + } +} diff --git a/Assets/ARDK/Utilities/Marker/Parser/BarcodeParserResult.cs.meta b/Assets/ARDK/Utilities/Marker/Parser/BarcodeParserResult.cs.meta new file mode 100644 index 0000000..477ba0f --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/Parser/BarcodeParserResult.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e9dd56d247988451abe5d4cfa192d76b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/Marker/Parser/IMarkerParser.cs b/Assets/ARDK/Utilities/Marker/Parser/IMarkerParser.cs new file mode 100644 index 0000000..f75a524 --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/Parser/IMarkerParser.cs @@ -0,0 +1,25 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using UnityEngine; + +namespace Niantic.ARDK.Utilities.Marker +{ + public interface IMarkerParser + { + /// + /// Process and try to obtain marker from the given image. + /// + /// Array of pixels of the image to process. + /// Width of the image to process. + /// Height of the image to process. + /// Information about the marker, if one was parsed from the image. + /// True if a barcode was found. + bool Decode + ( + Color32[] pixels, + int width, + int height, + out IParserResult parserResult + ); + } +} diff --git a/Assets/ARDK/Utilities/Marker/Parser/IMarkerParser.cs.meta b/Assets/ARDK/Utilities/Marker/Parser/IMarkerParser.cs.meta new file mode 100644 index 0000000..fa61a86 --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/Parser/IMarkerParser.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 21ee70f5e2c03491880b31d5db0c9344 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/Marker/Parser/IParserResult.cs b/Assets/ARDK/Utilities/Marker/Parser/IParserResult.cs new file mode 100644 index 0000000..a47c128 --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/Parser/IParserResult.cs @@ -0,0 +1,18 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.AR; +using UnityEngine; + +namespace Niantic.ARDK.Utilities.Marker +{ + public interface IParserResult + { + byte[] Data { get; set; } + + Vector2[] DetectedPoints { get; set; } + + IARCamera ARCamera { get; set; } + + double Timestamp { get; set; } + } +} diff --git a/Assets/ARDK/Utilities/Marker/Parser/IParserResult.cs.meta b/Assets/ARDK/Utilities/Marker/Parser/IParserResult.cs.meta new file mode 100644 index 0000000..3af889a --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/Parser/IParserResult.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ae1be17e6fb1e446a803f44a80bea43a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/Marker/Parser/ZXingBarcodeParser.cs b/Assets/ARDK/Utilities/Marker/Parser/ZXingBarcodeParser.cs new file mode 100644 index 0000000..4cc160a --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/Parser/ZXingBarcodeParser.cs @@ -0,0 +1,74 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.Utilities.Marker; + +using UnityEngine; + +using ZXing; + +namespace Niantic.ARDK.Utilities.QR +{ + /// @note This is part of an experimental feature that is not advised to be used in release builds. + public class ZXingBarcodeParser: + IMarkerParser + { + private readonly BarcodeReader _reader; + + public ZXingBarcodeParser(): + this(new MarkerScannerSettings()) + { + } + + public ZXingBarcodeParser(MarkerScannerSettings settings) + { + _reader = new BarcodeReader(); + _reader.AutoRotate = settings.ParserAutoRotate; + _reader.TryInverted = settings.ParserTryInverted; + _reader.Options.TryHarder = settings.ParserTryHarder; + } + + public bool Decode + ( + Color32[] pixels, + int width, + int height, + out IParserResult parserResult + ) + { + parserResult = new BarcodeParserResult(); + + if (pixels == null || pixels.Length == 0 || width == 0 || height == 0) + return false; + + var success = false; + try + { + var result = _reader.Decode(pixels, width, height); + + if (result != null) + { + var vectorPoints = new Vector2[4]; + + for (var i = 0; i < vectorPoints.Length; ++i) + { + var resultPoint = result.ResultPoints[i]; + vectorPoints[i] = new Vector2(resultPoint.X, resultPoint.Y); + } + + parserResult.Data = Convert.FromBase64String(result.Text); + parserResult.DetectedPoints = vectorPoints; + + success = true; + } + } + catch (Exception e) + { + Debug.Log(e); + } + + return success; + } + } +} diff --git a/Assets/ARDK/Utilities/Marker/Parser/ZXingBarcodeParser.cs.meta b/Assets/ARDK/Utilities/Marker/Parser/ZXingBarcodeParser.cs.meta new file mode 100644 index 0000000..688e74d --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/Parser/ZXingBarcodeParser.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c7878e8e4395b4c7c9f0a3be4c064101 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/Marker/Scanner.meta b/Assets/ARDK/Utilities/Marker/Scanner.meta new file mode 100644 index 0000000..41e9d97 --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/Scanner.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c66b3497a767f4b0dbd8a68e5f8028b3 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/Marker/Scanner/ARFrameMarkerScanner.cs b/Assets/ARDK/Utilities/Marker/Scanner/ARFrameMarkerScanner.cs new file mode 100644 index 0000000..9f8d23e --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/Scanner/ARFrameMarkerScanner.cs @@ -0,0 +1,392 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.ARSessionEventArgs; +using Niantic.ARDK.AR.Camera; +using Niantic.ARDK.AR.Frame; +using Niantic.ARDK.AR.Networking; +using Niantic.ARDK.Networking.Clock; +using Niantic.ARDK.Utilities.QR; + +using UnityEngine; + +#if !UNITY_WEBGL +using System.Threading; +#endif + +namespace Niantic.ARDK.Utilities.Marker +{ + /// + /// This Scanner processes image textures received from the given + /// ARSession's OnDidUpdateFrame callback to try and parse + /// a marker in the device camera's view + /// + /// @note This is part of an experimental feature that is not advised to be used in release builds. + public sealed class ARFrameMarkerScanner: + IMarkerScanner + { + public enum TextureType + { + /// Texture format is determined by platform (YCbCr for iOS, BGRA for Android or in-editor). + Platform, + + /// YCbCr format. This value is only valid on iOS devices. + YCbCr, + + /// BGRA format. This value is valid on Android devices and in-editor. + BGRA + } + + + public event ArdkEventHandler Ready; + public event ArdkEventHandler StatusChanged; + public event ArdkEventHandler GotResult; + + // Store references to the AR objects utilized by the scanner + private readonly IARSession _arSession; + private ICoordinatedClock _coordinatedClock; + private TextureType _textureType; + + // Store information about last image / results + private IARCamera _arCamera; + private double _timestamp; + private byte[] _rawPixels; + private int _rawWidth; + private int _rawHeight; + private IParserResult _result; + + // Background thread + private bool _parserPixelAvailable = false; + private float _mainThreadLastDecode = 0; + private bool _decodeInterrupted = true; +#if !UNITY_WEBGL + private Thread _codeScannerThread; +#endif + + public MarkerScannerStatus Status + { + get + { + return _status; + } + private set + { + if (value == _status) + return; + + _status = value; + + var handler = StatusChanged; + if (handler != null) + { + var args = new ARFrameMarkerScannerStatusChangedArgs(value); + handler(args); + } + } + } + + private MarkerScannerStatus _status; + + public IMarkerParser MarkerParser { get; private set; } + private MarkerScannerSettings _settings; + + // If no IMarkerParser is provided, will default to using a barcode parser + public ARFrameMarkerScanner + ( + IARNetworking arNetworking, + MarkerScannerSettings settings = null, + IMarkerParser markerParser = null + ) + { + _arSession = arNetworking.ARSession; + _coordinatedClock = arNetworking.Networking.CoordinatedClock; + InitializeFrameSettings(); + + _settings = settings ?? new MarkerScannerSettings(); + MarkerParser = markerParser ?? new ZXingBarcodeParser(_settings); + + Status = MarkerScannerStatus.Initialized; + } + + ~ARFrameMarkerScanner() + { + Debug.LogError("ARFrameMarkerScanner should be destroyed by an explicit call to Dispose()."); + } + + public void Dispose() + { + GC.SuppressFinalize(this); + + Stop(); + + // clean events + StatusChanged = null; + Ready = null; + GotResult = null; + + // clean returns + _result = null; + _parserPixelAvailable = false; + + // clean references + MarkerParser = null; + _coordinatedClock = null; + } + + private void InitializeFrameSettings() + { +#if AR_NATIVE_SUPPORT && UNITY_ANDROID + _textureType = TextureType.BGRA; +#else + _textureType = TextureType.YCbCr; +#endif + } + + /// + /// Used to start Scanning + /// + /// + public void Scan() + { + if (Status == MarkerScannerStatus.Running) + { + Debug.Log("This ARFrameMarkerScanner is already running."); + return; + } + +#if !UNITY_WEBGL + if (_settings.ScannerBackgroundThread) + { + if (_codeScannerThread != null) + Stop(); + + _decodeInterrupted = false; + _codeScannerThread = new Thread(ThreadTryToParse); + _codeScannerThread.Start(); + } +#endif + + Debug.Log("ARFrameMarkerScanner started."); + Status = MarkerScannerStatus.Running; + _arSession.FrameUpdated += Update; + } + + /// + /// Used to Stop Scanning + /// + public void Stop() + { + Debug.Log("ARFrameMarkerScanner stopped."); + + // Stop thread / Clean callback +#if !UNITY_WEBGL + if (_codeScannerThread != null) + { + _decodeInterrupted = true; + _codeScannerThread.Join(); + _codeScannerThread = null; + } +#endif + + Status = MarkerScannerStatus.Paused; + _arSession.FrameUpdated -= Update; + } + +#region Unthread + /// + /// Process Image Decoding in the main Thread + /// Background Thread : OFF + /// + private void TryToParse() + { + // Wait + if (Status != MarkerScannerStatus.Running || !_parserPixelAvailable) + return; + + try + { + ConvertTextureAndDecode(); + } + catch (Exception e) + { + Debug.LogError(e); + } + } +#endregion + +#region Background Thread +#if !UNITY_WEBGL + /// + /// Process Image Decoding in a Background Thread + /// Background Thread : ON + /// + private void ThreadTryToParse() + { + while (_decodeInterrupted == false && _result == null) + { + // Wait + if (Status != MarkerScannerStatus.Running || !_parserPixelAvailable) + { + Thread.Sleep(Mathf.FloorToInt(_settings.ScannerDecodeInterval * 1000)); + continue; + } + + try + { + ConvertTextureAndDecode(); + + if (_result == null) + continue; + + // Sleep a little bit and set the signal to get the next frame + Thread.Sleep(Mathf.FloorToInt(_settings.ScannerDecodeInterval * 1000)); + } + catch (ThreadAbortException) + { + } + catch (Exception e) + { + Debug.LogError(e); + } + } + } +#endif +#endregion + + private void ConvertTextureAndDecode() + { + // Convert Texture + var pixels = new Color32[_rawWidth * _rawHeight]; + + var rawIndex = 0; + for (var idx = 0; idx < _rawWidth * _rawHeight; idx++) + { + if (_textureType == TextureType.YCbCr) + { + // Use Y value in YCbCr texture to create a greyscale texture + var val = _rawPixels[idx]; + pixels[idx] = new Color32(val, val, val, 255); + } + else + { + pixels[idx] = + new Color32 + ( + _rawPixels[rawIndex + 2], + _rawPixels[rawIndex + 1], + _rawPixels[rawIndex], + _rawPixels[rawIndex + 3] + ); + + rawIndex += 4; + } + } + + // And try to Decode + TryToDecodePixels(pixels); + } + + private void TryToDecodePixels(Color32[] pixels) + { + IParserResult parserResult; + var parserSuccess = + MarkerParser.Decode + ( + pixels, + _rawWidth, + _rawHeight, + out parserResult + ); + + if (parserSuccess) + { + parserResult.ARCamera = _arCamera; + parserResult.Timestamp = _timestamp; + + var rawShortSide = Math.Min(_rawWidth, _rawHeight); + for (var i = 0; i < parserResult.DetectedPoints.Length; i++) + parserResult.DetectedPoints[i].y = rawShortSide - parserResult.DetectedPoints[i].y; + + _result = parserResult; + } + + _parserPixelAvailable = false; + } + + public void Update() + { + var args = new FrameUpdatedArgs(_arSession.CurrentFrame); + Update(args); + } + + /// + /// This Update Loop is used to : + /// * Bring back Succeeded to the main thread when using Background Thread + /// * To execute image Decoding When not using the background Thread + /// + private void Update(FrameUpdatedArgs updateArgs) + { + var readyHandler = Ready; + if (readyHandler != null) + { + Ready = null; + + var readyArgs = new ARFrameMarkerScannerReadyArgs(); + readyHandler(readyArgs); + } + + if (Status == MarkerScannerStatus.Running) + { + // Call the callback if a result is there + if (_result != null) + { + var gotResultHandler = GotResult; + if (gotResultHandler != null) + { + var args = new ARFrameMarkerScannerGotResultArgs(_result); + gotResultHandler(args); + } + + // clean and return + _result = null; + _parserPixelAvailable = false; + + return; + } + + if (!_parserPixelAvailable) + { + var frame = updateArgs.Frame; + _arCamera = frame.Camera; + _timestamp = _coordinatedClock.CurrentCorrectedTime; + + // Use raw data instead of doing extra step of getting pixels from texture + // For Android this will get the BGRA data + // For iOS this will get the Y of the YCbCr data, which is all the parser needs + _rawPixels = frame.CapturedImageBuffer.Planes[0].Data.ToArray(); + _rawWidth = frame.Camera.CPUImageResolution.width; + _rawHeight = frame.Camera.CPUImageResolution.height; + + _parserPixelAvailable = true; + } + + // If background thread OFF, do the decode main thread with a pause for UI + bool shouldParse = !_settings.ScannerBackgroundThread && + _mainThreadLastDecode < Time.realtimeSinceStartup - _settings.ScannerDecodeInterval; + + if (shouldParse) + { + TryToParse(); + _mainThreadLastDecode = Time.realtimeSinceStartup; + } + } + } + + public override string ToString() + { + return "[ARFrameMarkerScanner]"; + } + } +} diff --git a/Assets/ARDK/Utilities/Marker/Scanner/ARFrameMarkerScanner.cs.meta b/Assets/ARDK/Utilities/Marker/Scanner/ARFrameMarkerScanner.cs.meta new file mode 100644 index 0000000..050efbc --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/Scanner/ARFrameMarkerScanner.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3b485930ca5374672a2c27b463e4f522 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/Marker/Scanner/ARFrameMarkerScannerGotResultArgs.cs b/Assets/ARDK/Utilities/Marker/Scanner/ARFrameMarkerScannerGotResultArgs.cs new file mode 100644 index 0000000..ab7aa5d --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/Scanner/ARFrameMarkerScannerGotResultArgs.cs @@ -0,0 +1,17 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +namespace Niantic.ARDK.Utilities.Marker +{ + public struct ARFrameMarkerScannerGotResultArgs: + IArdkEventArgs + { + public readonly IParserResult ParserResult; + + public ARFrameMarkerScannerGotResultArgs(IParserResult parserResult) + { + ParserResult = parserResult; + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/Utilities/Marker/Scanner/ARFrameMarkerScannerGotResultArgs.cs.meta b/Assets/ARDK/Utilities/Marker/Scanner/ARFrameMarkerScannerGotResultArgs.cs.meta new file mode 100644 index 0000000..c74b17a --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/Scanner/ARFrameMarkerScannerGotResultArgs.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6a4945a5f0884b3382572edc5622be86 +timeCreated: 1607975589 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/Marker/Scanner/ARFrameMarkerScannerReadyArgs.cs b/Assets/ARDK/Utilities/Marker/Scanner/ARFrameMarkerScannerReadyArgs.cs new file mode 100644 index 0000000..11bb1ef --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/Scanner/ARFrameMarkerScannerReadyArgs.cs @@ -0,0 +1,9 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.Utilities.Marker +{ + public struct ARFrameMarkerScannerReadyArgs: + IArdkEventArgs + { + } +} \ No newline at end of file diff --git a/Assets/ARDK/Utilities/Marker/Scanner/ARFrameMarkerScannerReadyArgs.cs.meta b/Assets/ARDK/Utilities/Marker/Scanner/ARFrameMarkerScannerReadyArgs.cs.meta new file mode 100644 index 0000000..8ee4283 --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/Scanner/ARFrameMarkerScannerReadyArgs.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ea6321e05edb4ff1850e2b5ce4eb501e +timeCreated: 1607975589 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/Marker/Scanner/ARFrameMarkerScannerStatusChangedArgs.cs b/Assets/ARDK/Utilities/Marker/Scanner/ARFrameMarkerScannerStatusChangedArgs.cs new file mode 100644 index 0000000..64b12ca --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/Scanner/ARFrameMarkerScannerStatusChangedArgs.cs @@ -0,0 +1,15 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.Utilities.Marker +{ + public struct ARFrameMarkerScannerStatusChangedArgs: + IArdkEventArgs + { + public readonly MarkerScannerStatus Status; + + public ARFrameMarkerScannerStatusChangedArgs(MarkerScannerStatus status) + { + Status = status; + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/Utilities/Marker/Scanner/ARFrameMarkerScannerStatusChangedArgs.cs.meta b/Assets/ARDK/Utilities/Marker/Scanner/ARFrameMarkerScannerStatusChangedArgs.cs.meta new file mode 100644 index 0000000..93a4235 --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/Scanner/ARFrameMarkerScannerStatusChangedArgs.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6956ad0cf8924663948b51b7dbe74650 +timeCreated: 1607975589 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/Marker/Scanner/IMarkerScanner.cs b/Assets/ARDK/Utilities/Marker/Scanner/IMarkerScanner.cs new file mode 100644 index 0000000..fb37922 --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/Scanner/IMarkerScanner.cs @@ -0,0 +1,26 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +/// @namespace Niantic.ARDK.Utilities.Marker +/// @brief Tools supporting the MarkerSync feature that enables users to scan a physical marker to join a networked AR session. +/// @note This is part of an experimental feature that is not advised to be used in release builds. +namespace Niantic.ARDK.Utilities.Marker +{ + /// @note This is part of an experimental feature that is not advised to be used in release builds. + public interface IMarkerScanner: + IDisposable + { + event ArdkEventHandler Ready; + event ArdkEventHandler StatusChanged; + event ArdkEventHandler GotResult; + + MarkerScannerStatus Status { get; } + + IMarkerParser MarkerParser { get; } + + void Scan(); + void Stop(); + void Update(); + } +} diff --git a/Assets/ARDK/Utilities/Marker/Scanner/IMarkerScanner.cs.meta b/Assets/ARDK/Utilities/Marker/Scanner/IMarkerScanner.cs.meta new file mode 100644 index 0000000..c54cc4b --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/Scanner/IMarkerScanner.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f497bae82fac74207a3cd03ca331afc5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/Marker/Scanner/MarkerScannerSettings.cs b/Assets/ARDK/Utilities/Marker/Scanner/MarkerScannerSettings.cs new file mode 100644 index 0000000..ffb772b --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/Scanner/MarkerScannerSettings.cs @@ -0,0 +1,44 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.Utilities.Marker +{ + /// @note This is part of an experimental feature that is not advised to be used in release builds. + public class MarkerScannerSettings + { + // Scanner Options + public bool ScannerBackgroundThread { get; set; } + public int ScannerDelayFrameMin { get; set; } + + // This is in seconds + public float ScannerDecodeInterval { get; set; } + + // Parser Options + public bool ParserAutoRotate { get; set; } + public bool ParserTryInverted { get; set; } + public bool ParserTryHarder { get; set; } + + public MarkerScannerSettings() + { + ScannerBackgroundThread = true; + ScannerDelayFrameMin = 3; + ScannerDecodeInterval = 0.1f; + + ParserAutoRotate = true; + ParserTryInverted = true; + ParserTryHarder = false; + + // Device dependent settings + + // Disable background thread for webgl : Thread not supported +#if UNITY_WEBGL + ScannerDecodeInterval = 0.5f; + ScannerBackgroundThread = false; +#endif + + // Enable only for desktop usage : heavy CPU consumption +#if UNITY_STANDALONE || UNITY_EDITOR + ParserTryHarder = true; +#endif + } + } +} diff --git a/Assets/ARDK/Utilities/Marker/Scanner/MarkerScannerSettings.cs.meta b/Assets/ARDK/Utilities/Marker/Scanner/MarkerScannerSettings.cs.meta new file mode 100644 index 0000000..4230300 --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/Scanner/MarkerScannerSettings.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 306637274299b524ca9df1e5aec8351c +timeCreated: 1480394805 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/Marker/Scanner/MarkerScannerStatus.cs b/Assets/ARDK/Utilities/Marker/Scanner/MarkerScannerStatus.cs new file mode 100644 index 0000000..bc14c19 --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/Scanner/MarkerScannerStatus.cs @@ -0,0 +1,11 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.Utilities.Marker +{ + public enum MarkerScannerStatus + { + Initialized, + Running, + Paused + } +} diff --git a/Assets/ARDK/Utilities/Marker/Scanner/MarkerScannerStatus.cs.meta b/Assets/ARDK/Utilities/Marker/Scanner/MarkerScannerStatus.cs.meta new file mode 100644 index 0000000..0bd90e1 --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/Scanner/MarkerScannerStatus.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a10a91adac1af46f9a86c17358ae347d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/Marker/ZXingMarkerGenerator.cs b/Assets/ARDK/Utilities/Marker/ZXingMarkerGenerator.cs new file mode 100644 index 0000000..8b5c1b6 --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/ZXingMarkerGenerator.cs @@ -0,0 +1,143 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using UnityEngine; + +using ZXing; + +namespace Niantic.ARDK.Utilities.Marker +{ + /// @note This is part of an experimental feature that is not advised to be used in release builds. + public static class ZXingMarkerGenerator + { + public class MarkerGenerationResult + { + public Texture2D Texture { get; private set; } + public Color32[] RawPixels { get; private set; } + + public string EncodedText { get; private set; } + + public MarkerGenerationResult(Texture2D texture, Color32[] pixels, string encodedText) + { + Texture = texture; + RawPixels = pixels; + EncodedText = encodedText; + } + } + + private const float INCH_TO_METER = 0.0254f; + + public static MarkerGenerationResult GenerateBarcode + ( + MarkerMetadata metadata, + BarcodeFormat format, + int width, + int height + ) + { + var data = metadata.Serialize(); + + // Pad data buffer + var remainder = data.Length % 4; + var paddedData = new byte[data.Length + remainder]; + data.CopyTo(paddedData, 0); + + for (var i = 0; i < remainder; ++i) + paddedData[data.Length + i] = (byte)'='; + + // Generate the BitMatrix + var encodedText = Convert.ToBase64String(paddedData); + var bitMatrix = new MultiFormatWriter().encode(encodedText, format, width, height); + + // Generate the pixel array + var texPixels = new Color[width * height]; + var parserPixels = new Color32[texPixels.Length]; + var pos = 0; + + for (var x = 0; x < width; x++) + for (var y = 0; y < height; y++) + texPixels[pos++] = bitMatrix[x, y] ? Color.black : Color.white; + + // Rotate 180 + var orientedPixels = + ImageDataUtils.Transform + ( + texPixels, + ImageDataUtils.TransformType.RotateCounterclockwise, + width, + height + ); + + for (var index = 0; index < orientedPixels.Length; index++) + parserPixels[index] = orientedPixels[index]; + + // Setup the Texture + var tex = new Texture2D(width, height); + tex.SetPixels(orientedPixels); + tex.Apply(); + + var generatorResult = new MarkerGenerationResult(tex, parserPixels, encodedText); + + var resultLog = "Generated QR code using the ZXing library."; + + if (metadata.Source == MarkerMetadata.MarkerSource.Stationary) + { + resultLog += + string.Format + ( + " To generate a QR code for stationary display, use this site: {0} with this string: {1}", + "https://zxing.appspot.com/generator", + generatorResult.EncodedText + ); + } + + Debug.Log(resultLog); + + return generatorResult; + } + + public static Vector3[] GetRealWorldPointPositions(Vector2 center, Vector2[] points) + { + var locatorDistToAxis = Math.Abs(points[0].x - center.x); + var alignmentDistToAxis = Math.Abs(points[3].x - center.x); + + var screenWidthInMeters = Screen.width / Screen.dpi * INCH_TO_METER; + var pixelSize = screenWidthInMeters / Screen.width; + + var botLeft = + new Vector3 + ( + -locatorDistToAxis * pixelSize, + locatorDistToAxis * pixelSize, + 0 + ); + + var topLeft = + new Vector3 + ( + -locatorDistToAxis * pixelSize, + -locatorDistToAxis * pixelSize, + 0 + ); + + var topRight = + new Vector3 + ( + locatorDistToAxis * pixelSize, + -locatorDistToAxis * pixelSize, + 0 + ); + + var alignment = + new Vector3 + ( + alignmentDistToAxis * pixelSize, + alignmentDistToAxis * pixelSize, + 0 + ); + + return new[] {botLeft, topLeft, topRight, alignment}; + } + } +} diff --git a/Assets/ARDK/Utilities/Marker/ZXingMarkerGenerator.cs.meta b/Assets/ARDK/Utilities/Marker/ZXingMarkerGenerator.cs.meta new file mode 100644 index 0000000..6cfa050 --- /dev/null +++ b/Assets/ARDK/Utilities/Marker/ZXingMarkerGenerator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d044fd4687b644375a85f54c63fe1293 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/MathUtils.cs b/Assets/ARDK/Utilities/MathUtils.cs new file mode 100644 index 0000000..d96bc22 --- /dev/null +++ b/Assets/ARDK/Utilities/MathUtils.cs @@ -0,0 +1,717 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.Camera; + +using UnityEngine; + +namespace Niantic.ARDK.Utilities +{ + /// A collection of math helpers to calculate fundamental + /// transformations required for augmented reality. + internal static class MathUtils + { + /// Returns an affine transform for converting between + /// normalized image coordinates and a coordinate space + /// appropriate for rendering the camera image onscreen. + /// @note The width and height arguments must conform + /// with the specified viewport orientation. + /// @param camera The IARCamera that captured the AR background image. + /// @param viewportOrientation The orientation of the viewport. + /// @param viewportWidth The width of the viewport in pixels. + /// @param viewportHeight The height of the viewport in pixels. + /// @returns An affine 4x4 transformation matrix. + internal static Matrix4x4 CalculateDisplayTransform + ( + IARCamera camera, + ScreenOrientation viewportOrientation, + int viewportWidth, + int viewportHeight + ) + { + return CalculateDisplayTransform + ( + camera.ImageResolution.width, + camera.ImageResolution.height, + viewportWidth, + viewportHeight, + viewportOrientation + ); + } + + /// Returns an affine transform for converting between + /// normalized image coordinates and a coordinate space + /// appropriate for rendering the camera image onscreen. + /// @note The width and height arguments must conform + /// with the specified viewport orientation. + /// @param imageWidth The width of the raw AR background image in pixels. + /// @param imageHeight The height of the raw AR background image in pixels. + /// @param viewportOrientation The orientation of the viewport. + /// @param viewportWidth The width of the viewport in pixels. + /// @param viewportHeight The height of the viewport in pixels. + /// @returns An affine 4x4 transformation matrix. + internal static Matrix4x4 CalculateDisplayTransform + ( + int imageWidth, + int imageHeight, + int viewportWidth, + int viewportHeight, + ScreenOrientation viewportOrientation, + bool invertVertically = true + ) + { + // Infer image orientation + var imageOrientation = imageWidth > imageHeight + ? ScreenOrientation.LandscapeLeft + : ScreenOrientation.Portrait; + + // We invert the y coordinate because Unity's 2D coordinate system is + // upside-down compared to the native systems. + var invert = invertVertically ? AffineInvertVertical() : Matrix4x4.identity; + + return invert * + AffineFit + ( + imageWidth, + imageHeight, + imageOrientation, + viewportWidth, + viewportHeight, + viewportOrientation + ); + } + + /// Returns a view matrix for the specified screen orientation using the native convention. + /// @param camera The camera to convert world space coordinates to. + /// @param orientation The orientation of the viewport. + internal static Matrix4x4 CalculateNarViewMatrix + ( + IARCamera camera, + ScreenOrientation orientation + ) + { +#if UNITY_EDITOR + var currentOrientation = Screen.width > Screen.height + ? ScreenOrientation.LandscapeLeft + : ScreenOrientation.Portrait; +#else + var currentOrientation = Screen.orientation; +#endif + + // Get the view matrix for the current orientation in nar convention + var viewMatrixForCurrentOrientation = camera.GetViewMatrix(currentOrientation); + + // Calculate the required rotation for the target orientation + var rotation = CalculateViewRotation + ( + from: currentOrientation, + to: orientation + ); + + return rotation * viewMatrixForCurrentOrientation; + } + + /// Returns a view matrix for the specified screen orientation using the native convention. + /// @param camera The camera to convert world space coordinates to. + /// @param orientation The orientation of the viewport. + internal static Matrix4x4 CalculateNarViewMatrix + ( + Camera camera, + ScreenOrientation orientation + ) + { +#if UNITY_EDITOR + var currentOrientation = Screen.width > Screen.height + ? ScreenOrientation.LandscapeLeft + : ScreenOrientation.Portrait; +#else + var currentOrientation = Screen.orientation; +#endif + + // Get the view matrix for the current orientation in Unity convention + var viewMatrixForCurrentOrientation = camera.worldToCameraMatrix; + + // Flip the forward axis to conform with nar + var narView = viewMatrixForCurrentOrientation.ConvertViewMatrixBetweenNarAndUnity(); + + // Calculate the required rotation for the target orientation + var rotation = CalculateViewRotation + ( + from: currentOrientation, + to: orientation + ); + + return rotation * narView; + } + + /// Returns a view matrix for the specified screen orientation using Unity's convention. + /// @param camera The camera to convert world space coordinates to. + /// @param orientation The orientation of the viewport. + internal static Matrix4x4 CalculateUnityViewMatrix + ( + IARCamera camera, + ScreenOrientation orientation + ) + { +#if UNITY_EDITOR + var currentOrientation = Screen.width > Screen.height + ? ScreenOrientation.LandscapeLeft + : ScreenOrientation.Portrait; +#else + var currentOrientation = Screen.orientation; +#endif + + // Get the view matrix for the current orientation in nar convention + var viewMatrixForCurrentOrientation = camera.GetViewMatrix(currentOrientation); + + // Calculate the required rotation for the target orientation + var rotation = CalculateViewRotation + ( + from: currentOrientation, + to: orientation + ); + + // Rotate the view + var rotatedView = rotation * viewMatrixForCurrentOrientation; + + // Flip the forward axis to conform with unity + return rotatedView.ConvertViewMatrixBetweenNarAndUnity(); + } + + /// The forward vector is flipped between Unity camera matrices and IARCamera + /// view matrices. When called on a native view matrix, this extension method + /// converts to unity convention and vice-versa. + internal static Matrix4x4 ConvertViewMatrixBetweenNarAndUnity(this Matrix4x4 view) + { + var result = view; + + result.m20 *= -1.0f; + result.m21 *= -1.0f; + result.m22 *= -1.0f; + result.m23 *= -1.0f; + + return result; + } + + /// Calculates the intrinsic parameters of a Unity camera. + internal static CameraIntrinsics CalculateIntrinsics(Camera camera) + { + var f = (camera.focalLength * camera.pixelWidth) / camera.sensorSize.x; + var p = new Vector2(camera.pixelWidth / 2f, camera.pixelHeight / 2f); + return new CameraIntrinsics(f, f, p.x, p.y); + } + + /// Calculates camera intrinsics from the specified properties. + /// @param imageWidth Width of the captured image. + /// @param imageHeight Height of the captured image. + /// @param focalLength The focal length of the camera. + /// @param sensorWidth Width of the camera sensor. + /// @returns Intrinsic parameters of the described camera. + internal static CameraIntrinsics CalculateIntrinsics + ( + int imageWidth, + int imageHeight, + float focalLength, + float sensorWidth + ) + { + var f = (focalLength * imageWidth) / sensorWidth; + var p = new Vector2(imageWidth / 2f, imageHeight / 2f); + return new CameraIntrinsics(f, f, p.x, p.y); + } + + /// Returns a transform matrix appropriate for rendering + /// 3D content to match the image captured by the camera, + /// using the specified parameters. + /// @param camera The AR camera that captured the AR background image. + /// @param viewportOrientation The orientation of the viewport. + /// @param viewportWidth The width of the viewport in pixels. + /// @param viewportHeight The height of the viewport in pixels. + /// @param near The distance from the camera to the near clipping plane. + /// @param far The distance from the camera to the far clipping plane. + internal static Matrix4x4 CalculateProjectionMatrix + ( + IARCamera camera, + ScreenOrientation viewportOrientation, + int viewportWidth, + int viewportHeight, + float near, + float far + ) + { + var imageResolution = camera.ImageResolution; + + return CalculateProjectionMatrix + ( + camera.Intrinsics, + imageResolution.width, + imageResolution.height, + viewportWidth, + viewportHeight, + viewportOrientation, + near, + far + ); + } + + /// Returns a transform matrix appropriate for rendering + /// 3D content to match the image captured by the camera, + /// using the specified parameters. + /// @param intrinsics The intrinsics for the raw AR background image. + /// @param imageWidth The width of the raw AR background image. + /// @param imageHeight The height of the raw AR background image. + /// @param viewportOrientation The orientation of the viewport. + /// @param viewportWidth The width of the viewport in pixels. + /// @param viewportHeight The height of the viewport in pixels. + /// @param near The distance from the camera to the near clipping plane. + /// @param far The distance from the camera to the far clipping plane. + /// @param useOpenGLConvention Whether to construct an OpenGL-like projection matrix. + internal static Matrix4x4 CalculateProjectionMatrix + ( + CameraIntrinsics intrinsics, + int imageWidth, + int imageHeight, + int viewportWidth, + int viewportHeight, + ScreenOrientation viewportOrientation, + float near, + float far, + bool useOpenGLConvention = false + ) + { + // Get the viewport resolution in landscape + float viewportWidthLandscape = viewportWidth; + float viewportHeightLandscape = viewportHeight; + if (viewportOrientation == ScreenOrientation.Portrait) + (viewportWidthLandscape, viewportHeightLandscape) = (viewportHeightLandscape, viewportWidthLandscape); + + // Calculate scaling + var scale = viewportHeightLandscape / (viewportWidthLandscape / imageWidth * imageHeight); + + // Calculate the cropped resolution of the image in landscapess + var croppedFrame = new Vector2 + ( + // The image fills the longer axis of the viewport + x: imageWidth, + + // The image is cropped on the shorter axis of the viewport + y: imageHeight * scale + ); + + // Get the corners of the captured image + var right = useOpenGLConvention ? imageWidth : imageWidth - 1; + var top = useOpenGLConvention ? imageHeight : imageHeight - 1; + var left = right - 2.0f * intrinsics.PrincipalPoint.x; + var bottom = top - 2.0f * intrinsics.PrincipalPoint.y; + + // Calculate the image origin in landscape + Vector2 origin = new Vector2 + ( + x: left / croppedFrame.x, + y: -bottom / croppedFrame.y + ); + + // Rotate the image origin to the specified orientation + origin = RotateVector(origin, (float)GetAngle(viewportOrientation, ScreenOrientation.LandscapeLeft)); + + // Fx and Fy are identical for square pixels + var focalLength = intrinsics.FocalLength.x; + + Vector2 f = new Vector2 + ( + x: 1.0f / (croppedFrame.x * 0.5f / focalLength), + y: 1.0f / (croppedFrame.y * 0.5f / focalLength) + ); + + // Swap for portrait + if (viewportOrientation == ScreenOrientation.Portrait || + viewportOrientation == ScreenOrientation.PortraitUpsideDown) + { + (f.x, f.y) = (f.y, f.x); + } + + Matrix4x4 projection = Matrix4x4.zero; + projection[0, 0] = f.x; + projection[1, 1] = f.y; + projection[0, 2] = origin.x; + projection[1, 2] = origin.y; + projection[3, 2] = -1.0f; + + // Direct3D-like: The coordinate is 0 at the top and increases downward. + // This applies to Direct3D, Metal and consoles. + // OpenGL-like: The coordinate is 0 at the bottom and increases upward. + // This applies to OpenGL and OpenGL ES. + if (useOpenGLConvention) + { + projection[2, 2] = -(far + near) / (far - near); + projection[2, 3] = -2.0f * (far * near) / (far - near); + } + else + { + projection[2, 2] = far / (near - far); + projection[2, 3] = far * near / (near - far); + } + + return projection; + } + + /// Calculates a projective transformation to sync normalized image coordinates + /// with the target pose. + /// @param referencePose The original pose associated with the image. + /// @param targetPose The the pose to synchronize with. + /// @param backProjectionPlane The normalized distance of the back-projection plane + /// between the near and far clipping planes. Lower values make translations + /// more perceptible. + /// @returns A projective transformation matrix to be applied to normalized image coordinates. + internal static Matrix4x4 CalculateHomography + ( + Matrix4x4 referencePose, + Matrix4x4 targetPose, + Matrix4x4 projection, + float backProjectionPlane + ) + { + Vector3 worldPosition00 = ViewportToWorldPoint + (Vector2.zero, referencePose, projection, backProjectionPlane); + + Vector3 worldPosition01 = ViewportToWorldPoint + (Vector2.up, referencePose, projection, backProjectionPlane); + + Vector3 worldPosition11 = ViewportToWorldPoint + (Vector2.one, referencePose, projection, backProjectionPlane); + + Vector3 worldPosition10 = ViewportToWorldPoint + (Vector2.right, referencePose, projection, backProjectionPlane); + + Vector2 p00 = WorldToViewportPoint(worldPosition00, targetPose, projection); + Vector2 p01 = WorldToViewportPoint(worldPosition01, targetPose, projection); + Vector2 p11 = WorldToViewportPoint(worldPosition11, targetPose, projection); + Vector2 p10 = WorldToViewportPoint(worldPosition10, targetPose, projection); + + float a = p10.x - p11.x; + float b = p01.x - p11.x; + float c = p00.x - p01.x - p10.x + p11.x; + float d = p10.y - p11.y; + float e = p01.y - p11.y; + float f = p00.y - p01.y - p10.y + p11.y; + + float g = (c * d - a * f) / (b * d - a * e); + float h = (c * e - b * f) / (a * e - b * d); + + return new Matrix4x4 + ( + new Vector4(p10.x - p00.x + h * p10.x, p10.y - p00.y + h * p10.y, h), + new Vector4(p01.x - p00.x + g * p01.x, p01.y - p00.y + g * p01.y, g), + new Vector4(p00.x, p00.y, 1.0f), + new Vector4(0, 0, 0, 1) + ).inverse; + } + + // Returns an affine transformation such that if multiplied + // with normalized coordinates of the target coordinate frame, + // the results are normalized coordinates in the source + // coordinate frame. + // @notes + // E.g. if source is defined by an awareness buffer and + // target is defined by the viewport, normalized viewport + // coordinates multiplied with this transform will result + // in normalized coordinates in the awareness buffer. + // Further more, if source is defined by the AR image and + // the target is the viewport, this matrix will be equivalent + // to the display transform provided by the ARKit framework. + private static Matrix4x4 AffineFit + ( + float sourceWidth, + float sourceHeight, + ScreenOrientation sourceOrientation, + float targetWidth, + float targetHeight, + ScreenOrientation targetOrientation + ) + { + var rotatedContainer = RotateResolution + (sourceWidth, sourceHeight, sourceOrientation, targetOrientation); + + // Calculate scaling + var targetRatio = targetWidth / targetHeight; + var s = targetRatio < 1.0f + ? new Vector2(targetWidth / (targetHeight / rotatedContainer.y * rotatedContainer.x), 1.0f) + : new Vector2(1.0f, targetHeight / (targetWidth / rotatedContainer.x * rotatedContainer.y)); + + var rotate = GetAffineRotation(from: sourceOrientation, to: targetOrientation); + var scale = AffineScale(s); + var translate = AffineTranslation(new Vector2((1.0f - s.x) * 0.5f, (1.0f - s.y) * 0.5f)); + + return rotate * translate * scale; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static Matrix4x4 AffineRotation(double rad) + { + return new Matrix4x4 + ( + new Vector4((float)Math.Cos(rad), (float)Math.Sin(rad), 0, 0), + new Vector4((float)-Math.Sin(rad), (float)Math.Cos(rad), 0, 0), + new Vector4(0, 0, 1, 0), + new Vector4(0, 0, 0, 1) + ); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static Matrix4x4 AffineTranslation(Vector2 translation) + { + return new Matrix4x4 + ( + new Vector4(1, 0, 0, 0), + new Vector4(0, 1, 0, 0), + new Vector4(0, 0, 1, 0), + new Vector4(translation.x, translation.y, 0, 1) + ); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static Matrix4x4 AffineInvertHorizontal() + { + return _affineInvertHorizontalMatrix; + } + private static readonly Matrix4x4 _affineInvertHorizontalMatrix = new Matrix4x4 + ( + new Vector4(-1, 0, 0, 0), + new Vector4(0, 1, 0, 0), + new Vector4(0, 0, 1, 0), + new Vector4(1, 0, 0, 1) + ); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static Matrix4x4 AffineInvertVertical() + { + return _affineInvertVerticalMatrix; + } + private static readonly Matrix4x4 _affineInvertVerticalMatrix = new Matrix4x4 + ( + new Vector4(1, 0, 0, 0), + new Vector4(0, -1, 0, 0), + new Vector4(0, 0, 1, 0), + new Vector4(0, 1, 0, 1) + ); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static Matrix4x4 AffineScale(Vector2 scale) + { + return new Matrix4x4 + ( + new Vector4(scale.x, 0, 0, 0), + new Vector4(0, scale.y, 0, 0), + new Vector4(0, 0, 1, 0), + new Vector4(0, 0, 0, 1) + ); + } + + internal static Resolution CalculateDisplayFrame + ( + float sourceWidth, + float sourceHeight, + float viewportWidth, + float viewportHeight + ) + { + // Infer target orientation + var targetOrientation = viewportWidth > viewportHeight + ? ScreenOrientation.LandscapeLeft + : ScreenOrientation.Portrait; + + // Infer source orientation + var sourceOrientation = sourceWidth > sourceHeight + ? ScreenOrientation.LandscapeLeft + : ScreenOrientation.Portrait; + + Vector2 target = RotateResolution + ( + viewportWidth, + viewportHeight, + targetOrientation, + sourceOrientation + ); + + // Calculate scaling + var s = sourceOrientation == ScreenOrientation.Portrait + ? new Vector2(target.x / (target.y / sourceHeight * sourceWidth), 1.0f) + : new Vector2(1.0f, target.y / (target.x / sourceWidth * sourceHeight)); + + return new Resolution + { + width = Mathf.FloorToInt(sourceWidth * s.x), height = Mathf.FloorToInt(sourceHeight * s.y) + }; + } + + /// Calculates a rotation matrix that transforms a view + /// matrix from one screen orientation to another. + internal static Matrix4x4 CalculateViewRotation(ScreenOrientation from, ScreenOrientation to) + { + // Get the rotation between the screen orientations + var angle = (float)GetAngle(from, to) * Mathf.Rad2Deg; + + return Matrix4x4.Rotate + ( + // The view rotation the opposite of the UI rotation + Quaternion.AngleAxis(-angle, Vector3.forward) + ); + } + + /// Calculates an affine rotation matrix that transforms + /// an image from one screen orientation to another. + internal static Matrix4x4 CalculateScreenRotation(ScreenOrientation from, ScreenOrientation to) + { + return AffineRotation(GetAngle(from, to)); + } + + /// Transforms a viewport coordinate to world space. + /// @param viewPosition Coordinate to transform. + /// @param view View matrix. + /// @param projection Projection matrix. + /// @param distanceNormalized Defines how far the transformed point should be from the view. + /// @returns The point in world space. + private static Vector3 ViewportToWorldPoint + ( + Vector2 viewPosition, + Matrix4x4 view, + Matrix4x4 projection, + float distanceNormalized + ) + { + var clipCoordinates = new Vector4 + ( + viewPosition.x * 2.0f - 1.0f, + viewPosition.y * 2.0f - 1.0f, + distanceNormalized * 2.0f - 1.0f, + 1.0f + ); + + var viewProjectionInverted = (projection * view).inverse; + var result = viewProjectionInverted * clipCoordinates; + + if (Mathf.Approximately(result.w, 0.0f)) + { + return Vector3.zero; + } + + result.w = 1.0f / result.w; + result.x *= result.w; + result.y *= result.w; + result.z *= result.w; + + return result; + } + + /// Projects the specified world position to view space. + /// @param worldPosition Position to transform. + /// @param view View matrix. + /// @param projection Projection matrix. + /// @returns The world position in view space. + private static Vector2 WorldToViewportPoint + ( + Vector3 worldPosition, + Matrix4x4 view, + Matrix4x4 projection + ) + { + var position = new Vector4(worldPosition.x, worldPosition.y, worldPosition.z, 1.0f); + var transformed = view * position; + var projected = projection * transformed; + + if (Mathf.Approximately(projected.w, 0.0f)) + { + return Vector2.zero; + } + + projected.w = 1.0f / projected.w; + projected.x *= projected.w; + projected.y *= projected.w; + projected.z *= projected.w; + + return new Vector2(projected.x * 0.5f + 0.5f, projected.y * 0.5f + 0.5f); + } + + /// Calculates the angle to rotate from one screen orientation to another in radians. + /// @param from Original orientation. + /// @param to Target orientation. + /// @returns Angle to rotate to get from one orientation to the other. + private static double GetAngle(ScreenOrientation from, ScreenOrientation to) + { + const double rotationUnit = Math.PI / 2.0; + return (ScreenOrientationLookup[to] - ScreenOrientationLookup[from]) * rotationUnit; + } + + private static readonly IDictionary ScreenOrientationLookup = + new Dictionary + { + { + ScreenOrientation.LandscapeLeft, 0 + }, + { + ScreenOrientation.Portrait, 1 + }, + { + ScreenOrientation.LandscapeRight, 2 + }, + { + ScreenOrientation.PortraitUpsideDown, 3 + } + }; + + /// Calculates an affine transformation to rotate from one screen orientation to another + /// around the pivot. + /// @param from Original orientation. + /// @param to Target orientation. + /// @returns An affine matrix to be applied to normalized image coordinates. + private static Matrix4x4 GetAffineRotation(ScreenOrientation from, ScreenOrientation to) + { + // Rotate around the center + var pivot = new Vector2(0.5f, 0.5f); + return AffineTranslation(pivot) * + AffineRotation(GetAngle(from, to)) * + AffineTranslation(-pivot); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static Vector2 RotateResolution + ( + float sourceWidth, + float sourceHeight, + ScreenOrientation sourceOrientation, + ScreenOrientation targetOrientation + ) + { + if (sourceOrientation == ScreenOrientation.LandscapeLeft) + { + return + targetOrientation == ScreenOrientation.LandscapeLeft || + targetOrientation == ScreenOrientation.LandscapeRight + ? new Vector2(sourceWidth, sourceHeight) + : new Vector2(sourceHeight, sourceWidth); + } + + return + targetOrientation == ScreenOrientation.Portrait || + targetOrientation == ScreenOrientation.PortraitUpsideDown + ? new Vector2(sourceWidth, sourceHeight) + : new Vector2(sourceHeight, sourceWidth); + } + + private static Vector2 RotateVector(Vector2 vector, float radians) + { + float sin = Mathf.Sin(radians); + float cos = Mathf.Cos(radians); + + float x = vector.x; + float y = vector.y; + vector.x = cos * x - sin * y; + vector.y = sin * x + cos * y; + + return vector; + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/Utilities/MathUtils.cs.meta b/Assets/ARDK/Utilities/MathUtils.cs.meta new file mode 100644 index 0000000..6ad30cb --- /dev/null +++ b/Assets/ARDK/Utilities/MathUtils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5d832930bc5a544acbd80f7e1f452087 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/MatrixUtils.cs b/Assets/ARDK/Utilities/MatrixUtils.cs new file mode 100644 index 0000000..4bca6b3 --- /dev/null +++ b/Assets/ARDK/Utilities/MatrixUtils.cs @@ -0,0 +1,40 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using UnityEngine; + +namespace Niantic.ARDK.Utilities +{ + /// A utility class to help grepping information from matrices. + public static class MatrixUtils + { + /// Returns the position from a transform matrix. + /// @param matrix The matrix from which to extract the position. + public static Vector3 PositionFromMatrix(Matrix4x4 matrix) + { + Vector3 position = matrix.GetColumn(3); + return position; + } + + public static Vector3 ToPosition(this Matrix4x4 matrix) + { + return PositionFromMatrix(matrix); + } + + /// Returns the rotation as a quaternion from a transform matrix + /// @param matrix The matrix from which to extract the rotation. + /// @note This does not work on matrices with negative scale values. + public static Quaternion RotationFromMatrix(Matrix4x4 matrix) + { + // Adapted from https://answers.unity.com/questions/402280/how-to-decompose-a-trs-matrix.html + return Quaternion.LookRotation(matrix.GetColumn(2), matrix.GetColumn(1)); + } + + /// Returns the rotation as a quaternion from a transform matrix + /// @param matrix The matrix from which to extract the rotation. + /// @note This does not work on matrices with negative scaled values. + public static Quaternion ToRotation(this Matrix4x4 matrix) + { + return RotationFromMatrix(matrix); + } + } +} diff --git a/Assets/ARDK/Utilities/MatrixUtils.cs.meta b/Assets/ARDK/Utilities/MatrixUtils.cs.meta new file mode 100644 index 0000000..6c39e0b --- /dev/null +++ b/Assets/ARDK/Utilities/MatrixUtils.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 91623ce249a6d4b4186fcb71144e041e +timeCreated: 1525206722 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/NARConversions.cs b/Assets/ARDK/Utilities/NARConversions.cs new file mode 100644 index 0000000..7fd26b3 --- /dev/null +++ b/Assets/ARDK/Utilities/NARConversions.cs @@ -0,0 +1,43 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using UnityEngine; + +namespace Niantic.ARDK.Utilities +{ + /// A utility class to help convert between NAR and Unity coordinate frames + public static class NARConversions + { + private static readonly Vector3 _signVector3 = new Vector3(1, -1, 1); + + public static Vector3 FromNARToUnity(Vector3 point) + { + return Vector3.Scale(point, _signVector3); + } + + private static readonly Matrix4x4 _signMatrix4x4 = + new Matrix4x4 + ( + new Vector4(1, 0, 0, 0), + new Vector4(0, -1, 0, 0), + new Vector4(0, 0, 1, 0), + new Vector4(0, 0, 0, 1) + ); + + public static Matrix4x4 FromNARToUnity(Matrix4x4 matrix) + { + // Sy [R|T] Sy + // [0|1] + return _signMatrix4x4 * matrix * _signMatrix4x4; + } + + public static Vector3 FromUnityToNAR(Vector3 point) + { + return FromNARToUnity(point); + } + + public static Matrix4x4 FromUnityToNAR(Matrix4x4 matrix) + { + return FromNARToUnity(matrix); + } + } +} diff --git a/Assets/ARDK/Utilities/NARConversions.cs.meta b/Assets/ARDK/Utilities/NARConversions.cs.meta new file mode 100644 index 0000000..8dfa739 --- /dev/null +++ b/Assets/ARDK/Utilities/NARConversions.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 8bd4e74b10db64a6e805ca66e34f371a +timeCreated: 1541733168 +licenseType: Pro +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/Optional.cs b/Assets/ARDK/Utilities/Optional.cs new file mode 100644 index 0000000..e4db847 --- /dev/null +++ b/Assets/ARDK/Utilities/Optional.cs @@ -0,0 +1,168 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +namespace Niantic.ARDK.Utilities +{ + /// + /// A value that may not exist. + /// + /// + /// + /// Optional provides implicit conversion between itself and T and explicit for the + /// opposite. + /// + public struct Optional: + IEquatable>, + IEquatable + { + private T _value; + private bool _hasValue; + + /// + /// True when a value does exist. + /// + public bool HasValue + { + get { return _hasValue; } + } + + /// + /// Gets or sets the value. + /// + /// + /// If getting the value and there is no value. + /// + public T Value + { + get + { + if (!_hasValue) + throw new NullReferenceException(); + + return _value; + } + set + { + _value = value; + _hasValue = (value != null); + } + } + + /// + /// Creates a new optional with a given default value. + /// + /// + public Optional(T value) + { + _value = value; + _hasValue = (value != null); + } + + /// + /// Clears the value. + /// + public void Clear() + { + _hasValue = false; + _value = default(T); + } + + /// + /// Checks the equality between two Optionals + /// + /// + /// + public bool Equals(Optional other) + { + if (_hasValue != other._hasValue) + return false; + + if (!_hasValue) + return true; + + return _value.Equals(other._value); + } + + /// + /// Checks the equality between and Optional and T + /// + /// + /// + public bool Equals(T other) + { + if (other == null) + return !_hasValue; + + return _value.Equals(other); + } + + /// + /// Returns the value of the optional, or the default of T if no value has been set + /// + /// + public T GetOrDefault() + { + return _value; + } + + public override bool Equals(object obj) + { + if (obj is Optional) + return Equals((Optional)obj); + + if (obj is T) + return Equals((T)obj); + + return false; + } + + public override int GetHashCode() + { + if (!_hasValue) + return 0; + + return _value.GetHashCode(); + } + + public static explicit operator T(Optional optional) + { + return optional.Value; + } + + public static implicit operator Optional(T value) + { + return new Optional(value); + } + + public static bool operator ==(Optional a, Optional b) + { + return a.Equals(b); + } + + public static bool operator !=(Optional a, Optional b) + { + return !(a == b); + } + + public static bool operator ==(Optional a, T b) + { + return a.Equals(b); + } + + public static bool operator !=(Optional a, T b) + { + return !(a == b); + } + + public static bool operator ==(T a, Optional b) + { + return b.Equals(a); + } + + public static bool operator !=(T a, Optional b) + { + return !(a == b); + } + } +} diff --git a/Assets/ARDK/Utilities/Optional.cs.meta b/Assets/ARDK/Utilities/Optional.cs.meta new file mode 100644 index 0000000..9cc939f --- /dev/null +++ b/Assets/ARDK/Utilities/Optional.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3b34e4516fdb4767af2e17715cb15ec1 +timeCreated: 1551209621 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/PermissionRequester.cs b/Assets/ARDK/Utilities/PermissionRequester.cs new file mode 100644 index 0000000..7127e40 --- /dev/null +++ b/Assets/ARDK/Utilities/PermissionRequester.cs @@ -0,0 +1,147 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +using Niantic.ARDK.Utilities.Logging; + +#if UNITY_ANDROID +using UnityEngine; +using UnityEngine.Android; +#endif + +namespace Niantic.ARDK.Utilities.Permissions +{ + /// Permission types ARDK supports requesting from the user + public enum ARDKPermission + { + Camera, + Microphone, + FineLocation, + CoarseLocation, + ExternalStorageRead, + ExternalStorageWrite + } + + public enum PermissionStatus + { + /// User has granted permission + Granted, + + /// The user has denied the permission but not selected "Don't ask again." + Denied, + + /// The user has denied permission and selected "Don't ask again," + /// or is restricted from granting the permission. + DeniedAndCannotRequest, + + Unknown + } + + /// Static class for requesting permissions at runtime. We recommend following Android's + /// guideline for requesting permissions found here: https://developer.android.com/training/permissions/requesting + /// @note + /// Only valid on Android. Permission requests will pop up automatically on iOS devices when an + /// app starts a certain service that requires an ungranted permission. + public class PermissionRequester + { +#if UNITY_ANDROID + internal static readonly Dictionary AndroidPermissionString = + new Dictionary + { + { ARDKPermission.Camera, Permission.Camera }, + { ARDKPermission.Microphone, Permission.Microphone }, + { ARDKPermission.FineLocation, Permission.FineLocation }, + { ARDKPermission.CoarseLocation, Permission.CoarseLocation }, + { ARDKPermission.ExternalStorageRead, Permission.ExternalStorageRead }, + { ARDKPermission.ExternalStorageWrite, Permission.ExternalStorageWrite }, + }; + + /// Request a permission. + /// @param permission The permission to request. + public static async Task RequestPermissionAsync(ARDKPermission permission) + { + return await RequestPermissionAsync(AndroidPermissionString[permission]); + } + + /// Request a permission that ARDK does not have an enum for. + /// @param permission + /// The permission to request. Must be one of the constant values provided in the Android + /// documentation here: https://developer.android.com/reference/android/Manifest.permission + /// @note + /// Method is not really async (it's wrapping Unity's callback-based permissions API). But + /// it's named -Async because it's awaitable. + public static Task RequestPermissionAsync(string permissionName) + { + var t = new TaskCompletionSource(); + RequestPermission(permissionName, (status) => t.TrySetResult(status)); + + return t.Task; + } + + /// Request a permission. + /// @param permission + /// The permission to request. + /// @param callback + /// Method invoked once permission request popup has been closed. + public static void RequestPermission(ARDKPermission permission, Action callback) + { + RequestPermission(AndroidPermissionString[permission], callback); + } + + /// Request a permission that ARDK does not have an enum for. + /// @param permission + /// The permission to request. Must be one of the constant values provided in the Android + /// documentation here: https://developer.android.com/reference/android/Manifest.permission + /// @param callback + /// Method invoked once permission request popup has been closed. + public static void RequestPermission(string permissionName, Action callback) + { + if (HasPermission(permissionName)) + { + ARLog._Debug($"Requested permission for {permissionName} but it was already granted"); + callback.Invoke(PermissionStatus.Granted); + return; + } + + var callbacks = new PermissionCallbacks(); + callbacks.PermissionGranted += status => callback.Invoke(PermissionStatus.Granted); + callbacks.PermissionDenied += status => callback.Invoke(PermissionStatus.Denied); + callbacks.PermissionDeniedAndDontAskAgain += status => callback.Invoke(PermissionStatus.DeniedAndCannotRequest); + + ARLog._Debug("Requesting permission for: " + permissionName); + Permission.RequestUserPermission(permissionName, callbacks); + } + + /// Check the status of an Android permission. + /// @param permission + /// The permission the check. + /// @returns + /// True if the permission has been granted. Will always return true in the Unity Editor. + public static bool HasPermission(ARDKPermission permission) + { + return HasPermission(AndroidPermissionString[permission]); + } + + /// Check permission status for permissions that ARDK does not have an enum for. + /// @param permissionName + /// The permission to check. Must be one of the constant values provided in the Android + /// documentation here: https://developer.android.com/reference/android/Manifest.permission + /// + /// @returns + /// True if the permission has been granted. Will always return true in the Unity Editor. + public static bool HasPermission(string permissionName) + { +#if UNITY_EDITOR + var granted = true; +#else + var granted = Permission.HasUserAuthorizedPermission(permissionName); +#endif + ARLog._DebugFormat("{0} Permission: {1}", false, permissionName, granted ? "Granted" : "Not Granted" ); + return granted; + } +#endif + } +} \ No newline at end of file diff --git a/Assets/ARDK/Utilities/PermissionRequester.cs.meta b/Assets/ARDK/Utilities/PermissionRequester.cs.meta new file mode 100644 index 0000000..b27f052 --- /dev/null +++ b/Assets/ARDK/Utilities/PermissionRequester.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ee250dd9c2f7f47b6aaf408b385e0b11 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/Platform.cs b/Assets/ARDK/Utilities/Platform.cs new file mode 100644 index 0000000..68a7c49 --- /dev/null +++ b/Assets/ARDK/Utilities/Platform.cs @@ -0,0 +1,49 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Runtime.InteropServices; + +using Niantic.ARDK.AR; + +using UnityEngine; + +using Niantic.ARDK.Internals; +using Niantic.ARDK.Utilities.Logging; + +namespace Niantic.ARDK +{ + /// Internal helper class to initialize the platform. + /// @remark Each ARDK class has a static initializer that will ensure Platform.Init() is called + /// before any property or method is accessed/called. + internal static class Platform + { + private static bool _initAttempted; + + /// Initialize platform. + internal static void Init() + { + if (_initAttempted) + { + return; + } + + if (NativeAccess.Mode == NativeAccess.ModeType.Native) + { + ARLog._Debug("Initializing native ARDK systems"); + try + { + _ARDK_Init_Platform(); + } + catch (DllNotFoundException e) + { + ARLog._DebugFormat("Failed to initialize native ARDK systems: {0}", false, e); + } + } + + _initAttempted = true; + } + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _ARDK_Init_Platform(); + } +} diff --git a/Assets/ARDK/Utilities/Platform.cs.meta b/Assets/ARDK/Utilities/Platform.cs.meta new file mode 100644 index 0000000..6072131 --- /dev/null +++ b/Assets/ARDK/Utilities/Platform.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: cef4a9504a3f04080a93cc63f3f65eac +timeCreated: 1525206586 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/Preloading.meta b/Assets/ARDK/Utilities/Preloading.meta new file mode 100644 index 0000000..86795e8 --- /dev/null +++ b/Assets/ARDK/Utilities/Preloading.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7a2a068efbeed4391ba6b8e2567360d8 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/Preloading/Feature.cs b/Assets/ARDK/Utilities/Preloading/Feature.cs new file mode 100644 index 0000000..741285b --- /dev/null +++ b/Assets/ARDK/Utilities/Preloading/Feature.cs @@ -0,0 +1,14 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.Utilities.Preloading +{ + public enum Feature + { + /// Used by computer vision algorithms to generate semantic segmentation, depth, and mesh data. + ContextAwareness = 0, + + /// Used by computer vision algorithms to synchronize multiple devices to the + /// same coordinate space. + Dbow = 1 + } +} \ No newline at end of file diff --git a/Assets/ARDK/Utilities/Preloading/Feature.cs.meta b/Assets/ARDK/Utilities/Preloading/Feature.cs.meta new file mode 100644 index 0000000..5b02727 --- /dev/null +++ b/Assets/ARDK/Utilities/Preloading/Feature.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e0b0372adf4c4be98848ee99410024a0 +timeCreated: 1595363896 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/Preloading/FeaturePreloaderFactory.cs b/Assets/ARDK/Utilities/Preloading/FeaturePreloaderFactory.cs new file mode 100644 index 0000000..3ab617d --- /dev/null +++ b/Assets/ARDK/Utilities/Preloading/FeaturePreloaderFactory.cs @@ -0,0 +1,80 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.ComponentModel; + +using Niantic.ARDK.AR; +using Niantic.ARDK.Utilities.Logging; +using Niantic.ARDK.VirtualStudio.Remote; + +namespace Niantic.ARDK.Utilities.Preloading +{ + public static class FeaturePreloaderFactory + { + public static IFeaturePreloader Create() + { + return _Create(); + } + + public static IFeaturePreloader Create(RuntimeEnvironment env) + { + switch (env) + { + case RuntimeEnvironment.Mock: + return new _MockFeaturePreloader(); + + case RuntimeEnvironment.Remote: + if (!_RemoteConnection.IsEnabled) + return null; + + ARLog._Warn + ( + "Preloading is not yet supported over Remote. Required features will be downloaded " + + "to the ARSession when it is run on device." + ); + + return new _MockFeaturePreloader(); + + case RuntimeEnvironment.LiveDevice: +#pragma warning disable CS0162 + if (NativeAccess.Mode != NativeAccess.ModeType.Native && + NativeAccess.Mode != NativeAccess.ModeType.Testing) + return null; +#pragma warning restore CS0162 + + return new _NativeFeaturePreloader(); + } + + return null; + } + + private static readonly RuntimeEnvironment[] _bestMatches = + { RuntimeEnvironment.LiveDevice, RuntimeEnvironment.Remote, RuntimeEnvironment.Mock}; + + internal static IFeaturePreloader _Create + ( + IEnumerable sources = null + ) + { + bool triedAtLeast1 = false; + + if (sources != null) + { + foreach (var source in sources) + { + var possibleResult = Create(source); + if (possibleResult != null) + return possibleResult; + + triedAtLeast1 = true; + } + } + + if (!triedAtLeast1) + return _Create(_bestMatches); + + throw new NotSupportedException("None of the provided sources are supported by this build."); + } + } +} diff --git a/Assets/ARDK/Utilities/Preloading/FeaturePreloaderFactory.cs.meta b/Assets/ARDK/Utilities/Preloading/FeaturePreloaderFactory.cs.meta new file mode 100644 index 0000000..4cba090 --- /dev/null +++ b/Assets/ARDK/Utilities/Preloading/FeaturePreloaderFactory.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 83d18f1b4e314c6583038be0beb4c807 +timeCreated: 1595368107 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/Preloading/IFeaturePreloader.cs b/Assets/ARDK/Utilities/Preloading/IFeaturePreloader.cs new file mode 100644 index 0000000..f1c35db --- /dev/null +++ b/Assets/ARDK/Utilities/Preloading/IFeaturePreloader.cs @@ -0,0 +1,42 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +namespace Niantic.ARDK.Utilities.Preloading +{ + /// Interface for ARDK class that pre-downloads all necessary assets for certain ARDK features + /// to function. If the files are not preloaded, they will take time to download when an + /// ARSession configured to use those features is run. + public interface IFeaturePreloader: + IDisposable + { + /// @param feature + /// @returns + /// A value in the range of [0.0, 1.0] representing how much progress has been made + /// downloading the specified feature. + float GetProgress(Feature feature); + + /// @param feature + /// @returns + /// The current preload state of the specified feature. On device, if this feature was cleared + /// from the cache after it was completely downloaded, it will still return the last + /// known status. + PreloadedFeatureState GetStatus(Feature feature); + + /// @param feature + /// @returns + /// True if the specified feature was found in the application's cache. + /// When running in Virtual Studio's Mock mode, features will disappear from the cache + /// when the preloader is disposed. + bool ExistsInCache(Feature feature); + + /// Begin the download of all added features. Calling this after an ARSession has already run + /// is undefined behaviour. + void Download(Feature[] features); + + /// Clears this feature from the application's cache. Calling this while a download is in process, + /// or while downloaded features are being used in an ARSession, is invalid and will result in + /// undefined behaviour. + void ClearCache(Feature feature); + } +} \ No newline at end of file diff --git a/Assets/ARDK/Utilities/Preloading/IFeaturePreloader.cs.meta b/Assets/ARDK/Utilities/Preloading/IFeaturePreloader.cs.meta new file mode 100644 index 0000000..6be59eb --- /dev/null +++ b/Assets/ARDK/Utilities/Preloading/IFeaturePreloader.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 980ca18c5d294c85bba178cd3357d71a +timeCreated: 1595363896 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/Preloading/PreloadedFeatureState.cs b/Assets/ARDK/Utilities/Preloading/PreloadedFeatureState.cs new file mode 100644 index 0000000..34830fe --- /dev/null +++ b/Assets/ARDK/Utilities/Preloading/PreloadedFeatureState.cs @@ -0,0 +1,13 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.Utilities.Preloading +{ + public enum PreloadedFeatureState + { + Invalid = 0, + NotStarted, + Downloading, + Finished, + Failed + }; +} \ No newline at end of file diff --git a/Assets/ARDK/Utilities/Preloading/PreloadedFeatureState.cs.meta b/Assets/ARDK/Utilities/Preloading/PreloadedFeatureState.cs.meta new file mode 100644 index 0000000..ca26785 --- /dev/null +++ b/Assets/ARDK/Utilities/Preloading/PreloadedFeatureState.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 8ef1a710fe134be7ba745c20c551843a +timeCreated: 1595363895 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/Preloading/_MockFeaturePreloader.cs b/Assets/ARDK/Utilities/Preloading/_MockFeaturePreloader.cs new file mode 100644 index 0000000..83e51e8 --- /dev/null +++ b/Assets/ARDK/Utilities/Preloading/_MockFeaturePreloader.cs @@ -0,0 +1,103 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System.Collections.Generic; +using System.Linq; + +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; + +namespace Niantic.ARDK.Utilities.Preloading +{ + internal class _MockFeaturePreloader: + IFeaturePreloader + { + private HashSet _cache = new HashSet(); + private Dictionary _progress = new Dictionary(); + private bool _downloading; + + public void Dispose() + { + _cache.Clear(); + _UpdateLoop.Tick -= ProgressDownloads; + } + + public float GetProgress(Feature feature) + { + if (_cache.Contains(feature)) + return 1; + + if (_progress.TryGetValue(feature, out float value)) + return value; + + return 0; + } + + public PreloadedFeatureState GetStatus(Feature feature) + { + if (_cache.Contains(feature)) + return PreloadedFeatureState.Finished; + + if (_progress.ContainsKey(feature)) + return PreloadedFeatureState.Downloading; + + return PreloadedFeatureState.Invalid; + } + + public bool ExistsInCache(Feature feature) + { + return _cache.Contains(feature); + } + + public void Download(Feature[] features) + { + foreach (var feature in features) + { + if (!_cache.Contains(feature)) + _progress.Add(feature, 0f); + } + + if (!_downloading) + { + _downloading = true; + _UpdateLoop.FixedTick += ProgressDownloads; + } + } + + // Default value of Time.fixedDeltaTime is 0.02 (50 calls per second), meaning a download will + // take about 2 seconds to complete (likely enough to see any UI changes dependent on progress). + private const float _progressIncrement = 0.01f; + private void ProgressDownloads() + { + foreach (var feature in _progress.Keys.ToArray()) + { + var currProgress = _progress[feature] + _progressIncrement; + + if (currProgress > 1) + { + _progress.Remove(feature); + _cache.Add(feature); + + if (_progress.Count == 0) + { + _downloading = false; + _UpdateLoop.FixedTick -= ProgressDownloads; + } + } + else + { + _progress[feature] = currProgress; + } + } + } + + public void ClearCache(Feature feature) + { + if (_downloading) + ARLog._Error("Attempted to clear the preloader cache while downloads were in progress."); + + _downloading = false; + _UpdateLoop.Tick -= ProgressDownloads; + _cache.Remove(feature); + } + } +} diff --git a/Assets/ARDK/Utilities/Preloading/_MockFeaturePreloader.cs.meta b/Assets/ARDK/Utilities/Preloading/_MockFeaturePreloader.cs.meta new file mode 100644 index 0000000..65d76d5 --- /dev/null +++ b/Assets/ARDK/Utilities/Preloading/_MockFeaturePreloader.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 228ce40f94134397bcbb6ec049b097b0 +timeCreated: 1626358714 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/Preloading/_NativeFeaturePreloader.cs b/Assets/ARDK/Utilities/Preloading/_NativeFeaturePreloader.cs new file mode 100644 index 0000000..472ff08 --- /dev/null +++ b/Assets/ARDK/Utilities/Preloading/_NativeFeaturePreloader.cs @@ -0,0 +1,108 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.Configuration; +using Niantic.ARDK.Configuration; +using Niantic.ARDK.Internals; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; + +namespace Niantic.ARDK.Utilities.Preloading +{ + internal sealed class _NativeFeaturePreloader: + IFeaturePreloader + { + private IntPtr _nativeHandle; + + private const string _dbowUrl = "https://bowvocab.eng.nianticlabs.com/dbow_b50_l3.bin"; + + internal _NativeFeaturePreloader() + { + _nativeHandle = _NAR_ARDKFilePreloader_Init(); + } + + ~_NativeFeaturePreloader() + { + _NAR_ARDKFilePreloader_Release(_nativeHandle); + } + + public void Dispose() + { + GC.SuppressFinalize(this); + + var nativeHandle = _nativeHandle; + if (nativeHandle != IntPtr.Zero) + { + _nativeHandle = IntPtr.Zero; + + _NAR_ARDKFilePreloader_Release(nativeHandle); + } + } + + public float GetProgress(Feature feature) + { + return _NAR_ARDKFilePreloader_CurrentProgress(_nativeHandle, (UInt32)feature); + } + + public PreloadedFeatureState GetStatus(Feature feature) + { + return (PreloadedFeatureState)_NAR_ARDKFilePreloader_GetStatus(_nativeHandle, (UInt32)feature); + } + + public bool ExistsInCache(Feature feature) + { + return _NAR_ARDKFilePreloader_ExistsInCache(_nativeHandle, (UInt32)feature); + } + + public void Download(Feature[] features) + { + // Todo: This should really be done in native + if (features.Contains(Feature.Dbow) && string.IsNullOrEmpty(ArdkGlobalConfig.GetDbowUrl())) + ArdkGlobalConfig.SetDbowUrl(ArdkGlobalConfig._DBOW_URL); + + UInt32[] featuresInts = Array.ConvertAll(features, value => (UInt32) value); + _NAR_ARDKFilePreloader_Download(_nativeHandle, featuresInts, featuresInts.Length); + } + + public void ClearCache(Feature feature) + { + _NAR_ARDKFilePreloader_ClearFromCache(_nativeHandle, (UInt32)feature); + } + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NAR_ARDKFilePreloader_Init(); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NAR_ARDKFilePreloader_Download + ( + IntPtr ptr, + UInt32[] features, + int numFeatures + ); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NAR_ARDKFilePreloader_Release(IntPtr ptr); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern float _NAR_ARDKFilePreloader_CurrentProgress(IntPtr ptr, UInt32 feature); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern byte _NAR_ARDKFilePreloader_GetStatus(IntPtr ptr, UInt32 feature); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern bool _NAR_ARDKFilePreloader_ExistsInCache(IntPtr ptr, UInt32 feature); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NAR_ARDKFilePreloader_ClearFromCache(IntPtr ptr, UInt32 feature); + + // Returns true if the status is Finished or Failed + [DllImport(_ARDKLibrary.libraryName)] + private static extern bool _NAR_ARDKFilePreloader_IsDownloadFinished(IntPtr ptr, UInt32 feature); + } +} \ No newline at end of file diff --git a/Assets/ARDK/Utilities/Preloading/_NativeFeaturePreloader.cs.meta b/Assets/ARDK/Utilities/Preloading/_NativeFeaturePreloader.cs.meta new file mode 100644 index 0000000..5a17c74 --- /dev/null +++ b/Assets/ARDK/Utilities/Preloading/_NativeFeaturePreloader.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c8af40b1f655428fbeab354e2d16b130 +timeCreated: 1595366649 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/SafeGCHandle.cs b/Assets/ARDK/Utilities/SafeGCHandle.cs new file mode 100644 index 0000000..023ea3f --- /dev/null +++ b/Assets/ARDK/Utilities/SafeGCHandle.cs @@ -0,0 +1,245 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Concurrent; +using System.Runtime.InteropServices; +using System.Threading; +using UnityEngine; + +namespace Niantic.ARDK.Utilities +{ + /// This class has the purpose of allowing C# objects to be passed to native code as a "handle" + /// and then obtained back when native code calls back into C#. This is effectively the same + /// purpose as the GCHandle struct, yet this one is somewhat safer, as it will consistently return + /// null if we try to get a value of a freed handle, while the one from .NET might return null, + /// might throw an exception or, even worse, might return an invalid value. + public static class SafeGCHandle + { + // This number needs to be a power of 2. That's why bit-shifting is the best option. + private const uint kParallelism = 1 << 3; + + // Assuming kParallelism is a multiple of 2, this will have all the lower bytes set. + // We prefer to use & (and operator) instead of % (mod operator) because it is faster. + private const uint kBucketSelectorAnd = kParallelism - 1; + + // Maybe a TODO? + // Considering we are using ConcurrentDictionaries now, I am not sure how much improvement (if + // any) the kParallelism is giving us. As we keep adding and removing items, the kParallelism + // is probably helping us on resizes, but assuming we reach a good size, resizes should stop + // and then the ConcurrentDictionary is just "lock free" all the time... so, is this extra + // indirection with the array of ConcurrentDictionaries helping us or hurting us? + private static readonly ConcurrentDictionary[] _dictionaries = + new ConcurrentDictionary[kParallelism]; + + private static long _idGenerator; + static SafeGCHandle() + { + for (int i = 0; i < kParallelism; i++) + _dictionaries[i] = new ConcurrentDictionary(); + } + + /// Allocates a new handle for the given value, which guarantees that the object is kept alive + /// even if there are no other references, and returns it just as an IntPtr. A future call to + /// Free needs to be made, or there will be memory leaks. + /// + /// @param instance - The instance to create a handle for. null is a valid argument and will + /// just return the handle 0 (IntPtr.Zero). + /// + /// @return An IntPtr value that can be used to locate this instance again. + public static IntPtr AllocAsIntPtr(object instance) + { + if (instance == null) + return IntPtr.Zero; + + long id = Interlocked.Increment(ref _idGenerator); + uint bucketIndex = ((uint)id) & kBucketSelectorAnd; + IntPtr idAsIntPtr = new IntPtr(id); + var dictionary = _dictionaries[bucketIndex]; + _StaticMemberValidator._CollectionsAreEmptyWhenScopeEnds(() => _dictionaries); + + // As we are using an unique id generator, we know that the TryAdd is actually going to add. + // The only situation where it fails (without throwing) is if the key is duplicated. + dictionary.TryAdd(idAsIntPtr, instance); + + return idAsIntPtr; + } + + /// Allocates a new typed safe handle for the given instance. Such returned object is just a + /// struct and it will not release the object if it goes out-of-scope. This is on purpose, as + /// the intended use is to pass such handle to the native side and then allow the local one + /// to go out of scope. At a later point, the instance might be obtained by calling + /// TryGetInstance or another SafeGCHandle<T> can be reconstructed from its IntPtr + /// representation by calling SafeGCHandle<T>.FromIntPtr(handleValue). + /// The handle needs to be explicitly freed when we don't need to hold a reference to the + /// instance anymore by calling Free() (either from the typed SafeGCHandle or by giving its + /// IntPtr value). + /// + /// @param instance - The instance to create a handle to. If null is provided, a handle with ID + /// 0 will be returned. + /// + /// @return a SafeGCHandle to access this instance again. + public static SafeGCHandle Alloc(T instance) + where + T: class + { + IntPtr id = AllocAsIntPtr(instance); + return SafeGCHandle.FromIntPtr(id); + } + + /// Tries to get the instance of a previously allocated handle by the handle ID. This method + /// doesn't care about the actual type of the instance and will return it just as "object". + /// + /// @param id - The IntPtr ID of the allocated handle to access to the instance. This is + /// obtained by calling AllocAsIntPtr of by calling Alloc to get a handle and then + /// calling ToIntPtr() on the handle. + /// + /// @return Either the instance as object, or null if the id is either invalid or the handle + /// was already released. + public static object TryGetUntypedInstance(IntPtr id) + { + if (id == IntPtr.Zero) + return null; + + uint buckedIndex = ((uint)id) & kBucketSelectorAnd; + var dictionary = _dictionaries[buckedIndex]; + + object result; + dictionary.TryGetValue(id, out result); + + // If TryGetValue fails, it always sets result to null. + return result; + } + + /// Tries to get an instance referenced by its handle ID as the given generic T type. T must be + /// a class and null will be returned if either the result is null or the given T type is + /// incorrect. + /// + /// @param id - The IntPtr ID from the allocated handle that can be used to find the instance + /// again. + /// + /// @return Either the found instance or null. + public static T TryGetInstance(IntPtr id) + where + T : class + { + object untypedInstance = TryGetUntypedInstance(id); + + if (untypedInstance == null) + return null; + + T result = untypedInstance as T; + if (result == null) + { + Debug.Log( + "Tried to get instance of type " + untypedInstance.GetType().FullName + " as " + + typeof(T).FullName + " but that's not possible."); + } + + return result; + } + + /// Tries to free the handle identified by the given ID. + /// + /// @param id - The ID of the handle to free. + /// + /// @return True if such ID existed and was freed, false if it wasn't valid (either because + /// it never was or because it was being previously freed). + public static bool Free(IntPtr id) + { + if (id == IntPtr.Zero) + return false; + + uint buckedIndex = ((uint)id) & kBucketSelectorAnd; + var dictionary = _dictionaries[buckedIndex]; + return dictionary.TryRemove(id, out _); + } + } + + /// Represents a type-safe, SafeGCHandle, that can be used to either get access to the instance + /// again, to obtain its IntPtr ID, or to free the handle. + /// + /// This struct is marshalled just as the IntPtr ID it contains, so [DllImport] methods that need + /// to receive or return handles of a particular type can request for a + /// SafeGCHandle<SomeType> instead of requesting just for an IntPtr. + [StructLayout(LayoutKind.Sequential)] + public struct SafeGCHandle: + IEquatable> + where + T: class + { + /// Instantiates a new SafeGCHandle<T> from a provided IntPtr ID. This action never fails + /// but if the ID is invalid, a future call to TryGetInstance() will return null. + /// + /// @param id - The IntPtr ID that represents the allocated handle. + public static SafeGCHandle FromIntPtr(IntPtr id) + { + return new SafeGCHandle(id); + } + + private readonly IntPtr _id; + private SafeGCHandle(IntPtr id) + { + _id = id; + } + + /// Gets the inner IntPtr ID of this safe-handle. + /// + /// @return The IntPtr ID of this safe-handle. + public IntPtr ToIntPtr() + { + return _id; + } + + /// Tries to get the instance represented by this safe-handle, already cast to its right type. + /// + /// @return Either the typed-instance or null (if the handle is invalid, deallocated or of the + /// wrong type). + public T TryGetInstance() + { + return SafeGCHandle.TryGetInstance(_id); + } + + /// Tries to free the effective handle this struct represents. + /// + /// @return Either true if the handle was valid and was deallocated, or false if the handle + /// was somehow invalid (either already deallocated or never allocated). + public bool Free() + { + return SafeGCHandle.Free(_id); + } + + /// Returns the hashcode of this handle, which is effectively the hashcode of its IntPtr ID. + /// + /// @return The hashcode of the ID of this handle. + public override int GetHashCode() + { + return _id.GetHashCode(); + } + + /// Compares this handle to any object. It can only return true if obj is actually another + /// SafeGCHandle of the same T type and pointing to the same ID. + /// + /// @returns true if the provided obj is a SafeGCHandle of the same type and referencing the + /// same ID. Note that two SafeGCHandles with different IDs that point to the same + /// instance are still considered different, as each one of them need to be Free()d + /// separately. + public override bool Equals(object obj) + { + if (!(obj is SafeGCHandle)) + return false; + + SafeGCHandle other = (SafeGCHandle)obj; + return this.Equals(other); + } + + /// Checks if the provided handle equals this one. This means both have the same ID. + /// Two different IDs can point to the same instance, but they will still return false in this + /// check, as each one of them need to be Free()d independently. + /// + /// @return True if the IDs of both handles match, false otherwise. + public bool Equals(SafeGCHandle other) + { + return _id == other._id; + } + } +} diff --git a/Assets/ARDK/Utilities/SafeGCHandle.cs.meta b/Assets/ARDK/Utilities/SafeGCHandle.cs.meta new file mode 100644 index 0000000..bf23aca --- /dev/null +++ b/Assets/ARDK/Utilities/SafeGCHandle.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4e7395864e7e8407bb55bb2f1257839d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/TaskUtility.cs b/Assets/ARDK/Utilities/TaskUtility.cs new file mode 100644 index 0000000..26b7c7a --- /dev/null +++ b/Assets/ARDK/Utilities/TaskUtility.cs @@ -0,0 +1,35 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; +using System.Threading.Tasks; + +using UnityEngine; + +namespace Niantic.ARDK.Utilities +{ + public static class TaskUtility + { + /// Waits while the function is true + /// @param condition The function to check + /// @param delay The number of milliseconds between each condition check + public static async Task WaitWhile(Func condition, int delay = 1) + { + delay = Mathf.Max(1, delay); + while (condition()) + { + await Task.Delay(delay); + } + } + + /// Waits until the function is true + /// @param condition The function to wait on + /// @param delay The number of milliseconds between each condition check + public static async Task WaitUntil(Func condition, int delay = 1) + { + delay = Mathf.Max(1, delay); + while (!condition()) + { + await Task.Delay(delay); + } + } + } +} diff --git a/Assets/ARDK/Utilities/TaskUtility.cs.meta b/Assets/ARDK/Utilities/TaskUtility.cs.meta new file mode 100644 index 0000000..fdc7c83 --- /dev/null +++ b/Assets/ARDK/Utilities/TaskUtility.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c2da180a8f69a45b99d3b310b0e564cd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/TypedId.meta b/Assets/ARDK/Utilities/TypedId.meta new file mode 100644 index 0000000..c4a0d2b --- /dev/null +++ b/Assets/ARDK/Utilities/TypedId.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 1c54ead907af4a1b8b203543246da05c +timeCreated: 1584469966 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/TypedId/IRepresentedBy.cs b/Assets/ARDK/Utilities/TypedId/IRepresentedBy.cs new file mode 100644 index 0000000..b1d007b --- /dev/null +++ b/Assets/ARDK/Utilities/TypedId/IRepresentedBy.cs @@ -0,0 +1,17 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +namespace Niantic.ARDK.Utilities.TypedId { + /// + /// Generic interface to mark a class as representable by an identifier of type TId. + /// @note This interface is deliberately left empty (does not provide an accessor for TId) as + /// the identifier for implementing classes should be of type TypedId. + /// + /// Type of identifier that can be used to represent this class + public interface IRepresentedBy + where + TId: IEquatable + { + } +} \ No newline at end of file diff --git a/Assets/ARDK/Utilities/TypedId/IRepresentedBy.cs.meta b/Assets/ARDK/Utilities/TypedId/IRepresentedBy.cs.meta new file mode 100644 index 0000000..ecefc48 --- /dev/null +++ b/Assets/ARDK/Utilities/TypedId/IRepresentedBy.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5bdec2c83dbf4a3fa142565cbb6f68c4 +timeCreated: 1584557283 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/TypedId/TypedId.cs b/Assets/ARDK/Utilities/TypedId/TypedId.cs new file mode 100644 index 0000000..e9854f7 --- /dev/null +++ b/Assets/ARDK/Utilities/TypedId/TypedId.cs @@ -0,0 +1,110 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +namespace Niantic.ARDK.Utilities.TypedId +{ + /// + /// A generic identifier that takes into account the type of object that it is representing. For + /// example, a TypedId&#60;uint, ClassA&#62; with a value of 0 would not equal a + /// TypedId&#60;uint, ClassB&#62 with a value of 0. + /// + /// Type of the object being represented + /// Type of the identifier + public struct TypedId: + IEquatable>, + IEquatable + where + TRepresented: IRepresentedBy + where + TId: IEquatable + { + /// + /// The raw (untyped) identifier held by this TypedId + /// + public TId RawIdentifier { get; private set; } + + /// + /// Generate a new TypedId with a raw identifier + /// + /// Value to give this TypedId + public TypedId(TId rawIdentifier) + : this() + { + RawIdentifier = rawIdentifier; + } + + /// + /// Check if an object is a TypedId, and if it is equivalent to this TypedId + /// + public override bool Equals(object other) + { + return other is TypedId && Equals((TypedId) other); + } + + /// + /// Check if another TypedId is equivalent to this TypedId + /// + public bool Equals(TypedId other) + { + if (RawIdentifier == null) + return other.RawIdentifier == null; + + return RawIdentifier.Equals(other.RawIdentifier); + } + + /// + /// Check if this TypedId is equivalent to a raw identifier + /// + /// + /// + public bool Equals(TId other) + { + if (RawIdentifier == null) + return other == null; + + return RawIdentifier.Equals(other); + } + + /// + /// Get the hashcode of this TypedId + /// + public override int GetHashCode() + { + if (RawIdentifier == null) + return -1; + + return RawIdentifier.GetHashCode(); + } + + public static bool operator == (TypedId lhs, TypedId rhs) + { + return lhs.Equals(rhs); + } + + public static bool operator != (TypedId lhs, TypedId rhs) + { + return !(lhs == rhs); + } + + public static bool operator == (TypedId lhs, TId rhs) + { + return lhs.Equals(rhs); + } + + public static bool operator != (TypedId lhs, TId rhs) + { + return !(lhs == rhs); + } + + public static bool operator == (TId lhs, TypedId rhs) + { + return rhs.Equals(lhs); + } + + public static bool operator != (TId lhs, TypedId rhs) + { + return !(lhs == rhs); + } + } +} diff --git a/Assets/ARDK/Utilities/TypedId/TypedId.cs.meta b/Assets/ARDK/Utilities/TypedId/TypedId.cs.meta new file mode 100644 index 0000000..2b7a80a --- /dev/null +++ b/Assets/ARDK/Utilities/TypedId/TypedId.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ad04968701d847caba05bc0156bc2f43 +timeCreated: 1584560428 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/VersionUtilities.meta b/Assets/ARDK/Utilities/VersionUtilities.meta new file mode 100644 index 0000000..c8de546 --- /dev/null +++ b/Assets/ARDK/Utilities/VersionUtilities.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2cbdbff8d762b4821a74544170ab67a0 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/VersionUtilities/ARDKGlobalVersion.cs b/Assets/ARDK/Utilities/VersionUtilities/ARDKGlobalVersion.cs new file mode 100644 index 0000000..e0b6d95 --- /dev/null +++ b/Assets/ARDK/Utilities/VersionUtilities/ARDKGlobalVersion.cs @@ -0,0 +1,38 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.Utilities.VersionUtilities +{ + public static class ARDKGlobalVersion + { + private static _IARDKVersion _impl; + + private static _IARDKVersion _Impl + { + get + { + if (_impl == null) + { + _impl = new _NativeARDKVersion(); + } + + return _impl; + } + } + + /// @returns + /// The ARDK version number. + public static string GetARDKVersion() + { + return _Impl.GetARDKVersion(); + } + + /// @returns + /// The name of the ARdk BackEnd (ARBE) server, if a networking session + /// is currently successfully connected to one that has made that information + /// available. + public static string GetARBEVersion() + { + return _Impl.GetARBEVersion(); + } + } +} diff --git a/Assets/ARDK/Utilities/VersionUtilities/ARDKGlobalVersion.cs.meta b/Assets/ARDK/Utilities/VersionUtilities/ARDKGlobalVersion.cs.meta new file mode 100644 index 0000000..3f14400 --- /dev/null +++ b/Assets/ARDK/Utilities/VersionUtilities/ARDKGlobalVersion.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3e63c9edf87d47c9a9f4266541ef86d7 +timeCreated: 1610759922 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/VersionUtilities/_IARDKVersion.cs b/Assets/ARDK/Utilities/VersionUtilities/_IARDKVersion.cs new file mode 100644 index 0000000..df85b62 --- /dev/null +++ b/Assets/ARDK/Utilities/VersionUtilities/_IARDKVersion.cs @@ -0,0 +1,10 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.Utilities.VersionUtilities +{ + internal interface _IARDKVersion + { + string GetARDKVersion(); + string GetARBEVersion(); + } +} diff --git a/Assets/ARDK/Utilities/VersionUtilities/_IARDKVersion.cs.meta b/Assets/ARDK/Utilities/VersionUtilities/_IARDKVersion.cs.meta new file mode 100644 index 0000000..c82d5ff --- /dev/null +++ b/Assets/ARDK/Utilities/VersionUtilities/_IARDKVersion.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: df8adcd4b19a54ed8ba0f8f4b4357646 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/VersionUtilities/_NativeARDKVersion.cs b/Assets/ARDK/Utilities/VersionUtilities/_NativeARDKVersion.cs new file mode 100644 index 0000000..f5925ff --- /dev/null +++ b/Assets/ARDK/Utilities/VersionUtilities/_NativeARDKVersion.cs @@ -0,0 +1,78 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Runtime.InteropServices; + +using Niantic.ARDK.AR; +using Niantic.ARDK.Utilities; + +using UnityEngine; + +using Niantic.ARDK.Internals; +using Niantic.ARDK.Networking; +using Niantic.ARDK.Networking.MultipeerNetworkingEventArgs; +using Niantic.ARDK.Utilities.Logging; + +namespace Niantic.ARDK.Utilities.VersionUtilities +{ + internal sealed class _NativeARDKVersion: + _IARDKVersion + { + private bool _networkingConnected; + private bool _isNativeNetworking; + + public _NativeARDKVersion() + { + MultipeerNetworkingFactory.NetworkingInitialized += OnNetworkingInitialized; + _CallbackQueue.ApplicationWillQuit += OnApplicationQuit; + } + + private void OnApplicationQuit() + { + _networkingConnected = false; + MultipeerNetworkingFactory.NetworkingInitialized -= OnNetworkingInitialized; + } + + private void OnNetworkingInitialized(AnyMultipeerNetworkingInitializedArgs args) + { + args.Networking.Connected += _ => + { + _networkingConnected = true; + _isNativeNetworking = args.Networking is _NativeMultipeerNetworking; + }; + args.Networking.Disconnected += _ => _networkingConnected = false; + } + + public string GetARDKVersion() + { + var ptr = _NAR_VersionInfo_GetARDKVersion(); + return ptr != IntPtr.Zero ? Marshal.PtrToStringAnsi(ptr) : null; + } + + public string GetARBEVersion() + { + string version = null; + + if (_networkingConnected) + { + if (_isNativeNetworking) + { + var ptr = _NAR_VersionInfo_GetARBEVersion(); + version = ptr != IntPtr.Zero ? Marshal.PtrToStringAnsi(ptr) : null; + } + else + { + version = "Editor"; + } + } + + return string.IsNullOrEmpty(version) ? "Unavailable" : version; + } + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NAR_VersionInfo_GetARDKVersion(); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern IntPtr _NAR_VersionInfo_GetARBEVersion(); + } +} diff --git a/Assets/ARDK/Utilities/VersionUtilities/_NativeARDKVersion.cs.meta b/Assets/ARDK/Utilities/VersionUtilities/_NativeARDKVersion.cs.meta new file mode 100644 index 0000000..c7aa450 --- /dev/null +++ b/Assets/ARDK/Utilities/VersionUtilities/_NativeARDKVersion.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: acb8096252254767a3587613d99143d0 +timeCreated: 1610758310 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/_ByteArrayComparer.cs b/Assets/ARDK/Utilities/_ByteArrayComparer.cs new file mode 100644 index 0000000..8a5db27 --- /dev/null +++ b/Assets/ARDK/Utilities/_ByteArrayComparer.cs @@ -0,0 +1,82 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Niantic.ARDK.Utilities +{ + // Byte arrays don't provide a valid hash code according to its data, so if we want to use them + // as keys in dictionaries (or just store them in HashSets) we need to provide a comparer that + // provides a consistent hashcode based on the bytes, allowing 2 different byte arrays that are + // equal in contents to be seen as equals and having the same hashcode. + // Notice that changing the contents of the array will change the hashcode, so do not do that + // after adding the array as a key in a dictionary or hashset, as this will make the item "lost" + // because of the different hash used to store it. + internal sealed class _ByteArrayComparer: + IEqualityComparer + { + public static readonly _ByteArrayComparer Instance = new _ByteArrayComparer(); + + private _ByteArrayComparer() + { + } + + // Gets a hash-code by "XORing" all the Int32 values in the array (the code actually uses UInt64 + // blocks for performance, and at the end XORs the first 32 bits with the last 32 bits). + // As that simple XORing could always generate the exact same hashcode for any empty memory + // block of any length, the starting XORing value is actually the Length of the array itself. + // If the array has a length that is not multiple of a "block" the final bytes are xored byte + // by byte, but endianness is ignored. That means that a big-endian processor and a + // little-endian processor will generate different values, yet the generation is consistent in + // the same process (so, it is OK to use as dictionary hasher, but not OK to save in a file). + public int GetHashCode(byte[] array) + { + if (array == null) + return 0; + + unchecked + { + int length = array.Length; + UInt64 result = (UInt64)length; + int countBlocks = length / 8; + unsafe + { + fixed (byte* untypedPointer = array) + { + UInt64* blockPointer = (UInt64*)untypedPointer; + for (int i = 0; i < countBlocks; i++) + result ^= blockPointer[i]; + + int indexAtLastBlock = countBlocks * 8; + for (int i = indexAtLastBlock; i < length; i++) + { + UInt64 valueAtIndex = untypedPointer[i]; + int bitShiftAmount = (i % 8) * 8; + result ^= valueAtIndex << bitShiftAmount; + } + } + } + + return (int)(result ^ (result >> 32)); + } + } + public bool Equals(byte[] x, byte[] y) + { + // If both are the same instance, no need to check anything else. + if (x == y) + return true; + + // As the instances are different, if one of them is null, they are just different. + // No need to check further, also we can't access Length on null. + if (x == null || y == null) + return false; + + // When length is different, they are clearly not the same. + if (x.Length != y.Length) + return false; + + return x.SequenceEqual(y); + } + } +} diff --git a/Assets/ARDK/Utilities/_ByteArrayComparer.cs.meta b/Assets/ARDK/Utilities/_ByteArrayComparer.cs.meta new file mode 100644 index 0000000..a92a9d5 --- /dev/null +++ b/Assets/ARDK/Utilities/_ByteArrayComparer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6242c50d90596493180d9f40e23a45f0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/_CallbackQueue.cs b/Assets/ARDK/Utilities/_CallbackQueue.cs new file mode 100644 index 0000000..d8873f4 --- /dev/null +++ b/Assets/ARDK/Utilities/_CallbackQueue.cs @@ -0,0 +1,170 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; + +using Niantic.ARDK.Utilities.Logging; +#if UNITY_EDITOR +using UnityEditor; +#endif +using UnityEngine; + +namespace Niantic.ARDK.Utilities +{ + /// A helper class to ensure callbacks from native code get run on Unity's main thread. + /// @note You *do not* need to interact directly with this class, it will manually inject an + /// invisible, immortal game object to flush callbacks by itself. + internal sealed class _CallbackQueue: + MonoBehaviour + { + /// The _callbackQueue is a buffer for callback-handlers coming-in from ARDK. + /// We need this because our callbacks occur in a different thread/update cycle than Unity's + /// main thread. + private static readonly Queue _callbackQueue = new Queue(); + + /// + /// Internal flag for application shutting down. + /// + internal static bool _isApplicationQuitting; + +#if UNITY_EDITOR + /// Run so that the EditorRemoteConnector can start up a networking session while the Editor is + /// in edit mode. + /// TODO: refactor to be confined to EditorRemoteConnector + [InitializeOnLoadMethod] + private static void _OnEditorLoad() + { + EditorApplication.update += ConsumeQueue; + EditorApplication.quitting += OnEditorQuit; + } +#endif + + /// Called when Unity is first initializing right after a game starts, before a scene loads. + /// We create a game object that is invisible and won't be destroyed by switching scenes. This + /// becomes our link into Unity's main run loop where we can flush our callbacks ;) + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + private static void OnLoad() + { + var sneakySnake = new GameObject(); + sneakySnake.hideFlags = HideFlags.HideAndDontSave | HideFlags.HideInInspector; + + DontDestroyOnLoad(sneakySnake); + sneakySnake.AddComponent<_CallbackQueue>(); + } + + public static void ConsumeQueue() + { + Action[] actions; + + var exceptionOccurred = false; + lock (_callbackQueue) + { + actions = _callbackQueue.ToArray(); + _callbackQueue.Clear(); + } + + foreach (var action in actions) + { + try + { + action(); + } + catch (Exception e) + { + exceptionOccurred = true; + ARLog._Exception(e); + } + } + + if (exceptionOccurred) + { + var message = + "An exception occurred in a method subscribed to an ARDK event, check the device logs " + + "for more information"; + + throw new Exception(message); + } + } + + /// Queue a new callback to be called on Unity's main thread. + /// @param callback The callback to be called on Unity's main thread. + public static void QueueCallback(Action callback) + { + if (callback == null) + return; + + lock (_callbackQueue) + _callbackQueue.Enqueue(callback); + } + + internal static event Action ApplicationWillQuit; + internal static event Action ApplicationGainedFocus; + internal static event Action ApplicationLostFocus; + internal static event Action ApplicationPaused; + internal static event Action ApplicationUnpaused; + + /// In this Update method, we call all of the relevant callback functions subscribed to the + /// ARSession. Meaning that if any of those callback functions are very heavy, they will slow + /// down your app's performance and may have frame drops. Unfortunately, Unity doesn't have + /// great insight into the callbacks this method calls, so you may have to manually inspect + /// each function subscribed to an event. + private void Update() + { + ConsumeQueue(); + } + + // On Android, when the on-screen keyboard is enabled, it causes an OnApplicationFocus( false ) + // event. Additionally, if you press Home at the moment the keyboard is enabled, the + // OnApplicationFocus() event is not called, but OnApplicationPause() is called instead. + private void OnApplicationFocus(bool hasFocus) + { + if (hasFocus) + ApplicationGainedFocus?.Invoke(); + else + ApplicationLostFocus?.Invoke(); + } + + + private void OnApplicationPause(bool pauseStatus) + { + if (pauseStatus) + ApplicationPaused?.Invoke(); + else + ApplicationUnpaused?.Invoke(); + } + + private void OnApplicationQuit() + { + if (_isApplicationQuitting) + { + // Prevents the multiple invokations of this method that are happening for some reason + return; + } + + _isApplicationQuitting = true; + + var handler = ApplicationWillQuit; + handler?.Invoke(); + } + + private static void OnEditorQuit() + { + if (_isApplicationQuitting) + { + // Prevents the multiple invokations of this method that are happening for some reason + return; + } + + _isApplicationQuitting = true; + + var handler = ApplicationWillQuit; + handler?.Invoke(); + } + + private void OnDestroy() + { + if (!_isApplicationQuitting) + ARLog._Error("Callback Queue Destroyed. This should not happen."); + } + } +} diff --git a/Assets/ARDK/Utilities/_CallbackQueue.cs.meta b/Assets/ARDK/Utilities/_CallbackQueue.cs.meta new file mode 100644 index 0000000..cec14a7 --- /dev/null +++ b/Assets/ARDK/Utilities/_CallbackQueue.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 167f756e8862b4f73a85d4ff61a1382b +timeCreated: 1527614768 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/_CatchUpEvent.cs b/Assets/ARDK/Utilities/_CatchUpEvent.cs new file mode 100644 index 0000000..f88f590 --- /dev/null +++ b/Assets/ARDK/Utilities/_CatchUpEvent.cs @@ -0,0 +1,87 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; + +namespace Niantic.ARDK.Utilities +{ + // This is a helper class for events that should trigger even when the user registers to it + // after it was originally fired. + // This particular implementation will store the EventArgs used, and can be fired multiple times. + // If the event is fired multiple times, a new event handler that gets registered will be fired + // for all the values that this event was fired with. + internal sealed class _CatchUpEvent: + IDisposable + where + T: struct, IArdkEventArgs + { + private readonly object _lock = new object(); + private List _values; + private ArdkEventHandler _handler; + private bool _isDisposed; + + public void Dispose() + { + lock (_lock) + { + _handler = null; + _isDisposed = true; + } + } + + public void Register(ArdkEventHandler handler) + { + if (handler == null) + return; + + lock (_lock) + { + if (_isDisposed) + return; + + // This is done inside the lock as we don't want to "register" to the handler if + // concurrently we are being invoked as that could cause double-invokes. + _handler += handler; + + var values = _values; + if (values != null) + foreach (var value in values) + handler(value); + } + } + + public void Unregister(ArdkEventHandler handler) + { + // There is no need to lock to remove an event handler, as that is thread safe already. + _handler -= handler; + } + + public void InvokeUsingCallbackQueue(T value) + { + ArdkEventHandler handler; + lock (_lock) + { + if (_isDisposed) + return; + + if (_values == null) + _values = new List(); + + _values.Add(value); + handler = _handler; + } + + _CallbackQueue.QueueCallback + ( + () => + { + if (_isDisposed) + return; + + if (handler != null) + handler(value); + } + ); + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/Utilities/_CatchUpEvent.cs.meta b/Assets/ARDK/Utilities/_CatchUpEvent.cs.meta new file mode 100644 index 0000000..27d66d5 --- /dev/null +++ b/Assets/ARDK/Utilities/_CatchUpEvent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 85daa180aae754aabac72a81b87e1a28 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/_FriendTypeAsserter.cs b/Assets/ARDK/Utilities/_FriendTypeAsserter.cs new file mode 100644 index 0000000..c6b8086 --- /dev/null +++ b/Assets/ARDK/Utilities/_FriendTypeAsserter.cs @@ -0,0 +1,48 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Diagnostics; + +namespace Niantic.ARDK.Utilities +{ + // In .NET we don't have a "friend class" modifier or similar. + // The best we can do, by default, is to use internal. Yet, internal is still "too open". + // Sometimes we create a Factory and we want every call to pass through the factory (as it has + // additional steps after the constructor runs). Yet, a test, or any other class in the project + // can just "run" any internal code without passing through the factory. + // Well, this class tries to solve this problem by allowing us to validate who is the caller to + // our method. For performance considerations, this code only runs in MUST_VALIDATE_STATIC_MEMBERS + // builds, though and, unfortunately, will not capture bad calls at compile-time, just at + // run-time. + internal static class _FriendTypeAsserter + { + [Conditional("MUST_VALIDATE_STATIC_MEMBERS")] + public static void AssertCallerIs(Type type) + { + if (type == null) + throw new ArgumentNullException(nameof(type)); + + // 0 = this method. + // 1 = the method that wants to validate its caller. + var callerFrame = new StackFrame(1); + + var callerMethod = callerFrame.GetMethod(); + + bool isCallerSomehowInternal = + callerMethod.IsAssembly || + callerMethod.IsFamilyAndAssembly || + callerMethod.IsFamilyOrAssembly; + + if (!isCallerSomehowInternal) + throw new InvalidOperationException("Friend Type asserts are for internal methods only."); + + // 2 = the method to be validated. + var frameToValidate = new StackFrame(2); + + var methodToValidate = frameToValidate.GetMethod(); + if (methodToValidate.DeclaringType != type) + throw new InvalidOperationException("The declaring type is: " + methodToValidate.DeclaringType + + " but this method can only be invoked by: " + type.FullName); + } + } +} diff --git a/Assets/ARDK/Utilities/_FriendTypeAsserter.cs.meta b/Assets/ARDK/Utilities/_FriendTypeAsserter.cs.meta new file mode 100644 index 0000000..7b2e0f6 --- /dev/null +++ b/Assets/ARDK/Utilities/_FriendTypeAsserter.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 689dc334e0f44abf8784ef9640f832bd +timeCreated: 1608750854 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/_GcObserver.cs b/Assets/ARDK/Utilities/_GcObserver.cs new file mode 100644 index 0000000..3772608 --- /dev/null +++ b/Assets/ARDK/Utilities/_GcObserver.cs @@ -0,0 +1,222 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Threading; + +namespace Niantic.ARDK.Utilities +{ + // Class to "observe" when a garbage collection happens. This is useful to allow code that + // uses collections of WeakReferences, so them we can release the now nullified ones. + internal static class _GcObserver + { + static _GcObserver() + { + var reviver = new _Reviver(); + + // This KeepAlive call actually does nothing. The object is free to die on the next line + // and that's actually what we want. This call is being done only to avoid a warning that + // a new object was never assigned or that the reviver variable was never used. + GC.KeepAlive(reviver); + } + + private sealed class _Reviver + { + // This needs to be static or else the DomainUnload event will keep this object alive. + // We use this flag to stop the _Reviver from reviving when the domain is unloading, or else + // we "dead-lock" as the domain cannot be unloaded untill all the objects are dead and, as the + // name says, the reviver keeps reviving. + private static volatile bool _isUnloading; + + private static readonly object _lock = new object(); + + internal _Reviver() + { + // When the domain is unloading, we should stop the _Reviver from reviving. Setting this + // flag to true does the job. + AppDomain.CurrentDomain.DomainUnload += (a, b) => _isUnloading = true; + + var thread = new Thread(_GcHappenedCaller); + thread.Name = "GC Observer"; + thread.Start(); + } + + ~_Reviver() + { + // We only revive in normal garbage collections. When the domain is unloading we cannot + // reviver, or els we won't allow the app to finish. + if (_isUnloading) + return; + + GC.ReRegisterForFinalize(this); + _FireCleanup(); + } + + private void _FireCleanup() + { + bool lockTaken = false; + try + { + // We cannot use a normal lock, as all other threads are stopped during a GC. + // So, we try to get the lock. If we can't, we just skip it. This also avoids any issues + // in a situation where we have 2 GCs happening in a very short time but our event + // handlers still didn't finish doing their work. + Monitor.TryEnter(_lock, ref lockTaken); + + if (lockTaken) + Monitor.Pulse(_lock); + } + finally + { + if (lockTaken) + Monitor.Exit(_lock); + } + } + + // This method needs to be static or else the thread would keep this object alive. + private static void _GcHappenedCaller(object ignoredArgument) + { + var currentThread = Thread.CurrentThread; + + lock (_lock) + { + while (!_isUnloading) + { + currentThread.IsBackground = true; + Monitor.Wait(_lock); + + lock (_gcHappened) + { + int count = _gcHappened.Count; + if (count > 0) + { + currentThread.IsBackground = false; + + for (int i=count-1; i>=0; i--) + { + var weakAction = _gcHappened[i]; + + if (!weakAction._TryInvoke()) + _gcHappened.RemoveAt(i); + } + } + } + } + } + } + } + + // A normal Action holds a Target and the MethodInfo to be invoked, but doesn't allow the Target + // to be collected. The WeakAction also holds a Target and a MethodInfo to be invoked, but it + // allows the Target to be collected. + private struct _WeakAction + { + internal readonly WeakReference _targetReference; + internal readonly MethodInfo _method; + + internal _WeakAction(Action action) + { + // target can be null when the method is static. + var target = action.Target; + + if (target != null) + _targetReference = new WeakReference(target); + else + _targetReference = null; + + _method = action.Method; + } + + internal bool _TryInvoke() + { + if (_targetReference == null) + { + // If the method is static, we invoke it without issues. + _method.Invoke(null, null); + return true; + } + + var target = _targetReference.Target; + if (target == null) + return false; + + _method.Invoke(target, null); + return true; + } + } + + private static readonly List<_WeakAction> _gcHappened = new List<_WeakAction>(); + + private static int _testOnly_initialCount; + + // These two are for testing purposes only. + internal static int _TestOnly_GcHappenedHandlerCount + { + get + { + lock (_gcHappened) + return _gcHappened.Count - _testOnly_initialCount; + } + } + internal static void _TestOnly_SetupGcHappenedHandlerCount() + { + for (int i=0; i<2; i++) + { + GC.Collect(); + GC.WaitForPendingFinalizers(); + + Thread.Sleep(100); + } + + lock (_gcHappened) + _testOnly_initialCount = _gcHappened.Count; + } + + // As this event is internal, we can use Action as its type. + // This implemenation is so odd because we keep all the handlers as "weak handlers". If they + // need to be kept alive, they need to be either static, or part of an object that's going + // to stay around. + internal static event Action _GcHappened + { + add + { + if (value == null) + return; + + var weakAction = new _WeakAction(value); + lock (_gcHappened) + _gcHappened.Add(weakAction); + } + remove + { + if (value == null) + return; + + for (int i=_gcHappened.Count-1; i>=0; i--) + { + var weakAction = _gcHappened[i]; + + if (value.Method != weakAction._method) + continue; + + var targetReference = weakAction._targetReference; + if (targetReference == null) + { + _gcHappened.RemoveAt(i); + + // The real C# events allow double registration, so we also assume that the same event + // might be registered more than once and are unregistering only one. + return; + } + + if (targetReference.Target == value.Target) + { + _gcHappened.RemoveAt(i); + return; + } + } + } + } + } +} diff --git a/Assets/ARDK/Utilities/_GcObserver.cs.meta b/Assets/ARDK/Utilities/_GcObserver.cs.meta new file mode 100644 index 0000000..dd5f0c6 --- /dev/null +++ b/Assets/ARDK/Utilities/_GcObserver.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bd6645fa63cdc4579889f58d07edf75d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/_HttpClient.cs b/Assets/ARDK/Utilities/_HttpClient.cs new file mode 100644 index 0000000..7504376 --- /dev/null +++ b/Assets/ARDK/Utilities/_HttpClient.cs @@ -0,0 +1,132 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Text; +using System.Threading.Tasks; + +using Niantic.ARDK.Utilities.Logging; +using Niantic.ARDK.VPSCoverage; +using Niantic.ARDK.VPSCoverage.GeoserviceMessages; + +using UnityEngine; +using UnityEngine.Networking; + +namespace Niantic.ARDK.Utilities +{ + internal static class _HttpClient + { + // This method only works with [Serializable] TRequest and TResponse + internal static async Task<_HttpResponse> SendPostAsync + ( + string uri, + TRequest request, + Dictionary headers = null + ) + where TRequest: class + where TResponse: class + { + if (!typeof(TRequest).IsSerializable) + { + throw new ArgumentException(typeof(TRequest) + " is not serializable."); + } + + string jsonRequest = JsonUtility.ToJson(request); + + using (UnityWebRequest webRequest = new UnityWebRequest(uri, "POST")) + { + byte[] data = Encoding.UTF8.GetBytes(jsonRequest); + webRequest.uploadHandler = new UploadHandlerRaw(data); + webRequest.uploadHandler.contentType = "application/json"; + webRequest.downloadHandler = new DownloadHandlerBuffer(); + if (headers != null) + foreach (var header in headers) + webRequest.SetRequestHeader(header.Key, header.Value); + + await webRequest.SendWebRequest(); + + TResponse response; + + if (webRequest.result == UnityWebRequest.Result.Success) + response = JsonUtility.FromJson(webRequest.downloadHandler.text); + else + response = default; + + return new _HttpResponse + (_ResponseStatusTranslator.FromHttpStatus(webRequest.result, webRequest.responseCode), response); + } + } + + internal static async Task DownloadImageAsync(string imageUrl) + { + UnityWebRequest webRequest = UnityWebRequestTexture.GetTexture(imageUrl); + webRequest.downloadHandler = new DownloadHandlerTexture(); + await webRequest.SendWebRequest(); + + if (webRequest.result != UnityWebRequest.Result.Success) + { + ARLog._Error("Image download failed: " + webRequest.error + "\nURL: " + imageUrl); + return null; + } + + return ((DownloadHandlerTexture)webRequest.downloadHandler).texture; + } + } + + internal class _HttpResponse + { + public ResponseStatus Status { get; set; } + public TResponse Data { get; } + + public _HttpResponse(ResponseStatus status, TResponse data) + { + Status = status; + Data = data; + } + } + + #region Custom Awaiter for SendWebRequest() + public class UnityWebRequestAwaiter: INotifyCompletion + { + private UnityWebRequestAsyncOperation asyncOp; + private Action continuation; + + public UnityWebRequestAwaiter(UnityWebRequestAsyncOperation asyncOp) + { + this.asyncOp = asyncOp; + asyncOp.completed += OnRequestCompleted; + } + + public bool IsCompleted + { + get + { + return asyncOp.isDone; + } + } + + public void GetResult() + { + } + + public void OnCompleted(Action continuation) + { + this.continuation = continuation; + } + + private void OnRequestCompleted(AsyncOperation obj) + { + continuation(); + } + } + + public static class ExtensionMethods + { + public static UnityWebRequestAwaiter GetAwaiter(this UnityWebRequestAsyncOperation asyncOp) + { + return new UnityWebRequestAwaiter(asyncOp); + } + } + #endregion +} diff --git a/Assets/ARDK/Utilities/_HttpClient.cs.meta b/Assets/ARDK/Utilities/_HttpClient.cs.meta new file mode 100644 index 0000000..dd6ac69 --- /dev/null +++ b/Assets/ARDK/Utilities/_HttpClient.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a65704fc42e6f43e590412e4ee14884e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/_KeyValuePair.cs b/Assets/ARDK/Utilities/_KeyValuePair.cs new file mode 100644 index 0000000..0166427 --- /dev/null +++ b/Assets/ARDK/Utilities/_KeyValuePair.cs @@ -0,0 +1,17 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.Collections.Generic; + +namespace Niantic.ARDK.Utilities +{ + /// Helper class to create KeyValuePairs using type-inference. + /// Instead of new KeyValuePair<type1, type2>(value1, value2) just do: + /// _KeyValuePair.Create(value1, value2); + internal static class _KeyValuePair + { + public static KeyValuePair Create(TKey key, TValue value) + { + return new KeyValuePair(key, value); + } + } +} diff --git a/Assets/ARDK/Utilities/_KeyValuePair.cs.meta b/Assets/ARDK/Utilities/_KeyValuePair.cs.meta new file mode 100644 index 0000000..bdf33c7 --- /dev/null +++ b/Assets/ARDK/Utilities/_KeyValuePair.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c7ff37f14829f4662a8c4d1ad279db05 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/_Memory.cs b/Assets/ARDK/Utilities/_Memory.cs new file mode 100644 index 0000000..d94efef --- /dev/null +++ b/Assets/ARDK/Utilities/_Memory.cs @@ -0,0 +1,41 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +#if UNITY_STANDALONE_OSX || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_WIN +#define UNITY_STANDALONE_DESKTOP +#endif +#if (UNITY_IOS || UNITY_ANDROID || UNITY_STANDALONE_DESKTOP) && !UNITY_EDITOR +#define AR_NATIVE_SUPPORT +#endif + +using System; +using System.Runtime.InteropServices; +using Niantic.ARDK.Internals; + +namespace Niantic.ARDK.Utilities +{ + internal static class _Memory + { + /// Free the specified buffer. + public static void Free(IntPtr buffer) + { +#if AR_NATIVE_SUPPORT + _NARMemory_Free(buffer); +#endif + } + + // TODO: this is really specialized...make generic + /// Copies the source into the destination using the size specified in bytes. + public static void Copy(IntPtr source, UInt64[] destination, UInt64 size) + { +#if AR_NATIVE_SUPPORT + _NARMemory_Copy(source, destination, size); +#endif + } + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARMemory_Free(IntPtr buffer); + + [DllImport(_ARDKLibrary.libraryName)] + private static extern void _NARMemory_Copy(IntPtr source, UInt64[] destination, UInt64 size); + } +} diff --git a/Assets/ARDK/Utilities/_Memory.cs.meta b/Assets/ARDK/Utilities/_Memory.cs.meta new file mode 100644 index 0000000..d7a6f37 --- /dev/null +++ b/Assets/ARDK/Utilities/_Memory.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 7b20bb9c5c9024763abc5813c07ad0b9 +timeCreated: 1528482914 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/_ReferenceComparer.cs b/Assets/ARDK/Utilities/_ReferenceComparer.cs new file mode 100644 index 0000000..8541889 --- /dev/null +++ b/Assets/ARDK/Utilities/_ReferenceComparer.cs @@ -0,0 +1,45 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace Niantic.ARDK.Utilities +{ + /// + /// This comparer class will just compare objects by their reference, not their content. + /// It is useful for hashsets when we just want to check if we already hold an instance, + /// or dictionaries when we want to "attach" properties to existing instances + /// but don't want to affect identical instances. + /// + internal sealed class _ReferenceComparer: + IEqualityComparer + where + T: class + { + /// + /// Gets the singleton instance of this class. + /// + public static readonly _ReferenceComparer Instance = new _ReferenceComparer(); + + private _ReferenceComparer() + { + } + + /// + /// Returns a boolean value telling whether a and b are actually the same instance. + /// + public bool Equals(T a, T b) + { + return object.ReferenceEquals(a, b); + } + + /// + /// Returns the immutable hash-code given to an instance when it is created. + /// Such a hash-code is not affected by the class overriding GetHashCode() method. + /// + public int GetHashCode(T instance) + { + return RuntimeHelpers.GetHashCode(instance); + } + } +} diff --git a/Assets/ARDK/Utilities/_ReferenceComparer.cs.meta b/Assets/ARDK/Utilities/_ReferenceComparer.cs.meta new file mode 100644 index 0000000..220c3d6 --- /dev/null +++ b/Assets/ARDK/Utilities/_ReferenceComparer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0fa61537a81a5442390c4e382e8d3678 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/Utilities/_StaticMemberValidator.cs b/Assets/ARDK/Utilities/_StaticMemberValidator.cs new file mode 100644 index 0000000..382d336 --- /dev/null +++ b/Assets/ARDK/Utilities/_StaticMemberValidator.cs @@ -0,0 +1,276 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq.Expressions; +using System.Reflection; + +namespace Niantic.ARDK.Utilities +{ + internal static class _StaticMemberValidator + { +#if MUST_VALIDATE_STATIC_MEMBERS + private static readonly ConcurrentDictionary _fieldsToValidate = + new ConcurrentDictionary(); + + // Each field in _collectionsToValidate is an IEnumerable that will be validated as being empty. + // If they are not empty they will be cleared. + private static readonly object _collectionsToValidateLock = new object(); + private static readonly HashSet _collectionsToValidate = new HashSet(); + + // Each field in _collectionArrayssToValidate is an Array of IEnumerables that will be validated + // as being composed of only empty IEnumerables. + private static readonly object _collectionArraysToValidateLock = new object(); + private static readonly HashSet _collectionArraysToValidate = new HashSet(); + + // Do not call this method directly. Use a _StaticMembersValidatorScope instead. + internal static void _ForScopeOnly_CheckCleanState() + { + _FriendTypeAsserter.AssertCallerIs(typeof(_StaticMembersValidatorScope)); + + try + { + // Compare each field to validate to its expected value, and if any are different throw. + foreach (var pair in _fieldsToValidate) + { + var field = pair.Key; + var expectedValue = pair.Value; + + var value = field.GetValue(null); + + if (!object.Equals(value, expectedValue)) + { + string message = + "Field '" + field.DeclaringType.FullName + "." + field.Name +"' contains garbage.\n" + + "Expected value: " + expectedValue + ".\n" + + "Actual value: " + value + "."; + + throw new InvalidOperationException(message); + } + } + + _fieldsToValidate.Clear(); + + // Check that each collection is empty, and if any contain values then throw. + lock (_collectionsToValidateLock) + { + foreach (var field in _collectionsToValidate) + { + var untypedValue = field.GetValue(null); + + if (untypedValue == null) + continue; + + var collection = (IEnumerable)untypedValue; + foreach (var value in collection) + { + string message = + "Collection '" + field.DeclaringType.FullName + "." + field.Name + "' is not empty."; + + throw new InvalidOperationException(message); + } + } + + _collectionsToValidate.Clear(); + } + + // Iterate through each array to validate, and if any collections from any arrays contain + // values then throw. + lock (_collectionArraysToValidateLock) + { + foreach (var field in _collectionArraysToValidate) + { + var untypedValue = field.GetValue(null); + + if (untypedValue == null) + continue; + + var array = (ICollection)untypedValue; + int index = 0; + foreach (var subcollection in array) + { + var collection = (IEnumerable)subcollection; + foreach (var value in collection) + { + string message = + "Collection '" + field.DeclaringType.FullName + "." + field.Name + "[" + index + + "]" + "' is not empty."; + + throw new InvalidOperationException(message); + } + + index++; + } + } + + _collectionArraysToValidate.Clear(); + } + } + catch + { + // If any test fails, we just nullify/restore all fields and clear all collections. + foreach(var pair in _fieldsToValidate) + { + var field = pair.Key; + var value = pair.Value; + + field.SetValue(null, value); + } + + _fieldsToValidate.Clear(); + + lock (_collectionsToValidateLock) + { + foreach (var fieldCollection in _collectionsToValidate) + { + var untypedCollection = fieldCollection.GetValue(null); + if (untypedCollection == null) + continue; + + var clearMethod = + untypedCollection.GetType() + .GetMethod + ( + "Clear", + BindingFlags.Public | BindingFlags.Instance, + null, + Type.EmptyTypes, + null + ); + + if (clearMethod != null) + clearMethod.Invoke(untypedCollection, null); + } + + _collectionsToValidate.Clear(); + } + + lock (_collectionArraysToValidateLock) + { + foreach(var fieldCollection in _collectionArraysToValidate) + { + var untypedArray = fieldCollection.GetValue(null); + if (untypedArray == null) + continue; + + var array = (ICollection)untypedArray; + foreach (var untypedCollection in array) + { + var clearMethod = + untypedCollection.GetType() + .GetMethod + ( + "Clear", + BindingFlags.Public | BindingFlags.Instance, + null, + Type.EmptyTypes, + null + ); + + if (clearMethod != null) + clearMethod.Invoke(untypedCollection, null); + } + } + + _collectionArraysToValidate.Clear(); + } + + throw; + } + } +#endif + + // Use only with static fields. + // Usage like: _StaticMemberValidator._FieldIsNullWhenScopeEnds(() => staticField); + [Conditional("MUST_VALIDATE_STATIC_MEMBERS")] + internal static void _FieldIsNullWhenScopeEnds(Expression> expression) + where T: class + { + _FieldContainsSpecificValueWhenScopeEnds(expression, null); + } + + // Use only with static fields. + // Usage like: + // _StaticMemberValidator._FieldContainsSpecificValueWhenScopeEnds(() => staticField, 123); + [Conditional("MUST_VALIDATE_STATIC_MEMBERS")] + internal static void _FieldContainsSpecificValueWhenScopeEnds + ( + Expression> expression, + T valueAtEnd + ) + { +#if MUST_VALIDATE_STATIC_MEMBERS + var memberExpression = (MemberExpression)expression.Body; + var field = (FieldInfo)memberExpression.Member; + + if (!field.IsStatic) + throw new InvalidOperationException("Given field is not static."); + + if (!_fieldsToValidate.TryAdd(field, valueAtEnd)) + { + object existingValue; + _fieldsToValidate.TryGetValue(field, out existingValue); + + if (!object.Equals(existingValue, valueAtEnd)) + { + string message = + "The field " + field.DeclaringType.FullName + "." + field.Name + + " already has a valueAtEnd expectation to be '" + existingValue + + "' but we are now trying to set a new expectation of '" + valueAtEnd + "'."; + + throw new InvalidOperationException(message); + } + } + + _StaticMembersValidatorScope._ForValidatorOnly_CheckScopeExists(); +#endif + } + + // Use only with static collection fields. + // Usage like: + // _StaticMemberValidator._CollectionIsEmptyWhenScopeEnds(() => staticCollectionField); + [Conditional("MUST_VALIDATE_STATIC_MEMBERS")] + internal static void _CollectionIsEmptyWhenScopeEnds(Expression> expression) + { +#if MUST_VALIDATE_STATIC_MEMBERS + var memberExpression = (MemberExpression)expression.Body; + var field = (FieldInfo)memberExpression.Member; + + if (!field.IsStatic) + throw new InvalidOperationException("Given field is not static."); + + lock (_collectionsToValidateLock) + if (!_collectionsToValidate.Contains(field)) + _collectionsToValidate.Add(field); + + _StaticMembersValidatorScope._ForValidatorOnly_CheckScopeExists(); +#endif + } + + // Use only with static fields that are arrays of collections. + // Usage like: + // _StaticMemberValidator._CollectionIsEmptyWhenScopeEnds(() => staticArrayOfCollectionsField); + // Where staticArrayOfCollectionField looks like: + // static ICollection[] staticArrayCollectionField; + [Conditional("MUST_VALIDATE_STATIC_MEMBERS")] + internal static void _CollectionsAreEmptyWhenScopeEnds(Expression> expression) + { +#if MUST_VALIDATE_STATIC_MEMBERS + var memberExpression = (MemberExpression)expression.Body; + var field = (FieldInfo)memberExpression.Member; + + if (!field.IsStatic) + throw new InvalidOperationException("Given field is not static."); + + lock (_collectionArraysToValidateLock) + if (!_collectionArraysToValidate.Contains(field)) + _collectionArraysToValidate.Add(field); + + _StaticMembersValidatorScope._ForValidatorOnly_CheckScopeExists(); +#endif + } + } +} diff --git a/Assets/ARDK/Utilities/_StaticMemberValidator.cs.meta b/Assets/ARDK/Utilities/_StaticMemberValidator.cs.meta new file mode 100644 index 0000000..041b506 --- /dev/null +++ b/Assets/ARDK/Utilities/_StaticMemberValidator.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 274aedeb3b9c4b0a8368f0decffa2d9c +timeCreated: 1608322577 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/_StaticMembersValidatorScope.cs b/Assets/ARDK/Utilities/_StaticMembersValidatorScope.cs new file mode 100644 index 0000000..d290268 --- /dev/null +++ b/Assets/ARDK/Utilities/_StaticMembersValidatorScope.cs @@ -0,0 +1,65 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.AR; +using Niantic.ARDK.VirtualStudio; +using Niantic.ARDK.VirtualStudio.Networking; +using Niantic.ARDK.Networking.HLAPI.Object.Unity; +using Niantic.ARDK.VirtualStudio.Remote; + +namespace Niantic.ARDK.Utilities +{ + internal sealed class _StaticMembersValidatorScope: + IDisposable + { +#if MUST_VALIDATE_STATIC_MEMBERS + private static _StaticMembersValidatorScope _currentInstance; + + internal static void _ForValidatorOnly_CheckScopeExists() + { + _FriendTypeAsserter.AssertCallerIs(typeof(_StaticMemberValidator)); + + if (_currentInstance == null) + throw new InvalidOperationException("To use the current static member on tests, you need a scope."); + } + + public _StaticMembersValidatorScope() + { + if (_currentInstance != null) + throw new InvalidOperationException("Another Validator Scope already exists."); + + _CheckCleanState(); + + _currentInstance = this; + } + + public void Dispose() + { + if (_currentInstance != this) + throw new InvalidOperationException("We are not the current scope. Double dispose?"); + + _currentInstance = null; + NetworkSpawner._Deinitialize(); + + _VirtualStudioManager._ResetInstance(); + _RemoteConnection.Deinitialize(); + + _CheckCleanState(); + } + + private static void _CheckCleanState() + { + _MockNetworkingSessionsMediator._CheckActiveCountIsZero(); + _StaticMemberValidator._ForScopeOnly_CheckCleanState(); + } +#else + public void Dispose() + { + } + +#endif + } +} + + diff --git a/Assets/ARDK/Utilities/_StaticMembersValidatorScope.cs.meta b/Assets/ARDK/Utilities/_StaticMembersValidatorScope.cs.meta new file mode 100644 index 0000000..feee723 --- /dev/null +++ b/Assets/ARDK/Utilities/_StaticMembersValidatorScope.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: bbff85f738c74eda9c4593964b155bb7 +timeCreated: 1608242437 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/_ThreadCheckedObject.cs b/Assets/ARDK/Utilities/_ThreadCheckedObject.cs new file mode 100644 index 0000000..0652fc3 --- /dev/null +++ b/Assets/ARDK/Utilities/_ThreadCheckedObject.cs @@ -0,0 +1,42 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Diagnostics; + +namespace Niantic.ARDK.Utilities +{ + internal class _ThreadCheckedObject + { + [ThreadStatic] + private static object _staticCurrentThreadToken; + + private static object _GetOrCreateCurrentThreadToken() + { + var result = _staticCurrentThreadToken; + + if (result == null) + { + result = new object(); + _staticCurrentThreadToken = result; + } + + return result; + } + + private readonly object _creatorThreadToken; + + internal _ThreadCheckedObject() + { + _creatorThreadToken = _GetOrCreateCurrentThreadToken(); + } + + [Conditional("DEBUG")] + internal void _CheckThread() + { + // We don't use _GetOrCreateCurrentThreadToken as we don't want to create a token for + // this thread if we don't need to. + if (_creatorThreadToken != _staticCurrentThreadToken) + throw new InvalidOperationException("This action can only be done by the creator thread."); + } + } +} diff --git a/Assets/ARDK/Utilities/_ThreadCheckedObject.cs.meta b/Assets/ARDK/Utilities/_ThreadCheckedObject.cs.meta new file mode 100644 index 0000000..0327615 --- /dev/null +++ b/Assets/ARDK/Utilities/_ThreadCheckedObject.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 55c3ffaaa383422daf8e3212397f2a94 +timeCreated: 1613512077 \ No newline at end of file diff --git a/Assets/ARDK/Utilities/_UpdateLoop.cs b/Assets/ARDK/Utilities/_UpdateLoop.cs new file mode 100644 index 0000000..c710712 --- /dev/null +++ b/Assets/ARDK/Utilities/_UpdateLoop.cs @@ -0,0 +1,68 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using UnityEngine; + +namespace Niantic.ARDK.Utilities +{ + /// + /// A class to inject callbacks into unity update loops. + /// + [DefaultExecutionOrder(Int32.MinValue)] + internal sealed class _UpdateLoop: + MonoBehaviour + { + private bool _createdByStaticInitializer; + + /// + /// Event for standard unity tick. + /// @Note: Tick is always called before other objects' Update, so if you subscribe in Update to both + /// Tick and LateTick, LateTick will run first, on the frame that you subscribe. + /// + public static event Action Tick = () => {}; + + /// + /// Event for standard unity late tick. + /// + public static event Action LateTick = () => {}; + + /// + /// Event for standard unity fixed tick. + /// + public static event Action FixedTick = () => {}; + + static _UpdateLoop() + { + var go = new GameObject("__update_loop__", typeof(_UpdateLoop)); + go.hideFlags = HideFlags.HideInHierarchy; + + // Can only use DontDestroyOnLoad in play mode, but _UpdateLoop is used + // in edit mode tests as well + if (Application.isPlaying) + DontDestroyOnLoad(go); + + go.GetComponent<_UpdateLoop>()._createdByStaticInitializer = true; + } + + private void Start() + { + if (!_createdByStaticInitializer) + Destroy(this); + } + + private void Update() + { + Tick(); + } + + private void LateUpdate() + { + LateTick(); + } + + private void FixedUpdate() + { + FixedTick(); + } + } +} diff --git a/Assets/ARDK/Utilities/_UpdateLoop.cs.meta b/Assets/ARDK/Utilities/_UpdateLoop.cs.meta new file mode 100644 index 0000000..35e5b4b --- /dev/null +++ b/Assets/ARDK/Utilities/_UpdateLoop.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: b3a42405f051483ea358e3ac410014b1 +timeCreated: 1554416020 \ No newline at end of file diff --git a/Assets/ARDK/VERSION b/Assets/ARDK/VERSION new file mode 100644 index 0000000..227cea2 --- /dev/null +++ b/Assets/ARDK/VERSION @@ -0,0 +1 @@ +2.0.0 diff --git a/Assets/ARDK/VERSION.meta b/Assets/ARDK/VERSION.meta new file mode 100644 index 0000000..0a75868 --- /dev/null +++ b/Assets/ARDK/VERSION.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8e2fdb8ec116a48a0b273e46b42cfdd4 +timeCreated: 1532112588 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VirtualStudio.meta b/Assets/ARDK/VirtualStudio.meta new file mode 100644 index 0000000..0dbebc7 --- /dev/null +++ b/Assets/ARDK/VirtualStudio.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6a95d2b405f2546d19dcd49b4a353eb6 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VirtualStudio/AR.meta b/Assets/ARDK/VirtualStudio/AR.meta new file mode 100644 index 0000000..c8ec0d2 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 45c41522d0ba4ed697d09d38135d0ff7 +timeCreated: 1579731764 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/Camera.meta b/Assets/ARDK/VirtualStudio/AR/Camera.meta new file mode 100644 index 0000000..b75bfad --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/Camera.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d7d5d47b31c14ff9852782b2568cb988 +timeCreated: 1586295050 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/Camera/Input.meta b/Assets/ARDK/VirtualStudio/AR/Camera/Input.meta new file mode 100644 index 0000000..ee8883a --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/Camera/Input.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4eb359f11a1bd493b8fe94f9b46b2af3 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VirtualStudio/AR/Camera/Input/_CameraController.cs b/Assets/ARDK/VirtualStudio/AR/Camera/Input/_CameraController.cs new file mode 100644 index 0000000..0c2503c --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/Camera/Input/_CameraController.cs @@ -0,0 +1,132 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections; +using System.Collections.Generic; + +using Niantic.ARDK.VirtualStudio.AR; +using UnityEngine; + +#if ENABLE_INPUT_SYSTEM +using UnityEngine.InputSystem; +#endif + +namespace Niantic.ARDK.VirtualStudio.AR.Camera.Input +{ + internal class _CameraController: MonoBehaviour + { +#if ENABLE_INPUT_SYSTEM + private Transform cameraTransform; + private Mouse currentMouse; + private Keyboard currentKeyboard; + + private void Awake() + { + cameraTransform = transform; + currentMouse = Mouse.current; + currentKeyboard = Keyboard.current; + } + + private void Update() + { + RotateScroll(); + RotateDrag(); + Move(); + } + + private void Move() + { + cameraTransform.position += Time.deltaTime * _MockCameraConfiguration.MoveSpeed * GetMoveInput(); + } + + private void RotateDrag() + { + var isPressed = currentMouse.rightButton.isPressed || + currentMouse.rightButton.wasPressedThisFrame; + if (isPressed) + { + var mouseDeltaDirection = new Vector2(currentMouse.delta.x.ReadValue(), -1 * currentMouse.delta.y.ReadValue()); + Rotate(mouseDeltaDirection, _MockCameraConfiguration.LookSpeed); + } + } + + private void RotateScroll() + { + if (Mouse.current.scroll.ReadValue().magnitude > 0.01f) // not sure why but if this is 0, the camera tracks the mouse cursor. + { + var mouseScrollDelta = + new Vector2 + ( + currentMouse.scroll.x.ReadValue(), + currentMouse.scroll.y.ReadValue() + ); + + Rotate + ( + direction:mouseScrollDelta * _MockCameraConfiguration.ScrollDirection, + speed:_MockCameraConfiguration.LookSpeed / 10 + ); + } + } + + private void Rotate(Vector2 direction, float speed) + { + var pitchVector = Time.deltaTime * speed * direction.y; + var position = cameraTransform.position; + cameraTransform.RotateAround(position, cameraTransform.right, pitchVector); + + var yawVector = Time.deltaTime * speed * direction.x; + cameraTransform.RotateAround(position, Vector3.up, yawVector); + } + + private Vector3 GetMoveInput() + { + var input = Vector3.zero; + + var isWPressed = currentKeyboard.wKey.isPressed || + currentKeyboard.wKey.wasPressedThisFrame; + if (isWPressed) + { + input += cameraTransform.forward; + } + + var isSPressed = currentKeyboard.sKey.isPressed || + currentKeyboard.sKey.wasPressedThisFrame; + if (isSPressed) + { + input -= cameraTransform.forward; + } + + var isAPressed = currentKeyboard.aKey.isPressed || + currentKeyboard.aKey.wasPressedThisFrame; + if (isAPressed) + { + input -= cameraTransform.right; + } + + var isDPressed = currentKeyboard.dKey.isPressed || + currentKeyboard.dKey.wasPressedThisFrame; + if (isDPressed) + { + input += cameraTransform.right; + } + + var isQPressed = currentKeyboard.qKey.isPressed || + currentKeyboard.qKey.wasPressedThisFrame; + if (isQPressed) + { + input -= Vector3.up; + } + + var isEPressed = currentKeyboard.eKey.isPressed || + currentKeyboard.eKey.wasPressedThisFrame; + if (isEPressed) + { + input += Vector3.up; + } + + return input; + } +#endif + } +} \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/Camera/Input/_CameraController.cs.meta b/Assets/ARDK/VirtualStudio/AR/Camera/Input/_CameraController.cs.meta new file mode 100644 index 0000000..52b1c32 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/Camera/Input/_CameraController.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e7863f6d5617c4c44b78726a30ec36ef +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VirtualStudio/AR/Camera/Input/_CameraInputSystemProvider.cs b/Assets/ARDK/VirtualStudio/AR/Camera/Input/_CameraInputSystemProvider.cs new file mode 100644 index 0000000..36fc902 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/Camera/Input/_CameraInputSystemProvider.cs @@ -0,0 +1,23 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System.Collections; +using System.Collections.Generic; + +using UnityEngine; + +namespace Niantic.ARDK.VirtualStudio.AR.Camera.Input +{ + internal static class _CameraInputSystemProvider + { + public static void AttachController(GameObject cameraGameObject) + { +#if ENABLE_LEGACY_INPUT_MANAGER + var cameraLegacyInputController = cameraGameObject.AddComponent<_LegacyCameraController>(); + cameraLegacyInputController.enabled = true; + +#else + var cameraNewInputController = cameraGameObject.AddComponent<_CameraController>(); + cameraNewInputController.enabled = true; +#endif + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/Camera/Input/_CameraInputSystemProvider.cs.meta b/Assets/ARDK/VirtualStudio/AR/Camera/Input/_CameraInputSystemProvider.cs.meta new file mode 100644 index 0000000..3eee564 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/Camera/Input/_CameraInputSystemProvider.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5a6cb438b75b0408b8e00849fddf9304 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VirtualStudio/AR/Camera/Input/_LegacyCameraController.cs b/Assets/ARDK/VirtualStudio/AR/Camera/Input/_LegacyCameraController.cs new file mode 100644 index 0000000..9e3aa53 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/Camera/Input/_LegacyCameraController.cs @@ -0,0 +1,92 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; +using System.Collections; +using System.Collections.Generic; + +using Niantic.ARDK.VirtualStudio.AR; + +using UnityEngine; + +namespace Niantic.ARDK.VirtualStudio.AR.Camera.Input +{ + internal class _LegacyCameraController: MonoBehaviour + { +#if ENABLE_LEGACY_INPUT_MANAGER + private const string MouseHorizontalAxis = "Mouse X"; + private const string MouseVerticalAxis = "Mouse Y"; + + private Transform _cameraTransform; + + private void Awake() + { + _cameraTransform = gameObject.transform; + } + + private void Update() + { + RotateScroll(); + RotateDrag(); + Move(); + } + + private void RotateScroll() + { + var scrollSpeed = _MockCameraConfiguration.LookSpeed / 2; + var mouseScrollVector = UnityEngine.Input.mouseScrollDelta * _MockCameraConfiguration.ScrollDirection; + Rotate(mouseScrollVector, scrollSpeed); + } + + private void RotateDrag() + { + if (UnityEngine.Input.GetMouseButton(1)) + { + var dragDelta = new Vector2 + (UnityEngine.Input.GetAxis(MouseHorizontalAxis), -UnityEngine.Input.GetAxis(MouseVerticalAxis)); + + Rotate(dragDelta, _MockCameraConfiguration.LookSpeed); + } + } + + private void Rotate(Vector2 direction, float speed) + { + var pitchVector = Time.deltaTime * speed * direction.y; + _cameraTransform.RotateAround + (_cameraTransform.position, _cameraTransform.right, pitchVector); + + var yawVector = Time.deltaTime * speed * direction.x; + _cameraTransform.RotateAround(_cameraTransform.position, Vector3.up, yawVector); + } + + private void Move() + { + _cameraTransform.position += + Time.deltaTime * _MockCameraConfiguration.MoveSpeed * GetMoveInput(); + } + + private Vector3 GetMoveInput() + { + var input = Vector3.zero; + + if (UnityEngine.Input.GetKey(KeyCode.W)) + input += _cameraTransform.forward; + + if (UnityEngine.Input.GetKey(KeyCode.S)) + input -= _cameraTransform.forward; + + if (UnityEngine.Input.GetKey(KeyCode.A)) + input -= _cameraTransform.right; + + if (UnityEngine.Input.GetKey(KeyCode.D)) + input += _cameraTransform.right; + + if (UnityEngine.Input.GetKey(KeyCode.Q)) + input -= Vector3.up; + + if (UnityEngine.Input.GetKey(KeyCode.E)) + input += Vector3.up; + + return input; + } +#endif + } +} diff --git a/Assets/ARDK/VirtualStudio/AR/Camera/Input/_LegacyCameraController.cs.meta b/Assets/ARDK/VirtualStudio/AR/Camera/Input/_LegacyCameraController.cs.meta new file mode 100644 index 0000000..e688f95 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/Camera/Input/_LegacyCameraController.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 423e8d9a6071649af9c777b1d146b2ec +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VirtualStudio/AR/Camera/Resources.meta b/Assets/ARDK/VirtualStudio/AR/Camera/Resources.meta new file mode 100644 index 0000000..71a6c59 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/Camera/Resources.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a5e6a1a718644e488d623193bc1bb9a0 +timeCreated: 1624973501 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/Camera/Resources/FlipImage.shader b/Assets/ARDK/VirtualStudio/AR/Camera/Resources/FlipImage.shader new file mode 100644 index 0000000..7f92255 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/Camera/Resources/FlipImage.shader @@ -0,0 +1,53 @@ +Shader "Hidden/FlipImage" +{ + Properties + { + _MainTex ("Texture", 2D) = "white" {} + } + SubShader + { + Cull Off ZWrite Off ZTest Always + + Pass + { + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + + #include "UnityCG.cginc" + + struct appdata + { + float4 vertex : POSITION; + float2 uv : TEXCOORD0; + }; + + struct v2f + { + float2 uv : TEXCOORD0; + float4 vertex : SV_POSITION; + }; + + v2f vert (appdata v) + { + v2f o; + o.vertex = UnityObjectToClipPos(v.vertex); + o.uv = v.uv; + + // Flip y-axis because [0,0] is bottom left in Unity textures + // but top left when surfaced from native + o.vertex.y = -o.vertex.y; + + return o; + } + + sampler2D _MainTex; + + float4 frag (v2f i) : SV_Target + { + return tex2D(_MainTex, i.uv); + } + ENDCG + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/Camera/Resources/FlipImage.shader.meta b/Assets/ARDK/VirtualStudio/AR/Camera/Resources/FlipImage.shader.meta new file mode 100644 index 0000000..d8afb2f --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/Camera/Resources/FlipImage.shader.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 950d7128ba22543829db59aed36cbc28 +timeCreated: 1624982173 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/Camera/Resources/Segmentation.shader b/Assets/ARDK/VirtualStudio/AR/Camera/Resources/Segmentation.shader new file mode 100644 index 0000000..d3f791e --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/Camera/Resources/Segmentation.shader @@ -0,0 +1,55 @@ +Shader "ARDK/Segmentation" +{ + Properties + { + // The segmentation channel bits. This is set via a MaterialPropertyBlock in each + // game object that needs to be segmented. See MockSemanticLabel.cs + [PerRendererData] PackedColor("PackedColor", Color) = (0.0, 0.0, 0.0, 0.0) + } + SubShader + { + Pass + { + Cull Off + + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + + #include "UnityCG.cginc" + + struct appdata + { + float4 vertex : POSITION; + float2 uv : TEXCOORD0; + }; + + struct v2f + { + float2 uv : TEXCOORD0; + float4 vertex : SV_POSITION; + }; + + v2f vert (appdata v) + { + v2f o; + o.vertex = UnityObjectToClipPos(v.vertex); + o.uv = v.uv; + + // Flip y-axis because [0,0] is bottom left in Unity textures + // but top left when surfaced from native + o.vertex.y = -o.vertex.y; + + return o; + } + + float4 PackedColor; + + float4 frag (v2f i) : SV_Target + { + return PackedColor; + } + ENDCG + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/Camera/Resources/Segmentation.shader.meta b/Assets/ARDK/VirtualStudio/AR/Camera/Resources/Segmentation.shader.meta new file mode 100644 index 0000000..9b31e38 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/Camera/Resources/Segmentation.shader.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a4c48a72b6b249c1a1da1226dd53dedd +timeCreated: 1625244739 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/Camera/Resources/UnityToMetricDepth.shader b/Assets/ARDK/VirtualStudio/AR/Camera/Resources/UnityToMetricDepth.shader new file mode 100644 index 0000000..49b3c71 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/Camera/Resources/UnityToMetricDepth.shader @@ -0,0 +1,79 @@ +Shader "Hidden/UnityToMetricDepth" +{ + Properties + { + _MainTex ("Texture", 2D) = "white" {} + } + SubShader + { + // No culling or depth + Cull Off ZWrite Off ZTest Always + + Pass + { + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + + #include "UnityCG.cginc" + + struct appdata + { + float4 vertex : POSITION; + float2 uv : TEXCOORD0; + }; + + struct v2f + { + float2 uv : TEXCOORD0; + float4 vertex : SV_POSITION; + }; + + v2f vert (appdata v) + { + v2f o; + o.vertex = UnityObjectToClipPos(v.vertex); + o.uv = v.uv; + + // Flip y-axis because [0,0] is bottom left in Unity textures + // but top left when surfaced from native + o.vertex.y = -o.vertex.y; + + return o; + } + + sampler2D_float _MainTex; + + // Values used to linearize the Z buffer (http://www.humus.name/temp/Linearize%20depth.txt) + // x = 1-far/near + // y = far/near + // z = x/far + // w = y/far + + // or in case of a reversed depth buffer (UNITY_REVERSED_Z is 1) + // x = -1+far/near + // y = 1 + // z = x/far + // w = 1/far + + float _ZBufferParams_Z; + float _ZBufferParams_W; + + float frag (v2f i) : SV_Target + { + // Pixel values in the _CameraDepthTexture range between + // 1 (near) and 0 (far), with a non-linear distribution. + float depth = tex2D(_MainTex, i.uv).r; + + // RFloat textures are not clamped to 0-1, so we can return + // the actual metric depth even though it can go over 1.0. + + // LinearEyeDepth function duplicated from UnityCG.cginc so + // _ZBufferParams can be specified unaffected by other cameras. + float linearEyeDepth = 1.0 / (_ZBufferParams_Z * depth + _ZBufferParams_W); + return linearEyeDepth; + } + ENDCG + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/Camera/Resources/UnityToMetricDepth.shader.meta b/Assets/ARDK/VirtualStudio/AR/Camera/Resources/UnityToMetricDepth.shader.meta new file mode 100644 index 0000000..e0f4007 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/Camera/Resources/UnityToMetricDepth.shader.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 661204fd31de4c318c3562ebcaf938b0 +timeCreated: 1624982173 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/Camera/_MockCameraConfiguration.cs b/Assets/ARDK/VirtualStudio/AR/Camera/_MockCameraConfiguration.cs new file mode 100644 index 0000000..365b489 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/Camera/_MockCameraConfiguration.cs @@ -0,0 +1,43 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using UnityEngine; + +namespace Niantic.ARDK.VirtualStudio.AR +{ + internal static class _MockCameraConfiguration + { + // Camera control keys + private const string FPS_KEY = "ARDK_Mock_FPS"; + private const string MOVESPEED_KEY = "ARDK_Mock_Movespeed"; + private const string LOOKSPEED_KEY = "ARDK_Mock_Lookspeed"; + private const string SCROLLDIRECTION_KEY = "ARDK_Mock_ScrollDirection"; + + private const int _DefaultFps = 30; + private const float _DefaultMoveSpeed = 10f; + private const int _DefaultLookSpeed = 180; + private const int _DefaultScrollDirection = -1; + + internal static int FPS + { + get { return PlayerPrefs.GetInt(FPS_KEY, _DefaultFps); } + set { PlayerPrefs.SetInt(FPS_KEY, value);} + } + + internal static float MoveSpeed + { + get { return PlayerPrefs.GetFloat(MOVESPEED_KEY, _DefaultMoveSpeed); } + set { PlayerPrefs.SetFloat(MOVESPEED_KEY, value);} + } + + internal static int LookSpeed + { + get { return PlayerPrefs.GetInt(LOOKSPEED_KEY, _DefaultLookSpeed); } + set { PlayerPrefs.SetInt(LOOKSPEED_KEY, value);} + } + + internal static int ScrollDirection + { + get { return PlayerPrefs.GetInt(SCROLLDIRECTION_KEY, _DefaultScrollDirection); } + set { PlayerPrefs.SetInt(SCROLLDIRECTION_KEY, value);} + } + } +} diff --git a/Assets/ARDK/VirtualStudio/AR/Camera/_MockCameraConfiguration.cs.meta b/Assets/ARDK/VirtualStudio/AR/Camera/_MockCameraConfiguration.cs.meta new file mode 100644 index 0000000..959746c --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/Camera/_MockCameraConfiguration.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 0d82cf8275e3457e9cb1463905feb1d8 +timeCreated: 1623254942 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/Camera/_MockFrameBufferProvider.cs b/Assets/ARDK/VirtualStudio/AR/Camera/_MockFrameBufferProvider.cs new file mode 100644 index 0000000..dbf378b --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/Camera/_MockFrameBufferProvider.cs @@ -0,0 +1,655 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.ARSessionEventArgs; +using Niantic.ARDK.AR.Camera; +using Niantic.ARDK.AR.Configuration; +using Niantic.ARDK.AR.Awareness.Depth; +using Niantic.ARDK.AR.Awareness.Semantics; +using Niantic.ARDK.AR.Frame; +using Niantic.ARDK.AR.Image; +using Niantic.ARDK.Rendering; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Logging; + +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; + +using UnityEngine; +using UnityEngine.Rendering; + +using MathUtils = Niantic.ARDK.Utilities.MathUtils; + +#if ARDK_HAS_URP +using UnityEngine.Experimental.Rendering; +using UnityEngine.Experimental.Rendering.Universal; +using UnityEngine.Rendering.Universal; + +using Niantic.ARDK.Rendering.SRP; +#endif + +#if UNITY_EDITOR +using UnityEditor; +#endif + +namespace Niantic.ARDK.VirtualStudio.AR.Mock +{ + using Camera = UnityEngine.Camera; + internal sealed class _MockFrameBufferProvider: + IDisposable + { + // ARSession data + private readonly _MockARSession _arSession; + private readonly float _timeBetweenFrames; + private float _timeSinceLastFrame; + private _SerializableARCamera _cachedSerializedCamera; + private readonly Transform _camerasRoot; + + // Image buffer + private Camera _imageCamera; + private CameraIntrinsics _imageIntrinsics; + private RenderTexture _imageRT; + private RenderTexture _imageFlippedRT; + private Shader _flipImageShader; + private Material _flipImageMaterial; + + // Depth buffer + private bool _generateDepth; + private readonly float _timeBetweenDepthUpdates; + private float _timeSinceLastDepthUpdate; + private Camera _depthCamera; + private CameraIntrinsics _depthIntrinsics; + private RenderTexture _depthRT; + private RenderTexture _depthOnlyRT; + private Shader _depthToDisparityShader; + private Material _depthToDisparityMaterial; + + // Semantics buffer + private bool _generateSemantics; + private readonly float _timeBetweenSemanticsUpdates; + private float _timeSinceLastSemanticsUpdate; + private Camera _semanticsCamera; + private CameraIntrinsics _semanticsIntrinsics; + private Shader _semanticsShader; + private RenderTexture _semanticsRT; + private Texture2D _semanticsTex; + private string[] _channelNames; + + // Magic numbers to define the image resolution of mock frames + internal const int _ARImageWidth = 1920; + internal const int _ARImageHeight = 1440; + internal const int _SensorFocalLength = 26; + + // Awareness Model Params (updated ARDK 0.10): + private const int _ModelWidth = 256; + private const int _ModelHeight = 144; + private const float _ModelNearDistance = 0.2f; + private const float _ModelFarDistance = 100f; + + public const string MOCK_LAYER_NAME = "ARDK_MockWorld"; + + public const string MOCK_LAYER_MISSING_MSG = + "No ARDK_MockWorld layer found in the Layers list (Edit > ProjectSettings > Tags and Layers)"; + + public _MockFrameBufferProvider(_MockARSession mockARSession, Transform camerasRoot) + { + _arSession = mockARSession; + _arSession.Ran += CheckRunConfiguration; + _timeBetweenFrames = 1f / _MockCameraConfiguration.FPS; + + if (mockARSession.Configuration is _SerializableARWorldTrackingConfiguration worldTrackingConfiguration) + { + _timeBetweenDepthUpdates = 1f / worldTrackingConfiguration.DepthTargetFrameRate; + _timeBetweenSemanticsUpdates = 1f / worldTrackingConfiguration.SemanticTargetFrameRate; + } + + _camerasRoot = camerasRoot; + InitializeImageGeneration(); + + _UpdateLoop.Tick += Update; + } + + private void CheckRunConfiguration(ARSessionRanArgs args) + { + if (_arSession.Configuration is IARWorldTrackingConfiguration worldTrackingConfiguration) + { + _generateDepth = worldTrackingConfiguration.IsDepthEnabled; + _generateSemantics = worldTrackingConfiguration.IsSemanticSegmentationEnabled; + } + else + { + _generateDepth = false; + _generateSemantics = false; + } + + if (_generateDepth && _depthCamera == null) + InitializeDepthGeneration(); + + if (_generateSemantics && _semanticsCamera == null) + InitializeSemanticsGeneration(); + + if (_depthCamera != null) + { + _depthCamera.enabled = _generateDepth; + _depthCamera.depthTextureMode = + _generateDepth ? DepthTextureMode.Depth : DepthTextureMode.None; + } + + if (_semanticsCamera != null) + { + _semanticsCamera.enabled = _generateSemantics; + } + } + + private void InitializeImageGeneration() + { + // Instantiate a new Unity camera + _imageCamera = CreateCameraBase("Image"); + + // Configure the camera to use physical properties + _imageCamera.usePhysicalProperties = true; + _imageCamera.focalLength = _SensorFocalLength; + _imageCamera.nearClipPlane = 0.1f; + _imageCamera.farClipPlane = 100f; + + // Infer the orientation of the editor + var editorOrientation = Screen.width > Screen.height + ? ScreenOrientation.LandscapeLeft + : ScreenOrientation.Portrait; + + // Rotate the 'device' to the UI orientation + _imageCamera.transform.localRotation = MathUtils.CalculateViewRotation + ( + from: ScreenOrientation.LandscapeLeft, + to: editorOrientation + ).ToRotation(); + + // Set up rendering offscreen to render texture. + _imageRT = new RenderTexture(_ARImageWidth, _ARImageHeight, 16, RenderTextureFormat.BGRA32); + _imageFlippedRT = new RenderTexture(_ARImageWidth, _ARImageHeight, 16, RenderTextureFormat.BGRA32); + _imageRT.Create(); + _imageFlippedRT.Create(); + + _flipImageShader = Resources.Load("FlipImage"); + _flipImageMaterial = new Material(_flipImageShader); + _imageCamera.targetTexture = _imageRT; + + // This needs to be called AFTER we set the target texture + _imageIntrinsics = MathUtils.CalculateIntrinsics(_imageCamera); + + // Reading this property's value is equivalent to calling + // the CalculateProjectionMatrix method. + var projection = MathUtils.CalculateProjectionMatrix + ( + _imageIntrinsics, + _ARImageWidth, + _ARImageHeight, + Screen.width, + Screen.height, + RenderTarget.ScreenOrientation, + _imageCamera.nearClipPlane, + _imageCamera.farClipPlane + ); + + // Initialize the view matrix. + // This will be updated in every frame. + var initialView = GetMockViewMatrix(_imageCamera); + + var imageResolution = new Resolution + { + width = _ARImageWidth, height = _ARImageHeight + }; + + _cachedSerializedCamera = new _SerializableARCamera + ( + TrackingState.Normal, + TrackingStateReason.None, + imageResolution, + imageResolution, + _imageIntrinsics, + _imageIntrinsics, + initialView.inverse, + projectionMatrix: projection, + estimatedViewMatrix: initialView, + worldScale: 1.0f + ); + } + + private void InitializeDepthGeneration() + { + _depthCamera = CreateAwarenessCamera("Depth"); + _depthCamera.depthTextureMode = DepthTextureMode.Depth; + + var editorOrientation = Screen.width > Screen.height + ? ScreenOrientation.LandscapeLeft + : ScreenOrientation.Portrait; + + // Rotate the 'device' to the UI orientation + _depthCamera.transform.localRotation = MathUtils.CalculateViewRotation + ( + from: ScreenOrientation.LandscapeLeft, + to: editorOrientation + ).ToRotation(); + + _depthRT = + new RenderTexture + ( + _ModelWidth, + _ModelHeight, + 16, + RenderTextureFormat.Depth + ); + + _depthOnlyRT = + new RenderTexture + ( + _ModelWidth, + _ModelHeight, + 0, + RenderTextureFormat.RFloat + ); + + _depthToDisparityShader = Resources.Load("UnityToMetricDepth"); + _depthToDisparityMaterial = new Material(_depthToDisparityShader); + + var farDividedByNear = _ModelFarDistance / _ModelNearDistance; + _depthToDisparityMaterial.SetFloat("_ZBufferParams_Z", (-1 + farDividedByNear) / _ModelFarDistance); + _depthToDisparityMaterial.SetFloat("_ZBufferParams_W", 1 / _ModelFarDistance); + + _depthCamera.targetTexture = _depthRT; + _depthIntrinsics = MathUtils.CalculateIntrinsics(_depthCamera); + } + + private void InitializeSemanticsGeneration() + { + _semanticsCamera = CreateAwarenessCamera("Semantics"); + _semanticsCamera.clearFlags = CameraClearFlags.SolidColor; + _semanticsCamera.backgroundColor = new Color(0, 0, 0, 0); + + var editorOrientation = Screen.width > Screen.height + ? ScreenOrientation.LandscapeLeft + : ScreenOrientation.Portrait; + + // Rotate the 'device' to the UI orientation + _semanticsCamera.transform.localRotation = MathUtils.CalculateViewRotation + ( + from: ScreenOrientation.LandscapeLeft, + to: editorOrientation + ).ToRotation(); + + _semanticsRT = + new RenderTexture + ( + _ModelWidth, + _ModelHeight, + 16, + RenderTextureFormat.ARGB32 + ); + + _semanticsRT.Create(); + _semanticsCamera.targetTexture = _semanticsRT; + + _semanticsShader = Resources.Load("Segmentation"); + _semanticsCamera.SetReplacementShader(_semanticsShader, String.Empty); + + _semanticsTex = new Texture2D(_ModelWidth, _ModelHeight, TextureFormat.ARGB32, false); + + _semanticsIntrinsics = MathUtils.CalculateIntrinsics(_semanticsCamera); + + SetupReplacementRenderer(); + + _channelNames = Enum.GetNames(typeof(MockSemanticLabel.ChannelName)); + } + + private void SetupReplacementRenderer() + { +#if ARDK_HAS_URP + if (!_RenderPipelineInternals.IsUniversalRenderPipelineEnabled) + return; + + var rendererIndex = + _RenderPipelineInternals.GetRendererIndex + ( + _RenderPipelineInternals.REPLACEMENT_RENDERER_NAME + ); + + if (rendererIndex < 0) + { + ARLog._Error + ( + "Cannot generate mock semantic segmentation buffers unless the ArdkUrpAssetRenderer" + + " is added to the Renderer List." + ); + + return; + } + + _semanticsCamera.GetUniversalAdditionalCameraData().SetRenderer(rendererIndex); +#endif + } + + private Camera CreateCameraBase(string name) + { + var cameraObject = new GameObject(name); + cameraObject.transform.SetParent(_camerasRoot); + + var camera = cameraObject.AddComponent(); + camera.depth = int.MinValue; + +#if UNITY_EDITOR + var layerIndex = LayerMask.NameToLayer(MOCK_LAYER_NAME); + if (layerIndex < 0) + { + if (!CreateLayer(MOCK_LAYER_NAME, out layerIndex)) + return null; + } + camera.cullingMask = LayerMask.GetMask(MOCK_LAYER_NAME); +#endif + + return camera; + } + + private Camera CreateAwarenessCamera(string name) + { + var camera = CreateCameraBase(name); + + camera.nearClipPlane = _ModelNearDistance; + camera.farClipPlane = _ModelFarDistance; + camera.usePhysicalProperties = true; + camera.focalLength = _SensorFocalLength; + + return camera; + } + + private bool _isDisposed; + public void Dispose() + { + if (_isDisposed) + return; + + _isDisposed = true; + + _imageRT.Release(); + _imageFlippedRT.Release(); + + if (_depthCamera != null) + { + GameObject.Destroy(_depthCamera.gameObject); + _depthRT.Release(); + _depthOnlyRT.Release(); + } + + if (_semanticsCamera != null) + { + GameObject.Destroy(_semanticsCamera.gameObject); + _semanticsRT.Release(); + } + } + + private static Matrix4x4 GetMockViewMatrix(Camera serializedCamera) + { + var rotation = MathUtils.CalculateViewRotation + ( + from: ScreenOrientation.LandscapeLeft, + to: RenderTarget.ScreenOrientation + ); + + var narView = serializedCamera.worldToCameraMatrix.ConvertViewMatrixBetweenNarAndUnity(); + + return rotation * narView; + } + + private void Update() + { + if (_arSession != null && _arSession.State == ARSessionState.Running) + { + _timeSinceLastFrame += Time.deltaTime; + if (_timeSinceLastFrame >= _timeBetweenFrames) + { + _timeSinceLastFrame = 0; + + var mockViewMatrix = GetMockViewMatrix(_imageCamera); + _cachedSerializedCamera._estimatedViewMatrix = mockViewMatrix; + _cachedSerializedCamera.Transform = mockViewMatrix.inverse; + + _SerializableDepthBuffer depthBuffer = null; + if (_generateDepth && Time.time - _timeSinceLastDepthUpdate > _timeBetweenDepthUpdates) + { + depthBuffer = _GetDepthBuffer(); + _timeSinceLastDepthUpdate = Time.time; + } + + _SerializableSemanticBuffer semanticBuffer = null; + if (_generateSemantics && Time.time - _timeSinceLastSemanticsUpdate > _timeBetweenSemanticsUpdates) + { + semanticBuffer = _GetSemanticBuffer(); + _timeSinceLastSemanticsUpdate = Time.time; + } + + var serializedFrame = new _SerializableARFrame + ( + capturedImageBuffer: _GetImageBuffer(), + depthBuffer: depthBuffer, + semanticBuffer: semanticBuffer, + camera: _cachedSerializedCamera, + lightEstimate: null, + anchors: null, + maps: null, + worldScale: 1.0f, + estimatedDisplayTransform: MathUtils.CalculateDisplayTransform + ( + _ARImageWidth, + _ARImageHeight, + Screen.width, + Screen.height, + RenderTarget.ScreenOrientation, + invertVertically: true + ) + ); + + _arSession.UpdateFrame(serializedFrame); + } + } + } + + private _SerializableImageBuffer _GetImageBuffer() + { + Graphics.Blit(_imageRT, _imageFlippedRT, _flipImageMaterial); + + var imageData = + new NativeArray + ( + _ARImageWidth * _ARImageHeight * 4, + Allocator.Persistent, + NativeArrayOptions.UninitializedMemory + ); + +#if ENABLE_UNITY_COLLECTIONS_CHECKS + NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref imageData, AtomicSafetyHandle.Create()); +#endif + + AsyncGPUReadback.RequestIntoNativeArray(ref imageData, _imageFlippedRT).WaitForCompletion(); + + var plane = + new _SerializableImagePlane + ( + imageData, + _ARImageWidth, + _ARImageHeight, + _ARImageWidth * 4, + 4 + ); + + var buffer = + new _SerializableImageBuffer + ( + ImageFormat.BGRA, + new _SerializableImagePlanes(new[] { plane }), + 75 + ); + + return buffer; + } + + private _SerializableDepthBuffer _GetDepthBuffer() + { + Graphics.Blit(_depthRT, _depthOnlyRT, _depthToDisparityMaterial); + + var depthData = new NativeArray + ( + _ModelWidth * _ModelHeight, + Allocator.Persistent, + NativeArrayOptions.UninitializedMemory + ); + +#if ENABLE_UNITY_COLLECTIONS_CHECKS + NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref depthData, AtomicSafetyHandle.Create()); +#endif + + AsyncGPUReadback.RequestIntoNativeArray(ref depthData, _depthOnlyRT).WaitForCompletion(); + + var buffer = new _SerializableDepthBuffer + ( + _ModelWidth, + _ModelHeight, + isKeyframe:true, + GetMockViewMatrix(_imageCamera), + depthData, + _ModelNearDistance, + _ModelFarDistance, + _depthIntrinsics + ) + { + IsRotatedToScreenOrientation = true + }; + + return buffer; + } + + private _SerializableSemanticBuffer _GetSemanticBuffer() + { + var data = new NativeArray + ( + _ModelWidth * _ModelHeight, + Allocator.Persistent, + NativeArrayOptions.UninitializedMemory + ); + +#if ENABLE_UNITY_COLLECTIONS_CHECKS + NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref data, AtomicSafetyHandle.Create()); +#endif + + // Doing this in the CPU is slower, but I couldn't figure out how to get + // the correct uint value out of a shader. Performance is sufficient. + var currRT = RenderTexture.active; + RenderTexture.active = _semanticsRT; + + _semanticsTex.ReadPixels(new Rect(0, 0, _ModelWidth, _ModelHeight), 0, 0); + _semanticsTex.Apply(); + + RenderTexture.active = currRT; + + var byteArray = _semanticsTex.GetPixels32(); + for (var i = 0; i < byteArray.Length; i++) + { + data[i] = MockSemanticLabel.ToInt(byteArray[i]); + } + + var buffer = new _SerializableSemanticBuffer + ( + _ModelWidth, + _ModelHeight, + isKeyframe:true, + GetMockViewMatrix(_imageCamera), + data, + _channelNames, + _semanticsIntrinsics + ) + { + IsRotatedToScreenOrientation = true + }; + + return buffer; + } + +#if UNITY_EDITOR + internal static void RemoveMockFromCullingMask(Camera cam) + { + // get the input layer name's index, which should range from 0 to Unity's max # of layers minus 1 + int layerIndex = LayerMask.NameToLayer(MOCK_LAYER_NAME); + + if (layerIndex >= 0 || CreateLayer(MOCK_LAYER_NAME, out layerIndex)) + { + // perform a guardrail check to see if the mock layer + // is included in the ar camera's culling mask + if ((cam.cullingMask & (1 << layerIndex)) != 0) + { + // in the case that the mock layer is included, remove it from the culling mask + cam.cullingMask &= ~(1 << layerIndex); + } + } + } + + public static bool CreateLayer(string layerName, out int layerIndex) + { + layerIndex = -1; + if (LayerMask.NameToLayer(layerName) >= 0) + { + ARLog._WarnFormat("Layer: {0} already exists in TagManager.", false, layerName); + return false; + } + + var assets = AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/TagManager.asset"); + if (assets.Length == 0) + { + ARLog._ErrorFormat + ( + "No ProjectSettings/TagManager.asset file found to add Layer: {0} required for use " + + "of Virtual Studio Mock mode.", + false, + layerName + ); + + return false; + } + + var tagManager = new SerializedObject(assets[0]); + var layers = tagManager.FindProperty("layers"); + + // First 7 layers are reserved for Unity's built-in layers. + for (int i = 8, j = layers.arraySize; i < j; i++) + { + var layerProp = layers.GetArrayElementAtIndex(i); + if (string.IsNullOrEmpty(layerProp.stringValue)) + { + layerProp.stringValue = layerName; + tagManager.ApplyModifiedProperties(); + AssetDatabase.SaveAssets(); + + ARLog._ReleaseFormat + ( + "Layer: {0} has been added to your project for use with Virtual Studio Mock mode." + + "See the Edit > Project Settings > Tags and Layers menu to verify.", + false, + layerName + ); + + layerIndex = i; + return true; + } + } + + ARLog._ErrorFormat + ( + "All user layer slots are in use. Unable to add Layer: {0} required for use " + + "of Virtual Studio Mock mode.", + layerName + ); + + return false; + } +#endif + } +} \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/Camera/_MockFrameBufferProvider.cs.meta b/Assets/ARDK/VirtualStudio/AR/Camera/_MockFrameBufferProvider.cs.meta new file mode 100644 index 0000000..7cb2802 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/Camera/_MockFrameBufferProvider.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 67d2241b77cf4ca8927a7372ccada34f +timeCreated: 1585164499 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/IMockARSession.cs b/Assets/ARDK/VirtualStudio/AR/IMockARSession.cs new file mode 100644 index 0000000..954c244 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/IMockARSession.cs @@ -0,0 +1,20 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.Anchors; +using Niantic.ARDK.AR.SLAM; + +namespace Niantic.ARDK.VirtualStudio.AR +{ + public interface IMockARSession: + IARSession + { + void UpdateFrame(IARFrame frame); + + void UpdateAnchor(IARAnchor anchor); + void MergeAnchors(IARAnchor parent, IARAnchor[] children); + + void AddMap(IARMap map); + void UpdateMap(IARMap map); + } +} diff --git a/Assets/ARDK/VirtualStudio/AR/IMockARSession.cs.meta b/Assets/ARDK/VirtualStudio/AR/IMockARSession.cs.meta new file mode 100644 index 0000000..a755ddf --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/IMockARSession.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 82af7d171966405ebe21d3a4f009e483 +timeCreated: 1597955878 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/Networking.meta b/Assets/ARDK/VirtualStudio/AR/Networking.meta new file mode 100644 index 0000000..993ae87 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/Networking.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: b99b43518c934516bb6da87219f521f1 +timeCreated: 1579737987 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/Networking/IMockARNetworking.cs b/Assets/ARDK/VirtualStudio/AR/Networking/IMockARNetworking.cs new file mode 100644 index 0000000..23717b0 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/Networking/IMockARNetworking.cs @@ -0,0 +1,13 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.AR.Networking; +using UnityEngine; + +namespace Niantic.ARDK.VirtualStudio.AR.Networking.Mock +{ + public interface IMockARNetworking: + IARNetworking + { + void BroadcastPose(Matrix4x4 pose, float deltaTime); + } +} \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/Networking/IMockARNetworking.cs.meta b/Assets/ARDK/VirtualStudio/AR/Networking/IMockARNetworking.cs.meta new file mode 100644 index 0000000..aa82e50 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/Networking/IMockARNetworking.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a23e25c49edc451f89b74e1e54d7792e +timeCreated: 1607366466 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/Networking/_IEditorARNetworkingSessionMediator.cs b/Assets/ARDK/VirtualStudio/AR/Networking/_IEditorARNetworkingSessionMediator.cs new file mode 100644 index 0000000..6fca180 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/Networking/_IEditorARNetworkingSessionMediator.cs @@ -0,0 +1,22 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.Networking; +using Niantic.ARDK.Utilities.Collections; +using Niantic.ARDK.VirtualStudio.AR.Networking.Mock; + +namespace Niantic.ARDK.VirtualStudio.AR.Networking +{ + internal interface _IEditorARNetworkingSessionMediator: + ISessionMediator + { + _MockARNetworking CreateNonLocalSession(Guid stageIdentifier); + + IReadOnlyCollection<_MockARNetworking> GetConnectedSessions(Guid stageIdentifier); + + _MockARNetworking GetSession(Guid stageIdentifier); + } +} \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/Networking/_IEditorARNetworkingSessionMediator.cs.meta b/Assets/ARDK/VirtualStudio/AR/Networking/_IEditorARNetworkingSessionMediator.cs.meta new file mode 100644 index 0000000..cb5b0de --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/Networking/_IEditorARNetworkingSessionMediator.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3aacc6d7eebf4b49a85a51cbf0821b2e +timeCreated: 1606940399 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/Networking/_MockARNetworking.cs b/Assets/ARDK/VirtualStudio/AR/Networking/_MockARNetworking.cs new file mode 100644 index 0000000..090766f --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/Networking/_MockARNetworking.cs @@ -0,0 +1,305 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.Networking; +using Niantic.ARDK.AR.Networking.ARNetworkingEventArgs; +using Niantic.ARDK.Networking; +using Niantic.ARDK.Networking.MultipeerNetworkingEventArgs; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Collections; +using Niantic.ARDK.Utilities.Logging; +using Niantic.ARDK.Utilities.Marker; + +using UnityEngine; + +namespace Niantic.ARDK.VirtualStudio.AR.Networking.Mock +{ + internal sealed class _MockARNetworking: + IMockARNetworking + { + private readonly _IVirtualStudioManager _virtualStudioManager; + + private bool _isInitialized; + private bool _isDisposed; + + // milliseconds + private long _poseLatency = 17; // roughly 60 times per second + private float _timeSinceLastPoseSend; + + private bool _isPoseBroadcastingEnabled = true; + + public _MockARNetworking + ( + IARSession arSession, + IMultipeerNetworking networking, + _IVirtualStudioManager virtualStudioMaster + ) + { + ARSession = arSession; + Networking = networking; + _virtualStudioManager = virtualStudioMaster; + + _readOnlyLatestPeerPoses = new _ReadOnlyDictionary(_latestPeerPoses); + _readOnlyLatestPeerStates = new _ReadOnlyDictionary(_latestPeerStates); + + Networking.PeerAdded += _HandleNetworkingAddedPeer; + Networking.PeerRemoved += _HandleNetworkingRemovedPeer; + Networking.Connected += _HandleNetworkingConnected; + Networking.Disconnected += _HandleNetworkingDisconnected; + + Networking.Deinitialized += (_) => Dispose(); + ARSession.Deinitialized += (_) => Dispose(); + + _isInitialized = true; + + ARNetworkingFactory.ARNetworkingInitialized += OnARNetworkingInitialized; + ARNetworkingFactory.NonLocalARNetworkingInitialized += OnARNetworkingInitialized; + } + + private void OnARNetworkingInitialized(AnyARNetworkingInitializedArgs args) + { + if (args.ARNetworking.ARSession.StageIdentifier == ARSession.StageIdentifier) + { + ARNetworkingFactory.ARNetworkingInitialized -= OnARNetworkingInitialized; + ARNetworkingFactory.NonLocalARNetworkingInitialized -= OnARNetworkingInitialized; + } + } + + /// + public void Dispose() + { + if (_isDisposed) + return; + + _isDisposed = true; + + if (_isInitialized) + { + var deinitializing = Deinitialized; + if (deinitializing != null) + { + var args = new ARNetworkingDeinitializedArgs(); + deinitializing(args); + } + } + } + + /// + public IMultipeerNetworking Networking { get; private set; } + + /// + public IARSession ARSession { get; private set; } + + /// + public PeerState LocalPeerState { get; private set; } + + private readonly Dictionary _latestPeerPoses = + new Dictionary(); + + private _ReadOnlyDictionary _readOnlyLatestPeerPoses; + + /// + public IReadOnlyDictionary LatestPeerPoses + { + get { return _readOnlyLatestPeerPoses; } + } + + private readonly Dictionary _latestPeerStates = + new Dictionary(); + + private _ReadOnlyDictionary _readOnlyLatestPeerStates; + + /// + public IReadOnlyDictionary LatestPeerStates + { + get { return _readOnlyLatestPeerStates; } + } + + /// + public void EnablePoseBroadcasting() + { + _isPoseBroadcastingEnabled = true; + } + + /// + public void DisablePoseBroadcasting() + { + _isPoseBroadcastingEnabled = false; + } + + /// + public void SetTargetPoseLatency(long targetPoseLatency) + { + _poseLatency = targetPoseLatency; + } + + private void _HandleNetworkingAddedPeer(PeerAddedArgs args) + { + var peer = args.Peer; + + _latestPeerPoses.Add(peer, Matrix4x4.identity); + _latestPeerStates.Add(peer, PeerState.Unknown); + } + + private void _HandleNetworkingRemovedPeer(PeerRemovedArgs args) + { + var peer = args.Peer; + if (peer.Equals(Networking.Self)) + { + LocalPeerState = PeerState.Unknown; + _latestPeerPoses.Clear(); + _latestPeerStates.Clear(); + } + else + { + _latestPeerPoses.Remove(peer); + _latestPeerStates.Remove(peer); + } + } + + private void _HandleNetworkingConnected(ConnectedArgs args) + { + LocalPeerState = PeerState.Unknown; + _latestPeerStates.Add(args.Self, PeerState.Unknown); + + // Needs to happen on next frame, so that BroadcastState + // happens after all networking connected callbacks are invoked. + _CallbackQueue.QueueCallback + ( + () => + { + if (!_isDisposed) + BroadcastState(PeerState.WaitingForLocalizationData); + } + ); + } + + private void _HandleNetworkingDisconnected(DisconnectedArgs args) + { + LocalPeerState = PeerState.Unknown; + _latestPeerPoses.Clear(); + } + + public void BroadcastPose(Matrix4x4 pose, float deltaTime) + { + if (!_isPoseBroadcastingEnabled) + return; + + _timeSinceLastPoseSend += deltaTime * 1000f; + if (_timeSinceLastPoseSend < _poseLatency) + return; + + var mediator = _virtualStudioManager.ArNetworkingMediator; + var receivers = mediator.GetConnectedSessions(Networking.StageIdentifier); + + foreach (var receiver in receivers) + { + // Skip broadcasting to self + if (receiver.Networking.StageIdentifier == Networking.StageIdentifier) + continue; + + receiver._ReceivePoseFromPeer(pose, Networking.Self); + } + + _timeSinceLastPoseSend = 0; + } + + private void _ReceivePoseFromPeer(Matrix4x4 pose, IPeer peer) + { + _latestPeerPoses[peer] = pose; + + var peerPoseReceived = PeerPoseReceived; + if (peerPoseReceived != null) + { + var args = new PeerPoseReceivedArgs(peer, pose); + peerPoseReceived(args); + } + } + + public void BroadcastState(PeerState state) + { + PeerState currState; + if (_latestPeerStates.TryGetValue(Networking.Self, out currState) && currState == state) + { + ARLog._WarnFormat("Already in state {0}, will not broadcast change.", false, state); + return; + } + + var mediator = _virtualStudioManager.ArNetworkingMediator; + var receivers = mediator.GetConnectedSessions(Networking.StageIdentifier); + + foreach (var receiver in receivers) + { + var mockReceiver = receiver; + if (mockReceiver != null) + mockReceiver._ReceiveStateFromPeer(state, Networking.Self); + } + } + + private void _ReceiveStateFromPeer(PeerState state, IPeer peer) + { + _latestPeerStates[peer] = state; + + if (peer.Equals(Networking.Self)) + LocalPeerState = state; + + var peerStateReceived = _peerStateReceived; + if (peerStateReceived != null) + { + var args = new PeerStateReceivedArgs(peer, state); + peerStateReceived(args); + } + } + + private ArdkEventHandler _peerStateReceived; + + /// + public event ArdkEventHandler PeerStateReceived + { + add + { + _peerStateReceived += value; + + foreach (var pair in _latestPeerStates) + { + if (pair.Value != PeerState.Unknown) + { + var args = new PeerStateReceivedArgs(pair.Key, pair.Value); + value(args); + } + } + } + remove + { + _peerStateReceived -= value; + } + } + + /// + public event ArdkEventHandler PeerPoseReceived; + + /// + public event ArdkEventHandler Deinitialized; + + /// + void IARNetworking.InitializeForMarkerScanning(Vector3[] markerPointLocations) + { + throw new NotSupportedException(); + } + + /// + void IARNetworking.ScanForMarker + ( + MarkerScanOption options, + Action gotResult, + IMarkerScanner scanner, + IMetadataSerializer deserializer + ) + { + throw new NotSupportedException(); + } + } +} diff --git a/Assets/ARDK/VirtualStudio/AR/Networking/_MockARNetworking.cs.meta b/Assets/ARDK/VirtualStudio/AR/Networking/_MockARNetworking.cs.meta new file mode 100644 index 0000000..2796225 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/Networking/_MockARNetworking.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 50a232b86ca242c8beeeb7ee5426cb9d +timeCreated: 1579050466 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/Networking/_MockARNetworkingSessionsMediator.cs b/Assets/ARDK/VirtualStudio/AR/Networking/_MockARNetworkingSessionsMediator.cs new file mode 100644 index 0000000..2d8c558 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/Networking/_MockARNetworkingSessionsMediator.cs @@ -0,0 +1,113 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Linq; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.Networking; +using Niantic.ARDK.AR.Networking.ARNetworkingEventArgs; +using Niantic.ARDK.Utilities.Collections; +using Niantic.ARDK.Utilities.Logging; +using Niantic.ARDK.VirtualStudio.AR.Networking.Mock; + +using UnityEngine; + +namespace Niantic.ARDK.VirtualStudio.AR.Networking +{ + internal sealed class _MockARNetworkingSessionsMediator: + _IEditorARNetworkingSessionMediator + { + private readonly Dictionary _stageIdentifierToSession = + new Dictionary(); + + private _IVirtualStudioManager _virtualStudioManager; + + public _MockARNetworkingSessionsMediator(_IVirtualStudioManager virtualStudioMaster) + { + _virtualStudioManager = virtualStudioMaster; + + ARNetworkingFactory.ARNetworkingInitialized += HandleAnyInitialized; + ARNetworkingFactory.NonLocalARNetworkingInitialized += HandleAnyInitialized; + } + + ~_MockARNetworkingSessionsMediator() + { + ARLog._Error("_MockARNetworkingSessionsMediator was not correctly disposed."); + } + + public void Dispose() + { + GC.SuppressFinalize(this); + + foreach (var session in _stageIdentifierToSession.Values.ToArray()) + session.Dispose(); + + ARNetworkingFactory.ARNetworkingInitialized -= HandleAnyInitialized; + ARNetworkingFactory.NonLocalARNetworkingInitialized -= HandleAnyInitialized; + } + + public _MockARNetworking CreateNonLocalSession(Guid stageIdentifier) + { + var networking = _virtualStudioManager.MultipeerMediator.GetSession(stageIdentifier); + var arSession = _virtualStudioManager.ArSessionMediator.GetSession(stageIdentifier); + + var arNetworking = + ARNetworkingFactory._CreateVirtualStudioManagedARNetworking + ( + arSession, + networking, + _virtualStudioManager, + isLocal: false + ); + + return (_MockARNetworking) arNetworking; + } + + public _MockARNetworking GetSession(Guid stageIdentifier) + { + return HasSession(stageIdentifier) ? _stageIdentifierToSession[stageIdentifier] : null; + } + + public IReadOnlyCollection<_MockARNetworking> GetConnectedSessions(Guid stageIdentifier) + { + var connectedARNetworkings = new HashSet<_MockARNetworking>(); + var readonlyARNetworkings = connectedARNetworkings.AsArdkReadOnly(); + + if (GetSession(stageIdentifier).Networking.IsConnected) + { + var connectedNetworkings = + _virtualStudioManager.MultipeerMediator.GetConnectedSessions(stageIdentifier); + + if (connectedNetworkings != null) + foreach (var connectedNetworking in connectedNetworkings) + connectedARNetworkings.Add(GetSession(connectedNetworking.StageIdentifier)); + } + + return readonlyARNetworkings; + } + + public bool HasSession(Guid stageIdentifier) + { + return _stageIdentifierToSession.ContainsKey(stageIdentifier); + } + + private void HandleAnyInitialized(AnyARNetworkingInitializedArgs args) + { + var mockARNetworking = args.ARNetworking as _MockARNetworking; + if (mockARNetworking == null) + { + ARLog._Error + ( + "While VirtualStudio is running mock AR networks, only other mock ARNetworking " + + "instances can be initialized." + ); + return; + } + + var stageIdentifier = mockARNetworking.ARSession.StageIdentifier; + mockARNetworking.Deinitialized += (_) => _stageIdentifierToSession.Remove(stageIdentifier); + _stageIdentifierToSession.Add(stageIdentifier, mockARNetworking); + } + } +} diff --git a/Assets/ARDK/VirtualStudio/AR/Networking/_MockARNetworkingSessionsMediator.cs.meta b/Assets/ARDK/VirtualStudio/AR/Networking/_MockARNetworkingSessionsMediator.cs.meta new file mode 100644 index 0000000..32503e8 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/Networking/_MockARNetworkingSessionsMediator.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a2f06690d29f4891b52ee747b3cd65b9 +timeCreated: 1579731858 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/Networking/_RemoteEditorARNetworking.cs b/Assets/ARDK/VirtualStudio/AR/Networking/_RemoteEditorARNetworking.cs new file mode 100644 index 0000000..236fa2a --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/Networking/_RemoteEditorARNetworking.cs @@ -0,0 +1,273 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.Networking; +using Niantic.ARDK.AR.Networking.ARNetworkingEventArgs; +using Niantic.ARDK.Networking; +using Niantic.ARDK.Networking.MultipeerNetworkingEventArgs; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Collections; +using Niantic.ARDK.Utilities.Logging; +using Niantic.ARDK.Utilities.Marker; +using Niantic.ARDK.VirtualStudio.Remote.Data; + +using UnityEngine; + +namespace Niantic.ARDK.VirtualStudio.Remote +{ + /// + /// AR networking that will communicate with a ARDK's remote application. + /// + internal sealed class _RemoteEditorARNetworking: + IARNetworking + { + private bool _isInitialized; + private bool _isDisposed; + + internal _RemoteEditorARNetworking(IARSession arSession, IMultipeerNetworking networking) + { + ARSession = arSession; + Networking = networking; + + _RegisterMessageHandlers(); + _EasyConnection.Send + ( + new ARNetworkingInitMessage + { + StageIdentifier = arSession.StageIdentifier, + ConstructFromExistingNetworking = true + }, + TransportType.ReliableOrdered + ); + + _readOnlyLatestPeerPoses = new _ReadOnlyDictionary(_latestPeerPoses); + _readOnlyLatestPeerStates = new _ReadOnlyDictionary(_latestPeerStates); + + Networking.PeerAdded += _HandleNetworkingAddedPeer; + Networking.PeerRemoved += _HandleNetworkingRemovedPeer; + Networking.Disconnected += _HandleNetworkingDisconnected; + + _isInitialized = true; + } + + ~_RemoteEditorARNetworking() + { + ARLog._Error + ( + "_RemoteEditorARNetworking should be destroyed by an explicit call to Dispose()." + ); + } + + /// + public void Dispose() + { + if (_isDisposed) + return; + + GC.SuppressFinalize(this); + _isDisposed = true; + + if (_isInitialized) + { + var deinitializing = Deinitialized; + if (deinitializing != null) + { + var args = new ARNetworkingDeinitializedArgs(); + deinitializing(args); + } + } + + if (_RemoteConnection.IsConnected) + _EasyConnection.Send(new ARNetworkingDestroyMessage(), TransportType.ReliableOrdered); + else + _HandleNetworkingAboutToBeDestroyed(null); + } + + /// + public IMultipeerNetworking Networking { get; private set; } + + /// + public IARSession ARSession { get; private set; } + + /// + public PeerState LocalPeerState { get; private set; } + + private readonly Dictionary _latestPeerPoses = + new Dictionary(); + + private _ReadOnlyDictionary _readOnlyLatestPeerPoses; + + /// + public IReadOnlyDictionary LatestPeerPoses + { + get { return _readOnlyLatestPeerPoses; } + } + + private readonly Dictionary _latestPeerStates = + new Dictionary(); + + private _ReadOnlyDictionary _readOnlyLatestPeerStates; + + /// + public IReadOnlyDictionary LatestPeerStates + { + get { return _readOnlyLatestPeerStates; } + } + + private void _RegisterMessageHandlers() + { + _EasyConnection.Register + ( + _HandleDidReceiveStateFromPeerMessage + ); + + _EasyConnection.Register + ( + _HandleDidReceivePoseFromPeerMessage + ); + + _EasyConnection.Register + ( + _HandleNetworkingAboutToBeDestroyed + ); + } + + private void _HandleDidReceiveStateFromPeerMessage + ( + ARNetworkingPeerStateReceivedMessage message + ) + { + var peer = _Peer.FromIdentifier(message.PeerIdentifier); + var state = message.PeerState; + + _latestPeerStates[peer] = state; + + if (peer.Equals(Networking.Self)) + LocalPeerState = state; + + var peerStateReceived = _peerStateReceived; + if (peerStateReceived != null) + { + var args = new PeerStateReceivedArgs(peer, state); + peerStateReceived(args); + } + } + + private void _HandleDidReceivePoseFromPeerMessage + ( + ARNetworkingPeerPoseReceivedMessage message + ) + { + var peer = _Peer.FromIdentifier(message.PeerIdentifier); + var pose = message.Pose; + + _latestPeerPoses[peer] = pose; + + var peerPoseReceived = PeerPoseReceived; + if (peerPoseReceived != null) + { + var args = new PeerPoseReceivedArgs(peer, pose); + peerPoseReceived(args); + } + } + + private void _HandleNetworkingAboutToBeDestroyed(ARNetworkingDeinitializedMessage message) + { + _EasyConnection.Unregister(); + Dispose(); + } + + private void _HandleNetworkingAddedPeer(PeerAddedArgs args) + { + var peer = args.Peer; + + _latestPeerPoses.Add(peer, Matrix4x4.identity); + _latestPeerStates.Add(peer, PeerState.Unknown); + } + + private void _HandleNetworkingRemovedPeer(PeerRemovedArgs args) + { + var peer = args.Peer; + if (peer.Equals(Networking.Self)) + { + LocalPeerState = PeerState.Unknown; + _latestPeerPoses.Clear(); + _latestPeerStates.Clear(); + } + else + { + _latestPeerPoses.Remove(peer); + _latestPeerStates.Remove(peer); + } + } + + private void _HandleNetworkingDisconnected(DisconnectedArgs args) + { + LocalPeerState = PeerState.Unknown; + _latestPeerPoses.Clear(); + } + + /// + public event ArdkEventHandler Deinitialized; + + private ArdkEventHandler _peerStateReceived; + + /// + public event ArdkEventHandler PeerStateReceived + { + add + { + _peerStateReceived += value; + + foreach (var pair in _latestPeerStates) + { + var args = new PeerStateReceivedArgs(pair.Key, pair.Value); + value(args); + } + } + remove + { + _peerStateReceived -= value; + } + } + + /// + public event ArdkEventHandler PeerPoseReceived; + + void IARNetworking.EnablePoseBroadcasting() + { + throw new NotSupportedException(); + } + + void IARNetworking.DisablePoseBroadcasting() + { + throw new NotSupportedException(); + } + + void IARNetworking.SetTargetPoseLatency(long targetPoseLatency) + { + throw new NotSupportedException(); + } + + /// + void IARNetworking.InitializeForMarkerScanning(Vector3[] markerPointLocations) + { + throw new NotSupportedException(); + } + + /// + void IARNetworking.ScanForMarker + ( + MarkerScanOption options, + Action gotResult, + IMarkerScanner scanner, + IMetadataSerializer deserializer + ) + { + throw new NotSupportedException(); + } + } +} diff --git a/Assets/ARDK/VirtualStudio/AR/Networking/_RemoteEditorARNetworking.cs.meta b/Assets/ARDK/VirtualStudio/AR/Networking/_RemoteEditorARNetworking.cs.meta new file mode 100644 index 0000000..adf8326 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/Networking/_RemoteEditorARNetworking.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3baf7a26433247a8a3320e5afc3658dc +timeCreated: 1544649564 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/SceneComponents.meta b/Assets/ARDK/VirtualStudio/AR/SceneComponents.meta new file mode 100644 index 0000000..86835a6 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/SceneComponents.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2c320c3bee204d2da237d2643e0e2a1d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockAnchorBase.cs b/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockAnchorBase.cs new file mode 100644 index 0000000..4d1d2c0 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockAnchorBase.cs @@ -0,0 +1,60 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.Anchors; + +namespace Niantic.ARDK.VirtualStudio.AR.Mock +{ + /// Base class for mocked anchors. Mocked anchors are only detected in the local ARSession. + public abstract class MockAnchorBase: + MockDetectableBase + { + private HashSet _discoveredInSessions = new HashSet(); + + internal abstract void CreateAndAddAnchorToSession(_IMockARSession arSession); + + internal abstract void RemoveAnchorFromSession(_IMockARSession arSession); + + protected abstract IARAnchor AnchorData { get; } + + protected abstract bool UpdateAnchorData(); + + internal sealed override void BeDiscovered(_IMockARSession arSession, bool isLocal) + { + if (!_discoveredInSessions.Contains(arSession.StageIdentifier)) + { + _discoveredInSessions.Add(arSession.StageIdentifier); + CreateAndAddAnchorToSession(arSession); + } + } + + internal override void OnSessionRanAgain(_IMockARSession arSession) + { + if ((arSession.RunOptions & ARSessionRunOptions.RemoveExistingAnchors) != 0) + { + _discoveredInSessions.Remove(arSession.StageIdentifier); + RemoveAnchorFromSession(arSession); + } + } + + protected virtual void Update() + { + // Check every frame to see if anything has changed in this anchor's transform. + + if (AnchorData != null && transform.hasChanged) + { + // If something has changed, recalculate and apply the anchor data + // to reflect the current transform state. + if (UpdateAnchorData()) + { + // Now that the anchor data has been updated, notify the session + // that an update has occurred to this anchor + UpdateAnchorInSessions(AnchorData); + } + } + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockAnchorBase.cs.meta b/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockAnchorBase.cs.meta new file mode 100644 index 0000000..dbee421 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockAnchorBase.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3f66b756bf31448aae9e7a06aac21b37 +timeCreated: 1582655538 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockDetectableBase.cs b/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockDetectableBase.cs new file mode 100644 index 0000000..8e36b2c --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockDetectableBase.cs @@ -0,0 +1,202 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.Collections; +using System.Collections.Generic; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.Anchors; +using Niantic.ARDK.AR.ARSessionEventArgs; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; + +namespace Niantic.ARDK.VirtualStudio.AR.Mock +{ + public abstract class MockDetectableBase: + MonoBehaviour + { + internal interface _ISessionHelper + { + _IMockARSession Session { get; } + bool IsLocal { get; } + + void Dispose(); + } + + private sealed class _SessionHelper : + _ISessionHelper + { + public _IMockARSession Session { get; } + public bool IsLocal { get; } + + private readonly MockDetectableBase _owner; + private bool _ran; + + private Coroutine _discoveryCoroutine; + + internal _SessionHelper(MockDetectableBase owner, _IMockARSession session, bool isLocal) + { + _owner = owner; + Session = session; + IsLocal = isLocal; + + Session.Ran += _OnSessionRan; + Session.Paused += OnSessionPaused; + Session.Deinitialized += OnSessionDeinitialized; + } + + public void Dispose() + { + Session.Ran -= _OnSessionRan; + Session.Paused -= OnSessionPaused; + } + + private void StopDiscoveryCoroutine() + { + if (_discoveryCoroutine != null) + { + if (_owner != null) + _owner.StopCoroutine(_discoveryCoroutine); + + _discoveryCoroutine = null; + } + } + + private void _OnSessionRan(ARSessionRanArgs args) + { + if (_ran) + _owner.OnSessionRanAgain(Session); + + _ran = true; + + StopDiscoveryCoroutine(); + _discoveryCoroutine = _owner.StartCoroutine(nameof(WaitToBeDiscovered), this); + } + + private void OnSessionPaused(ARSessionPausedArgs args) + { + StopDiscoveryCoroutine(); + } + + private void OnSessionDeinitialized(ARSessionDeinitializedArgs args) + { + StopDiscoveryCoroutine(); + } + } + + private readonly object _activeSessionsLock = new object(); + + private Dictionary _activeSessionHelpers = + new Dictionary(_ReferenceComparer.Instance); + + [SerializeField] + protected float _timeToDiscovery = 2.0f; + + // Method provided for implementations to override for initialization steps, + // should be used instead of Awake or Start. + // @returns True if initialization was successful + protected virtual bool Initialize() + { + return true; + } + + // Method called `_timeToDiscovery` seconds after the specified arSession is initialized. + internal abstract void BeDiscovered(_IMockARSession arSession, bool sessionIsLocal); + + internal abstract void OnSessionRanAgain(_IMockARSession arSession); + + internal virtual _ISessionHelper _CreateSessionHelper(_IMockARSession mockSession, bool isLocal) + { + return new _SessionHelper(this, mockSession, isLocal); + } + + internal IEnumerator WaitToBeDiscovered(_ISessionHelper sessionHelper) + { + // Debug.LogFormat + // ( + // "{0}: Waiting to be discovered by ARSession {1}", + // gameObject.name, + // sessionHelper.Session.StageIdentifier + // ); + + if (_timeToDiscovery > 0) + yield return new WaitForSeconds(_timeToDiscovery); + + BeDiscovered(sessionHelper.Session, sessionHelper.IsLocal); + } + + protected void UpdateAnchorInSessions(IARAnchor anchorData) + { + lock (_activeSessionsLock) + { + foreach (var helper in _activeSessionHelpers.Values) + { + helper.Session.UpdateAnchor(anchorData); + } + } + } + + // Declared as private method here to prevent implementations from overriding + private void Awake() + { + } + + // Uses Start instead of Awake to give PlayMode tests a frame to initialize variables + private void Start() + { + if (!gameObject.activeSelf) + return; + + if (!Initialize()) + return; + + ARSessionFactory.SessionInitialized += OnSessionInitialized; + ARSessionFactory._NonLocalSessionInitialized += OnSessionInitialized; + } + + private void OnDestroy() + { + ARSessionFactory.SessionInitialized -= OnSessionInitialized; + ARSessionFactory._NonLocalSessionInitialized -= OnSessionInitialized; + + Dictionary helpers; + lock (_activeSessionsLock) + { + helpers = _activeSessionHelpers; + _activeSessionHelpers = null; + } + + foreach (var helper in helpers.Values) + helper.Dispose(); + } + + private void OnSessionInitialized(AnyARSessionInitializedArgs args) + { + var session = args.Session; + + if (!(session is _IMockARSession mockSession)) + { + ARLog._Warn("Mock objects can only be detected by mock ARSessions."); + return; + } + + var helper = _CreateSessionHelper(mockSession, args._IsLocal); + lock (_activeSessionsLock) + _activeSessionHelpers.Add(session, helper); + + session.Deinitialized += + (_) => + { + // When the session dies, we only need to remove it from our session list, no need + // to "dispose" the helper, as no more events will come from the session. + lock (_activeSessionsLock) + { + var helpers = _activeSessionHelpers; + if (helpers != null) + helpers.Remove(session); + } + }; + } + } +} diff --git a/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockDetectableBase.cs.meta b/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockDetectableBase.cs.meta new file mode 100644 index 0000000..6162b62 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockDetectableBase.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3491eda864924d05bd644d9f1652008b +timeCreated: 1582680301 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockImageAnchor.cs b/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockImageAnchor.cs new file mode 100644 index 0000000..8fefba9 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockImageAnchor.cs @@ -0,0 +1,358 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; + +using Niantic.ARDK.AR.Anchors; +using Niantic.ARDK.AR.ReferenceImage; +using Niantic.ARDK.Utilities.Logging; + +#if UNITY_EDITOR +using UnityEditor; +#endif + +using UnityEngine; + +namespace Niantic.ARDK.VirtualStudio.AR.Mock +{ + [ExecuteInEditMode] + public sealed class MockImageAnchor: + MockAnchorBase, ISerializationCallbackReceiver + { + [SerializeField] + private string _name; + + [SerializeField] + private Orientation _orientation; + + [SerializeField] + private Texture2D _image; + + private Texture2D _currImage; + private bool _imageDirty; + + private readonly Vector3[] _defaultVertices = + { + new Vector3(-0.5f, 0, -0.5f), // BL + new Vector3(0.5f, 0, -0.5f), // BR + new Vector3(-0.5f, 0, 0.5f), // TL + new Vector3(0.5f, 0, 0.5f) // TR + }; + + // Mesh is built directly in this class to make sure aspect ratio is the same as the image's. + private Vector3[] _vertices; + + private readonly int[] _triangles = { 0, 2, 1, 2, 3, 1 }; + + private Vector2[] _uv = + { + new Vector2(0, 0), + new Vector2(1, 0), + new Vector2(0, 1), + new Vector2(1, 1) + }; + + private _SerializableARImageAnchor _anchorData; + + protected override IARAnchor AnchorData + { + get => _anchorData; + } + + private MeshFilter _meshFilter; + private MeshFilter _MeshFilter + { + get + { + if (_meshFilter == null) + _meshFilter = GetComponent(); + + return _meshFilter; + } + } + + private MeshRenderer _meshRenderer; + private MeshRenderer _MeshRenderer + { + get + { + if (_meshRenderer == null) + _meshRenderer = GetComponent(); + + return _meshRenderer; + } + } + + protected override bool Initialize() + { + Build(); + UpdateImageDisplay(); + + return base.Initialize(); + } + + protected override void Update() + { + if (_imageDirty) + UpdateImageDisplay(); + } + + internal override void CreateAndAddAnchorToSession(_IMockARSession arSession) + { + if (_anchorData == null) + { + // Initialize the anchor data with initial values such as + // a new guid, non-transform related values, etc + + var imageAsBytes = _image.GetRawTextureData(); + + var vertices = GetComponent().sharedMesh.vertices; + var botLeft = transform.localToWorldMatrix * vertices[0]; + var topRight = transform.localToWorldMatrix * vertices[3]; + var imageWidth = Mathf.Abs(botLeft.x - topRight.x); + var imageHeight = Mathf.Abs(botLeft.y - topRight.y); + + var referenceImage = + (_SerializableARReferenceImage)ARReferenceImageFactory.Create + ( + _name, + imageAsBytes, + imageAsBytes.Length, + imageWidth, + _orientation + ); + + referenceImage.PhysicalSize = new Vector2(imageWidth, imageHeight); + + _anchorData = + new _SerializableARImageAnchor + ( + new Matrix4x4(), + Guid.NewGuid(), + referenceImage + ); + + // Transform value will be set here + UpdateAnchorData(); + + // Value starts off as true, so needs to be set to false here + transform.hasChanged = false; + } + + if (!arSession.AddAnchor(_anchorData)) + { + ARLog._WarnFormat + ( + "Image anchor for {0} cannot be detected. If that is unintended, make sure that a " + + "reference image with the same name as this anchor's was added to the active " + + "ARWorldTrackingConfiguration's DetectionImages set.", + false, + gameObject.name + ); + + enabled = false; + } + } + + internal override void RemoveAnchorFromSession(_IMockARSession arSession) + { + arSession.RemoveAnchor(_anchorData); + } + + protected override bool UpdateAnchorData() + { + // Note: transform.hasChanged is susceptible to other logic changing this flag's value + // but for the time being, this is also the most straightforward approach for detecting + // changes to this GameObject's transform component + if (_anchorData == null || !transform.hasChanged) + return false; + + _anchorData.Transform = + Matrix4x4.TRS + ( + transform.position, + transform.rotation, + Vector3.one + ); + + transform.hasChanged = false; + return true; + } + +#if UNITY_EDITOR + private bool _created; + private void Reset() + { + if (!_created) + { + if (!CreateDialog()) + return; + } + + _created = true; + _vertices = null; + Build(); + + _orientation = Orientation.Up; + + var parent = transform.parent; + transform.localRotation = Quaternion.Euler(-90, 0, 0); + + // Unparent from everything to set scale to [1, 1, 1] + transform.SetParent(null, true); + transform.localScale = Vector3.one; + + // Reparent while keeping the scale the same. + if (parent != null) + transform.SetParent(parent, true); + } + + private bool CreateDialog() + { + var numComponents = GetComponents().Length; + var hasMeshFilter = GetComponent() != null; + var hasMeshRenderer = GetComponent() != null; + + if (hasMeshFilter || hasMeshRenderer || numComponents > 2) + { + var goName = gameObject.name; + + string msg; + if (hasMeshFilter || hasMeshRenderer) + { + msg = + "A MeshFilter or MeshRenderer component already exists on this GameObject. Adding a " + + "MockImageAnchor will alter their properties."; + } + else + { + msg = "Adding a MockImageAnchor will alter this GameObject's transform."; + } + + var option = EditorUtility.DisplayDialogComplex + ( + $"Create MockImageAnchor on {goName}?", + msg, + "Create", + "Cancel", + "Create on new child GameObject" + ); + + switch (option) + { + // Create + case 0: + return true; + + // Cancel + case 1: + DestroyImmediate(this); + return false; + + // Create on new child + case 2: + var child = new GameObject(); + child.transform.SetParent(transform, false); + DestroyImmediate(this); + child.AddComponent(); + + Undo.RegisterCreatedObjectUndo(child, "Create MockImageAnchor"); + Selection.activeObject = child; + return false; + } + } + + return true; + } + + private void OnValidate() + { + if (_image != _currImage) + _imageDirty = true; + } +#endif + + // OnBeforeSerialize is called often while in Edit Mode, essentially whenever it's + // open in the Inspector view, but it's also only called after Reset when a component + // is first added to a GameObject. That makes it perfect to use to check if Reset is being + // invoked from a a pre-existing or new component. + public void OnBeforeSerialize() + { +#if UNITY_EDITOR + _created = true; +#endif + } + + public void OnAfterDeserialize() + { + } + + [ContextMenu("Update Display")] + private void UpdateImageDisplay() + { + _currImage = _image; + + if (_currImage == null) + { + UpdateVertices(0.5f, 0.5f); + return; + } + + _MeshRenderer.sharedMaterial.mainTexture = _currImage; + + // Match aspect ratio, but keep longest side to 1m so importing a huge image + // isn't annoying. + var width = (float)_currImage.width; + var height = (float)_currImage.height; + + var mockWidth = 1f; + var mockHeight = 1f; + + if (width > height) + mockHeight = height / width; + else if (width < height) + mockWidth = width / height; + + UpdateVertices(mockWidth, mockHeight); + + _imageDirty = false; + } + + private void Build() + { + var mesh = new Mesh(); + + if (_MeshFilter == null) + gameObject.AddComponent(); + + _MeshFilter.mesh = mesh; + + mesh.vertices = (_vertices == null || _vertices.Length == 0) ? _defaultVertices : _vertices; + mesh.uv = _uv; + mesh.triangles = _triangles; + + mesh.RecalculateNormals(); + mesh.RecalculateBounds(); + + + if (_MeshRenderer == null) + gameObject.AddComponent(); + + _MeshRenderer.material = new Material(Shader.Find("Unlit/Texture")); + } + + private void UpdateVertices(float width, float height) + { + var xExtent = width / 2; + var yExtent = height / 2; + + _vertices = new Vector3[] + { + new Vector3(-xExtent, 0, -yExtent), // BL + new Vector3(xExtent, 0, -yExtent), // BR + new Vector3(-xExtent, 0, yExtent), // TL + new Vector3(xExtent, 0, yExtent) // TR + }; + + _MeshFilter.sharedMesh.vertices = _vertices; + } + } +} diff --git a/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockImageAnchor.cs.meta b/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockImageAnchor.cs.meta new file mode 100644 index 0000000..5dcaec7 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockImageAnchor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 304c61c136de41519c9927f6668260e4 +timeCreated: 1645640624 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockMap.cs b/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockMap.cs new file mode 100644 index 0000000..261a541 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockMap.cs @@ -0,0 +1,85 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections; +using System.Collections.Generic; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.Networking; +using Niantic.ARDK.AR.SLAM; +using UnityEngine; + +namespace Niantic.ARDK.VirtualStudio.AR.Mock +{ + /// A map will be discovered at this location in TimeToDiscovery seconds after an ARSession + /// starts running. + /// + /// If the local peer is the host, that means the IARNetworking.PeerStateReceived event + /// will surface a change for the local peer for PeerState.WaitingForLocalizationData to + /// PeerState.Stable. + /// + /// Else, it will surface a for the local peer from PeerState.WaitingForLocalizationData to + /// PeerState.Localizing, and then another TimeToDiscovery seconds later, another PeerStateReceived + /// event will surface a change from PeerState.Localizing to PeerState.Stable. + /// + /// @note + /// Mock maps will only be discovered by the local player's session. To have more control over + /// surfacing PeerState changes, and/or to surface changes from non-local players, + /// use the MockPlayer.SetPeerState method or the Virtual Studio Editor Window's Mock controls. + public sealed class MockMap: + MockDetectableBase + { + private Guid _identifier = Guid.NewGuid(); + private HashSet _discoveredInSessions = new HashSet(); + + private MockPlayer _player; + + private Coroutine _stableCoroutine; + + internal override void BeDiscovered(_IMockARSession arSession, bool isLocal) + { + if (!isLocal || _discoveredInSessions.Contains(arSession.StageIdentifier)) + return; + + _discoveredInSessions.Add(arSession.StageIdentifier); + + var serialMap = + new _SerializableARMap + ( + _identifier, + 1.0f, + Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one) + ); + + arSession.AddMap(serialMap); + + _player = _VirtualStudioManager.Instance.LocalPlayer; + var networking = _player.Networking; + var isHost = networking.Self.Equals(networking.Host); + + if (isHost) + { + _player.SetPeerState(PeerState.Stable); + } + else + { + _player.SetPeerState(PeerState.Localizing); + Action secondChange = () => _player.SetPeerState(PeerState.Stable); + _stableCoroutine = StartCoroutine(nameof(WaitAndChangeStateAgain), secondChange); + } + } + + internal override void OnSessionRanAgain(_IMockARSession arSession) + { + // Nothing happens on device either. + } + + private IEnumerator WaitAndChangeStateAgain(Action secondChange) + { + if (_timeToDiscovery > 0) + yield return new WaitForSeconds(_timeToDiscovery); + + secondChange(); + } + } +} diff --git a/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockMap.cs.meta b/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockMap.cs.meta new file mode 100644 index 0000000..be08034 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockMap.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: eba9fec7434a4baf81377fef0bfdaf9a +timeCreated: 1582680102 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockMesh.cs b/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockMesh.cs new file mode 100644 index 0000000..1bebc33 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockMesh.cs @@ -0,0 +1,45 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.Mesh; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; + +namespace Niantic.ARDK.VirtualStudio.AR.Mock +{ + /// This script can load individual mesh files saved with Niantic.ARDK.Extensions.Meshing.MeshSaver + /// into the Unity Editor play mode. Use MockMeshSequence to load mesh sequences. + /// @note + /// If an ARSession is re-run with the RemoveExistingMesh option, this mesh will be + /// re-discovered in _timeToDiscovery seconds. + public sealed class MockMesh: + MockDetectableBase + { + /// _meshPath is the path to a single mesh file (mesh_*.bin) in the project. + [SerializeField] + private string _meshPath = null; + + internal override void BeDiscovered(_IMockARSession arSession, bool isLocal) + { + if (!isLocal) + return; + + ARLog._Debug("Will load the mesh @ " + _meshPath); + + var loadedMesh = new _FileARMeshData(_meshPath); + + arSession.UpdateMesh(loadedMesh); + } + + internal override void OnSessionRanAgain(_IMockARSession arSession) + { + if ((arSession.RunOptions & ARSessionRunOptions.RemoveExistingMesh) != 0) + { + arSession.UpdateMesh(null); + } + } + } +} diff --git a/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockMesh.cs.meta b/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockMesh.cs.meta new file mode 100644 index 0000000..9d1772e --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockMesh.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 96df25fcb12f4ab3933cfda2a757d0f3 +timeCreated: 1601682639 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockMeshSequence.cs b/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockMeshSequence.cs new file mode 100644 index 0000000..33aa50c --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockMeshSequence.cs @@ -0,0 +1,79 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.Mesh; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; + +namespace Niantic.ARDK.VirtualStudio.AR.Mock +{ + /// This script can load sequences mesh files saved with Niantic.ARDK.Extensions.Meshing.MeshSaver + /// into the Unity Editor play mode, loading all meshes inside a same directory, ordered by mesh + /// version number, one after the other at the pace specified by _updateInterval. + /// Use MockMesh to load single meshes. + public sealed class MockMeshSequence: + MockDetectableBase + { + /// _meshSequencePath is the path to a folder of mesh files (mesh_*.bin) in the project. + /// Individual mesh files will be loaded at fixed intervals, ordered by version number. + [SerializeField] + private string _meshSequencePath = null; + + /// _updateInterval is the desired time interval in seconds between mesh updates. + [SerializeField] + private float _updateInterval = 1.0f; + + internal override void BeDiscovered(_IMockARSession arSession, bool isLocal) + { + if (!isLocal) + return; + + ARLog._Debug("will load the meshes @ " + _meshSequencePath); + + string[] paths = GetMeshPaths(); + if (paths.Length > 0) + StartCoroutine(UpdateMeshes(arSession, paths)); + } + + private string[] GetMeshPaths() + { + string[] paths = Directory.GetFiles(_meshSequencePath, "mesh_*.bin"); + + // order paths by version number + paths = paths.OrderBy + ( + s => + int.Parse(Regex.Match(s, "\\d+", RegexOptions.RightToLeft).Value) + ) + .ToArray(); + + return paths; + } + + private IEnumerator UpdateMeshes(_IMockARSession arSession, string[] paths) + { + foreach (string meshPath in paths) + { + using (_FileARMeshData loadedMeshData = new _FileARMeshData(meshPath)) + arSession.UpdateMesh(loadedMeshData); + + yield return new WaitForSeconds(_updateInterval); + } + } + + internal override void OnSessionRanAgain(_IMockARSession arSession) + { + if ((arSession.RunOptions & ARSessionRunOptions.RemoveExistingMesh) != 0) + { + throw new NotImplementedException("Removing meshes is not yet supported in Virtual Studio"); + } + } + } +} diff --git a/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockMeshSequence.cs.meta b/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockMeshSequence.cs.meta new file mode 100644 index 0000000..7532583 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockMeshSequence.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a973c0ccaf364bfa9f35cafca6d1fb9e +timeCreated: 1615240986 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockPlaneAnchor.cs b/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockPlaneAnchor.cs new file mode 100644 index 0000000..ec5322e --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockPlaneAnchor.cs @@ -0,0 +1,193 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections; + +using Niantic.ARDK.AR.Anchors; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Logging; + +#if UNITY_EDITOR +using UnityEditor; +#endif + +using UnityEngine; + +using Matrix4x4 = UnityEngine.Matrix4x4; +using Quaternion = UnityEngine.Quaternion; +using Vector3 = UnityEngine.Vector3; + +namespace Niantic.ARDK.VirtualStudio.AR.Mock +{ + /// Attach this component to a GameObject in a mock environment scene and adjust the `center` and + /// `rotation` values so the Gizmo lies flat on top of the plane. A mock `IARPlaneAnchor` will + /// become discovered and raised through the `IARSession.AnchorsAdded` event after + /// '_timeToDiscovery' seconds have passed. + /// @note + /// Mock plane anchors are one-sided, so make sure to configure the `rotation` value so the + /// plane's normal vector (indicated by the arrow) points in the correct direction. + public sealed class MockPlaneAnchor: + MockAnchorBase + { + [SerializeField] + private Vector3 _center = Vector3.zero; + + [Tooltip("All values should be increments of 90")] + [SerializeField] + private Vector3 _rotation = Vector3.zero; + + [SerializeField] + private PlaneAlignment _planeAlignment = default(PlaneAlignment); + + [Header("Plane Classification Options")] + [SerializeField] + private bool _shouldSuccessfullyClassify = true; + + [SerializeField] + private PlaneClassification _planeClassification = default(PlaneClassification); + + // Time (in seconds) it takes for this anchor's PlaneClassificationStatus to settle after + // it is discovered. + [SerializeField] + private float _timeToClassify = 1f; + + private _SerializableARPlaneAnchor _anchorData; + + private Vector3 _localScale = new Vector3(1, 0.001f, 1); + + protected override bool Initialize() + { + if (_planeAlignment == PlaneAlignment.Unknown) + { + ARLog._Error("MockPlaneAnchors with Unknown plane alignments will not be discovered."); + return false; + } + + return true; + } + + protected override IARAnchor AnchorData + { + get => _anchorData; + } + + protected override bool UpdateAnchorData() + { + // Note: transform.hasChanged is susceptible to other logic changing this flag's value + // but for the time being, this is also the most straightforward approach for detecting + // changes to this GameObject's transform component + if (_anchorData == null || !transform.hasChanged) + return false; + + var localTransform = + Matrix4x4.TRS + ( + _center, + Quaternion.Euler(_rotation).normalized, + _localScale + ); + + var worldTransform = transform.localToWorldMatrix * localTransform; + + _anchorData.Transform = + Matrix4x4.TRS + ( + worldTransform.ToPosition(), + worldTransform.ToRotation(), + Vector3.one + ); + + _anchorData.Extent = + new Vector3 + ( + worldTransform.lossyScale.x, + 0, + worldTransform.lossyScale.z + ); + + transform.hasChanged = false; + return true; + } + + internal override void CreateAndAddAnchorToSession(_IMockARSession arSession) + { + if (_anchorData == null) + { + // Initialize the anchor data with initial values such as + // a new guid, non-transform related values, etc + _anchorData = + new _SerializableARPlaneAnchor + ( + new Matrix4x4(), + Guid.NewGuid(), + _planeAlignment, + PlaneClassification.None, + PlaneClassificationStatus.Undetermined, + Vector3.zero, + Vector3.zero + ); + + // Transform and Extent values will be set here + UpdateAnchorData(); + + // Value starts off as true, so needs to be set to false here + transform.hasChanged = false; + } + + if (arSession.AddAnchor(_anchorData)) + StartCoroutine(ClassifyPlane(arSession)); + else + { + ARLog._DebugFormat + ( + "Plane anchor for {0} cannot be detected. If that is unintended, check" + + "that the active ARWorldTrackingConfiguration's PlaneDetection value is correct." + ); + + enabled = false; + } + } + + internal override void RemoveAnchorFromSession(_IMockARSession arSession) + { + arSession.RemoveAnchor(_anchorData); + } + + private IEnumerator ClassifyPlane(_IMockARSession arSession) + { + yield return new WaitForSeconds(_timeToClassify); + + _anchorData.Classification = + _shouldSuccessfullyClassify + ? _planeClassification + : PlaneClassification.None; + + _anchorData.ClassificationStatus = + _shouldSuccessfullyClassify + ? PlaneClassificationStatus.Known + : PlaneClassificationStatus.Unknown; + + arSession.UpdateAnchor(_anchorData); + } + +#if UNITY_EDITOR + private void OnDrawGizmosSelected() + { + Gizmos.matrix = transform.localToWorldMatrix; + + var orientation = Quaternion.Euler(_rotation); + Gizmos.DrawWireCube(_center, orientation * _localScale); + + var worldCenter = transform.position; + Handles.ArrowHandleCap + ( + 0, + worldCenter, + transform.rotation * orientation * Quaternion.LookRotation(Vector3.up), + .25f, + EventType.Repaint + ); + } +#endif + } +} diff --git a/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockPlaneAnchor.cs.meta b/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockPlaneAnchor.cs.meta new file mode 100644 index 0000000..67f6d1a --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockPlaneAnchor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: efac6a083cc96476b94cbcda0cfb8ffd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockSceneConfiguration.cs b/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockSceneConfiguration.cs new file mode 100644 index 0000000..262ec2f --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockSceneConfiguration.cs @@ -0,0 +1,93 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.ARSessionEventArgs; +using Niantic.ARDK.Utilities.Logging; +using Niantic.ARDK.VirtualStudio.Remote; + +using UnityEngine; + +#if UNITY_EDITOR +using Niantic.ARDK.Utilities.Extensions; + +using UnityEditor; +#endif + +namespace Niantic.ARDK.VirtualStudio.AR.Mock +{ + public sealed class MockSceneConfiguration: + MonoBehaviour + { +#if UNITY_EDITOR + private void OnEnable() + { + const string layerName = _MockFrameBufferProvider.MOCK_LAYER_NAME; + var mockLayer = LayerMask.NameToLayer(layerName); + if (mockLayer < 0 && !_MockFrameBufferProvider.CreateLayer(layerName, out mockLayer)) + return; + + var noLayerCount = 0; + foreach (var descendant in gameObject.GetComponentsInChildren()) + { + if (descendant.gameObject.layer != mockLayer) + noLayerCount++; + } + + if (noLayerCount > 0) + { + ARLog._WarnFormatRelease + ( + "Found {0} GameObjects parented to {1} that are not in the " + + "Layer: {2} required for use of Virtual Studio Mock mode.\n" + + "Reset the MockSceneConfiguration to set " + + "the correct layer for all objects in its hierarchy.", + noLayerCount, + gameObject.name, + layerName + ); + } + } + + private void Reset() + { + _SetLayerForDescendants(); + } + + [MenuItem("GameObject/3D Object/ARDK/MockScene", false, 0)] + private static void CreateRoot(MenuCommand menuCommand) + { + var mockSceneRoot = new GameObject("MockSceneRoot"); + var mockScene = mockSceneRoot.AddComponent(); + mockScene._SetLayerForDescendants(); + + // Ensure it gets re-parented if this was a context click (otherwise does nothing) + GameObjectUtility.SetParentAndAlign(mockSceneRoot, menuCommand.context as GameObject); + + // Register the creation in the undo system + Undo.RegisterCreatedObjectUndo(mockSceneRoot, "Create " + mockSceneRoot.name); + + Selection.activeObject = mockSceneRoot; + } + + // Sets the layer of this component's GameObject and all its descendants + // to _MockFrameBufferProvider.MOCK_LAYER_NAME. + // It will add that layer to the TagManager.asset if it does not already exist. + private void _SetLayerForDescendants() + { + const string layerName = _MockFrameBufferProvider.MOCK_LAYER_NAME; + var layerIndex = LayerMask.NameToLayer(layerName); + if (layerIndex < 0) + { + if (!_MockFrameBufferProvider.CreateLayer(layerName, out layerIndex)) + return; + } + + foreach (var descendant in gameObject.GetComponentsInChildren()) + descendant.gameObject.layer = layerIndex; + } +#endif + } +} + diff --git a/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockSceneConfiguration.cs.meta b/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockSceneConfiguration.cs.meta new file mode 100644 index 0000000..49c8e31 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockSceneConfiguration.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 356a576ce733a4b21bee15f55b9f0741 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockSemanticLabel.cs b/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockSemanticLabel.cs new file mode 100644 index 0000000..be1af63 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockSemanticLabel.cs @@ -0,0 +1,122 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; +using System.ComponentModel; + +using Niantic.ARDK.AR.Awareness.Semantics; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; +using UnityEngine.Assertions; + +namespace Niantic.ARDK.VirtualStudio.AR.Mock +{ + /// Add this to any mesh in the Editor in order to have it semantically + /// segmented as a certain channel. + [RequireComponent(typeof(MeshRenderer))] + public class MockSemanticLabel: MonoBehaviour + { + public enum ChannelName + { + sky, ground, artificial_ground, water, building, foliage, grass + } + + public ChannelName Channel; + + private MaterialPropertyBlock materialPropertyBlock; + + private void Awake() + { + var bits = ToBits(Channel); + var color = ToColor(bits); + + materialPropertyBlock = new MaterialPropertyBlock(); + materialPropertyBlock.SetColor("PackedColor", color); + materialPropertyBlock.SetColor("DebugColor", _debugColors[(int)Channel]); + GetComponent().SetPropertyBlock(materialPropertyBlock); + + ARLog._DebugFormat("GameObject: {0} - Channel: {1} - Bits: {2}", false, gameObject.name, Channel, ToBinaryString(bits)); + } + + // Channel format copied from semantic_buffer.cpp + static uint ToBits(ChannelName channel) + { + return 1u << (_NativeSemanticBuffer.BitsPerPixel - 1 - (int)channel); + } + + static Color32 ToColor(uint buffer) + { + byte r = (byte)((buffer) & 0xFF); + byte g = (byte)((buffer >> 8) & 0xFF); + byte b = (byte)((buffer >> 16) & 0xFF); + byte a = (byte)((buffer >> 24) & 0xFF); + + return new Color32(r, g, b, a); + } + + public static uint ToInt(Color32 color) + { + uint buffer = 0; + + uint A = (uint) color.a << 24; + uint B = (uint) color.b << 16; + uint G = (uint) color.g << 8; + uint R = color.r; + + + buffer = R + G + B + A; + + return buffer; + } + + public static string ToBinaryString(uint val) + { + var bits = Convert.ToString(val, 2).ToCharArray(); + var numBits = bits.Length; + + var a = new char[39]; // 32 bits + 7 spaces + + var ai = a.Length - 1; + var si = numBits - 1; + + var spaceCount = 0; + while (si >= 0) + { + if (spaceCount == 4) + { + spaceCount = 0; + a[ai--] = ' '; + } + + spaceCount++; + + try + { + a[ai--] = bits[si--]; + } + catch (Exception e) + { + throw e; + } + } + + // Pad leading zeroes + while (ai >= 0) + { + if (spaceCount == 4) + { + spaceCount = 0; + a[ai--] = ' '; + } + + spaceCount++; + a[ai--] = '0'; + } + + return new string(a); + } + +#region DEBUG + private static Color[] _debugColors = { Color.blue, new Color(165/255f, 42/255f, 42/255f, 1), Color.gray, Color.cyan, Color.yellow, Color.red, Color.green}; +#endregion + } +} diff --git a/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockSemanticLabel.cs.meta b/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockSemanticLabel.cs.meta new file mode 100644 index 0000000..ade3efb --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/SceneComponents/MockSemanticLabel.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f16534bb6007474a91d7b492b09b52c9 +timeCreated: 1625241751 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/_IEditorARSessionMediator.cs b/Assets/ARDK/VirtualStudio/AR/_IEditorARSessionMediator.cs new file mode 100644 index 0000000..8219d27 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/_IEditorARSessionMediator.cs @@ -0,0 +1,16 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.AR; + +namespace Niantic.ARDK.VirtualStudio.AR +{ + internal interface _IEditorARSessionMediator: + ISessionMediator + { + IARSession CreateNonLocalSession(Guid stageIdentifier, RuntimeEnvironment runtimeEnvironment); + + IARSession GetSession(Guid stageIdentifier); + } +} \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/_IEditorARSessionMediator.cs.meta b/Assets/ARDK/VirtualStudio/AR/_IEditorARSessionMediator.cs.meta new file mode 100644 index 0000000..65b66ef --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/_IEditorARSessionMediator.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: cf145ec1187043e38744e1a89ee76471 +timeCreated: 1595968552 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/_IMockARSession.cs b/Assets/ARDK/VirtualStudio/AR/_IMockARSession.cs new file mode 100644 index 0000000..9066d14 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/_IMockARSession.cs @@ -0,0 +1,30 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.Anchors; +using Niantic.ARDK.AR.Mesh; +using Niantic.ARDK.AR.SLAM; + +namespace Niantic.ARDK.VirtualStudio.AR +{ + internal interface _IMockARSession: + IMockARSession, + _IARSession + { + bool CheckMapsUnion(IARSession otherSession); + + bool AddAnchor(_SerializableARAnchor anchor); + + void UpdateMesh(_IARMeshData meshData); + + // Event raised when mock ARMaps are added to the session (ie by MockMap) but the + // local peer is not the host. A "local map" isn't a valid concept in _NativeARSession, + // but it's needed here to support mock localizing. + // + // Note: This event doesn't need to follow the new pattern for events to avoid breaking + // changes because it is an internal event. + event Action ImplDidAddLocalMaps; + } +} diff --git a/Assets/ARDK/VirtualStudio/AR/_IMockARSession.cs.meta b/Assets/ARDK/VirtualStudio/AR/_IMockARSession.cs.meta new file mode 100644 index 0000000..dc04c1e --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/_IMockARSession.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 83d8a209516c4b54b631a681019ef480 +timeCreated: 1595970925 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/_MockARSession.cs b/Assets/ARDK/VirtualStudio/AR/_MockARSession.cs new file mode 100644 index 0000000..b170159 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/_MockARSession.cs @@ -0,0 +1,638 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.Anchors; +using Niantic.ARDK.AR.ARSessionEventArgs; +using Niantic.ARDK.AR.Awareness; +using Niantic.ARDK.AR.Configuration; +using Niantic.ARDK.AR.Awareness.Depth; +using Niantic.ARDK.AR.Awareness.Depth.Generators; +using Niantic.ARDK.AR.Frame; +using Niantic.ARDK.AR.Mesh; +using Niantic.ARDK.AR.Networking; +using Niantic.ARDK.AR.SLAM; +using Niantic.ARDK.Extensions.Meshing; +using Niantic.ARDK.LocationService; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Collections; +using Niantic.ARDK.Utilities.Logging; +using Niantic.ARDK.VirtualStudio.AR.Camera.Input; +using Niantic.ARDK.VirtualStudio.AR.Mock; + +using UnityEngine; +using UnityEngine.Rendering; + +namespace Niantic.ARDK.VirtualStudio.AR +{ + internal sealed class _MockARSession: + _IMockARSession + { + private bool _isWorldTracking; + private bool _isSharedExperience; + + private bool _anchorsDirty; + private ReadOnlyCollection _cachedAnchors = new ReadOnlyCollection(new IARAnchor[0]); + private readonly Dictionary _anchors = new Dictionary(); + + private readonly Dictionary _addedAnchors = new Dictionary(); + private readonly Dictionary _updatedAnchors = new Dictionary(); + private readonly List _removedAnchors = new List(); + + private bool _mapsDirty; + private _SerializableARMap[] _cachedMaps = EmptyArray<_SerializableARMap>.Instance; + private readonly Dictionary _maps = new Dictionary(); + + private readonly Dictionary _localMaps = + new Dictionary(); + + // TODO: Should we use a HashSet here? Should we use _ReferenceComparer? + private readonly HashSet _newMaps = new HashSet(); + + private _IVirtualStudioManager _virtualStudioManager; + + private GameObject _camerasRoot; + private _MockFrameBufferProvider _frameProvider; + +#if DEBUG + private System.Diagnostics.StackTrace _stackTrace = new System.Diagnostics.StackTrace(true); +#endif + + public ARSessionChangesCollector ARSessionChangesCollector { get; } + + public ARSessionRunOptions RunOptions { get; private set; } + + public IARMesh Mesh + { + get { return _meshDataParser; } + } + + private _MeshDataParser _meshDataParser = new _MeshDataParser(); + + internal _MockARSession(Guid stageIdentifier, _IVirtualStudioManager virtualStudioManager) + { + _FriendTypeAsserter.AssertCallerIs(typeof(ARSessionFactory)); + + StageIdentifier = stageIdentifier; + _virtualStudioManager = virtualStudioManager ?? _VirtualStudioManager.Instance; + ARSessionChangesCollector = new ARSessionChangesCollector(this); + } + + private bool _isDestroyed; + public void Dispose() + { + if (_isDestroyed) + return; + + _isDestroyed = true; + + if (State == ARSessionState.Running) + Pause(); + + var handler = Deinitialized; + if (handler != null) + { + var args = new ARSessionDeinitializedArgs(); + handler(args); + } + + CurrentFrame?.Dispose(); + CurrentFrame = null; + + if (_camerasRoot != null) + { + if (Application.isEditor) + GameObject.DestroyImmediate(_camerasRoot); + else + GameObject.Destroy(_camerasRoot); + } + + _frameProvider?.Dispose(); + _frameProvider = null; + + _depthPointCloudGen?.Dispose(); + _depthPointCloudGen = null; + + _meshDataParser?.Dispose(); + _meshDataParser = null; + } + + private float _worldScale = 1.0f; + public float WorldScale + { + get { return _worldScale; } + set { _worldScale = value; } + } + + public IARConfiguration Configuration { get; private set; } + public Guid StageIdentifier { get; private set; } + public ARSessionState State { get; private set; } + + private IARFrame _currentFrame; + /// + public IARFrame CurrentFrame + { + get { return _currentFrame; } + internal set + { + _SessionFrameSharedLogic._MakeSessionFrameBecomeNonCurrent(this); + _currentFrame = value; + } + } + + /// + public ARFrameDisposalPolicy DefaultFrameDisposalPolicy { get; set; } + + public void Run + ( + IARConfiguration configuration, + ARSessionRunOptions options = ARSessionRunOptions.None + ) + { + ARSessionChangesCollector._CollectChanges(configuration, ref options); + + if (!_ARConfigurationValidator.RunAllChecks(this, configuration)) + return; + + Configuration = configuration; + RunOptions = options; + + if ((RunOptions & ARSessionRunOptions.RemoveExistingMesh) != 0) + _meshDataParser.Clear(); + + ARLog._DebugFormat("Running _MockARSession with options: {0}", false, options); + + if (configuration is IARWorldTrackingConfiguration worldConfiguration) + { + _isWorldTracking = true; + _isSharedExperience = _isWorldTracking && worldConfiguration.IsSharedExperienceEnabled; + } + + if (_virtualStudioManager.LocalPlayer?.ARSession == this && _camerasRoot == null) + { + _camerasRoot = new GameObject(); + _camerasRoot.name = "ARDK_MockDeviceCamera_Root"; + + _frameProvider = new _MockFrameBufferProvider(this, _camerasRoot.transform); + _CameraInputSystemProvider.AttachController(_camerasRoot); + } + + State = ARSessionState.Running; + + var handler = _onDidRun; + if (handler != null) + handler(new ARSessionRanArgs()); + } + + public void Pause() + { + if (State != ARSessionState.Running) + return; + + State = ARSessionState.Paused; + + var handler = Paused; + if (handler != null) + handler(new ARSessionPausedArgs()); + } + + public bool AddAnchor(_SerializableARAnchor anchor) + { + if (State != ARSessionState.Running) + return false; + + switch (anchor.AnchorType) + { + case AnchorType.Plane: + var planeAnchor = (IARPlaneAnchor)anchor; + if (!_IsPlaneAnchorDetectable(planeAnchor)) + return false; + + break; + + case AnchorType.Image: + var imageAnchor = (IARImageAnchor)anchor; + if (!_IsImageAnchorDetectable(imageAnchor)) + return false; + + break; + } + + var anchorCopy = anchor.Copy(); + _anchors.Add(anchor.Identifier, anchorCopy); + _addedAnchors.Add(anchor.Identifier, anchorCopy); + _anchorsDirty = true; + + return true; + } + + public IARAnchor AddAnchor(Matrix4x4 transform) + { + var anchor = _ARAnchorFactory._Create(transform); + AddAnchor((_SerializableARAnchor) anchor); + + return anchor; + } + + public void UpdateAnchor(IARAnchor anchor) + { + if (!_anchors.ContainsKey(anchor.Identifier)) + { + ARLog._ErrorFormat("Tried to update anchor {0} that hadn't been added.", anchor.Identifier); + return; + } + + var anchorCopy = anchor._AsSerializable().Copy(); + _anchors[anchor.Identifier] = anchorCopy; + _updatedAnchors[anchor.Identifier] = anchorCopy; + _anchorsDirty = true; + } + + public void MergeAnchors(IARAnchor parent, IARAnchor[] children) + { + // TODO: ecomas hook this up to MockPlaneAnchor + bool foundAllAnchors = _anchors.ContainsKey(parent.Identifier); + foreach(var child in children) + { + foundAllAnchors = foundAllAnchors & _anchors.ContainsKey(child.Identifier); + } + + if (!foundAllAnchors) + { + ARLog._Warn("Cannot merge an anchor that was not added."); + return; + } + + var handler = AnchorsMerged; + if (handler != null) + { + var args = new AnchorsMergedArgs(parent, children); + handler(args); + } + } + + private bool _IsPlaneAnchorDetectable(IARPlaneAnchor planeAnchor) + { + if (!_isWorldTracking) + return false; + + // See definition of either enum more information on why it has to be this way. + var detectedPlanes = ((IARWorldTrackingConfiguration)Configuration).PlaneDetection; + var thisPlane = (PlaneDetection) planeAnchor.Alignment; + return (detectedPlanes & thisPlane) != 0; + } + + private bool _IsImageAnchorDetectable(IARImageAnchor imageAnchor) + { + if (!_isWorldTracking) + return false; + + foreach (var image in ((IARWorldTrackingConfiguration)Configuration).DetectionImages) + { + if (image.Name.Equals(imageAnchor.ReferenceImage.Name)) + return true; + } + + return false; + } + + public void RemoveAnchor(IARAnchor anchor) + { + if (State != ARSessionState.Running) + return; + + if (!_anchors.ContainsKey(anchor.Identifier)) + { + ARLog._Warn("Tried to remove an anchor that was not added."); + return; + } + + _anchors.Remove(anchor.Identifier); + _anchorsDirty = true; + + _removedAnchors.Add(anchor); + } + + public void UpdateFrame(IARFrame frame) + { + // do something new with this frame data per frame + _UpdateCachedAnchorsAndMaps(); + + var serializableFrame = frame._AsSerializable(); + serializableFrame.Anchors = _cachedAnchors; + serializableFrame.Maps = _cachedMaps.AsNonNullReadOnly(); + + _UpdateGenerators(serializableFrame); + CurrentFrame = serializableFrame; + + var frameUpdatedHandler = FrameUpdated; + if (frameUpdatedHandler != null) + { + var args = new FrameUpdatedArgs(serializableFrame); + frameUpdatedHandler(args); + } + + RaiseAnchorAndMapEvents(); + + } + + private DepthPointCloudGenerator _depthPointCloudGen; + private void _UpdateGenerators(_SerializableARFrame frame) + { + if (!(Configuration is IARWorldTrackingConfiguration worldConfig)) + return; + + if (!worldConfig.IsDepthPointCloudEnabled) + return; + + var depthBuffer = frame.DepthBuffer; + if (depthBuffer == null || !depthBuffer.IsKeyframe) + return; + + // Create a generator if needed + if (_depthPointCloudGen == null) + { + _depthPointCloudGen = new DepthPointCloudGenerator(); + + ARLog._Debug("Created new depth point cloud generator"); + } + + // Generate the point cloud + var pointCloud = _depthPointCloudGen.GeneratePointCloud(frame.DepthBuffer, frame.Camera); + ARLog._Debug("Updated depth point cloud generator with new keyframe", true); + + frame.DepthPointCloud = pointCloud; + } + + private void _UpdateCachedAnchorsAndMaps() + { + if (_anchorsDirty) + { + _cachedAnchors = _anchors.Values.ToArray().AsNonNullReadOnly(); + _anchorsDirty = false; + } + + if (_mapsDirty) + { + _cachedMaps = _maps.Values.ToArray()._AsSerializableArray(); + _mapsDirty = false; + } + } + + private void RaiseAnchorAndMapEvents() + { + if (_addedAnchors.Count > 0) + { + var anchors = _addedAnchors.Values.ToArray(); + + var handler = AnchorsAdded; + if (handler != null) + { + var args = new AnchorsArgs(anchors); + handler(args); + } + + _addedAnchors.Clear(); + } + + if (_updatedAnchors.Count > 0) + { + var anchors = _updatedAnchors.Values.ToArray(); + + var handler = AnchorsUpdated; + if (handler != null) + { + var args = new AnchorsArgs(anchors); + handler(args); + } + + _updatedAnchors.Clear(); + } + + if (_removedAnchors.Count > 0) + { + var anchors = _removedAnchors.ToArray(); + + var handler = AnchorsRemoved; + if (handler != null) + { + var args = new AnchorsArgs(anchors); + handler(args); + } + + _removedAnchors.Clear(); + } + + if (_newMaps.Count > 0) + { + var mapsArray = _newMaps.ToArray(); + + var mapsHandler = MapsAdded; + if (mapsHandler != null) + { + var args = new MapsArgs(mapsArray); + mapsHandler(args); + } + + _newMaps.Clear(); + } + } + + public bool CheckMapsUnion(IARSession otherSession) + { + var otherFrame = otherSession.CurrentFrame; + if (otherFrame == null) + return false; + + var otherMaps = new HashSet(otherFrame.Maps); + + foreach (var map in otherMaps) + if (_localMaps.ContainsKey(map.Identifier)) + return true; + + return false; + } + + private IARNetworking _GetPartnerARNetworking() + { + return _virtualStudioManager.ArNetworkingMediator.GetSession(StageIdentifier); + } + + public void AddMap(IARMap map) + { + bool isHost = true; + + var arNetworking = _GetPartnerARNetworking(); + if (arNetworking != null && arNetworking.Networking.IsConnected) + isHost = arNetworking.Networking.Host.Equals(arNetworking.Networking.Self); + else + { + var message = + "An ARMap is only supposed to be added to an ARSession that is part of a connected" + + " ARNetworking session."; + + ARLog._Error(message); + return; + } + + if (!_isSharedExperience) + { + var message = + "A map cannot be added to a session that is not running with SharedExperienceEnabled " + + "set to true."; + + ARLog._Error(message); + return; + } + + if (_maps.ContainsKey(map.Identifier)) + { + var message = + "Map (identifier {0}) already exists in this session. " + + "If it needs to be updated use UpdateSerializedMap"; + + ARLog._ErrorFormat(message, map.Identifier); + return; + } + + if (isHost) + { + _maps.Add(map.Identifier, map); + _mapsDirty = true; + + // Can't invoke ImplDidAddMaps here because it needs to be invoked after the + // frame is updated with the map. See ValidateCachedAnchorsAndMaps for more. + // Todo: same logic for anchors + _newMaps.Add(map); + } + else + { + _localMaps.Add(map.Identifier, map); + + var handler = ImplDidAddLocalMaps; + if (handler != null) + handler(new[] { map }); + } + } + + public void UpdateMap(IARMap map) + { + if (_GetPartnerARNetworking() == null) + { + ARLog._Warn + ( + "An ARMap can only be added for an ARSession that is part of an ARNetworking session." + ); + + return; + } + + if (!_maps.ContainsKey(map.Identifier)) + { + ARLog._WarnFormat + ( + "Map (identifier {0}) does not exist in this session.", + objs: map.Identifier + ); + + return; + } + + _maps[map.Identifier] = map; + _mapsDirty = true; + + var maps = _ArrayFromElement.Create(map); + + var handler = MapsUpdated; + if (handler != null) + { + var args = new MapsArgs(maps); + handler(args); + } + } + + public void UpdateMesh(_IARMeshData meshData) + { + if (Configuration is IARWorldTrackingConfiguration worldConfig) + { + if (meshData == null) + _meshDataParser.ParseMesh(_SerializableARMeshData.EmptyMesh()); + else if (worldConfig.IsMeshingEnabled) + _meshDataParser.ParseMesh(meshData); + } + } + + public AwarenessInitializationStatus GetAwarenessInitializationStatus + ( + out AwarenessInitializationError error, + out string errorMessage + ) + { + error = AwarenessInitializationError.None; + errorMessage = string.Empty; + + return AwarenessInitializationStatus.Ready; + } + + + private ArdkEventHandler _onDidRun; + public event ArdkEventHandler Ran + { + add + { + _onDidRun += value; + + if (State == ARSessionState.Running) + value(new ARSessionRanArgs()); + } + remove + { + _onDidRun -= value; + } + } + + public event ArdkEventHandler Paused; + public event ArdkEventHandler Deinitialized; + + public event ArdkEventHandler FrameUpdated; + public event ArdkEventHandler AnchorsMerged; + public event ArdkEventHandler AnchorsAdded; + public event ArdkEventHandler AnchorsUpdated; + public event ArdkEventHandler AnchorsRemoved; + public event ArdkEventHandler MapsAdded; + public event ArdkEventHandler MapsUpdated; + + // This are internal events, so we don't care about the args standard. + public event Action ImplDidAddLocalMaps; + +#region Events Unused by Mock Implementation + event ArdkEventHandler IARSession.SessionInterrupted { add {} remove {} } + event ArdkEventHandler IARSession.SessionInterruptionEnded { add {} remove {} } + event ArdkEventHandler IARSession.QueryingShouldSessionAttemptRelocalization { add {} remove {} } + event ArdkEventHandler IARSession.SessionFailed { add {} remove {} } + + event ArdkEventHandler IARSession.CameraTrackingStateChanged + { + add {} + remove {} + } +#endregion Events Unused by Mock Implementation + + RuntimeEnvironment IARSession.RuntimeEnvironment + { + get { return RuntimeEnvironment.Mock; } + } + + public bool IsPlayback { get { return false; } } + + internal bool _HasSetupLocationService = false; + void IARSession.SetupLocationService(ILocationService locationService) + { + _HasSetupLocationService = true; + } + } +} diff --git a/Assets/ARDK/VirtualStudio/AR/_MockARSession.cs.meta b/Assets/ARDK/VirtualStudio/AR/_MockARSession.cs.meta new file mode 100644 index 0000000..e8de1cf --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/_MockARSession.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 38fc3171155645a896ebcd268ef781c7 +timeCreated: 1596209063 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/_MockARSessionMediator.cs b/Assets/ARDK/VirtualStudio/AR/_MockARSessionMediator.cs new file mode 100644 index 0000000..6f473d6 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/_MockARSessionMediator.cs @@ -0,0 +1,83 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.ARSessionEventArgs; + +using UnityEngine; + +namespace Niantic.ARDK.VirtualStudio.AR +{ + internal sealed class _MockARSessionMediator: + _IEditorARSessionMediator + { + private readonly Dictionary _stageIdentifierToSession = + new Dictionary(); + + private _IVirtualStudioManager _virtualStudioManager; + + public _MockARSessionMediator(_IVirtualStudioManager virtualStudioMaster) + { + _virtualStudioManager = virtualStudioMaster; + + ARSessionFactory.SessionInitialized += HandleAnyInitialized; + ARSessionFactory._NonLocalSessionInitialized += HandleAnyInitialized; + } + + ~_MockARSessionMediator() + { + // This class has no unmanaged data, so no need to have a Dispose(false) call. + Debug.LogError("EditorARSessionMediator should be destroyed by calling Dispose()."); + } + + public void Dispose() + { + GC.SuppressFinalize(this); + + foreach (var session in _stageIdentifierToSession.Values.ToArray()) + session.Dispose(); + + ARSessionFactory.SessionInitialized -= HandleAnyInitialized; + ARSessionFactory._NonLocalSessionInitialized -= HandleAnyInitialized; + } + + public IARSession CreateNonLocalSession(Guid stageIdentifier, RuntimeEnvironment runtimeEnvironment) + { + return + ARSessionFactory._CreateVirtualStudioManagedARSession + ( + runtimeEnvironment, + stageIdentifier, + isLocal: false, + _virtualStudioManager + ); + } + + public IARSession GetSession(Guid stageIdentifier) + { + IARSession session; + if (_stageIdentifierToSession.TryGetValue(stageIdentifier, out session)) + return session; + + return null; + } + + private void HandleAnyInitialized(AnyARSessionInitializedArgs args) + { + var arSession = args.Session; + + var stageIdentifier = arSession.StageIdentifier; + if (stageIdentifier == Guid.Empty) + throw new InvalidOperationException("A Session StageIdentifier can't be empty."); + + _stageIdentifierToSession.Add(stageIdentifier, arSession); + + arSession.Deinitialized += + (_) => _stageIdentifierToSession.Remove(stageIdentifier); + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/_MockARSessionMediator.cs.meta b/Assets/ARDK/VirtualStudio/AR/_MockARSessionMediator.cs.meta new file mode 100644 index 0000000..f5c95c2 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/_MockARSessionMediator.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 60c1a19173f44c94a3314ddfb6550fef +timeCreated: 1579731779 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/AR/_RemoteEditorARSession.cs b/Assets/ARDK/VirtualStudio/AR/_RemoteEditorARSession.cs new file mode 100644 index 0000000..0539c73 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/_RemoteEditorARSession.cs @@ -0,0 +1,605 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.Anchors; +using Niantic.ARDK.AR.ARSessionEventArgs; +using Niantic.ARDK.AR.Awareness; +using Niantic.ARDK.AR.Configuration; +using Niantic.ARDK.AR.Awareness.Depth.Generators; +using Niantic.ARDK.AR.Frame; +using Niantic.ARDK.AR.Mesh; +using Niantic.ARDK.LocationService; +using Niantic.ARDK.Networking; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Logging; +using Niantic.ARDK.VirtualStudio.Remote; +using Niantic.ARDK.VirtualStudio.Remote.Data; + +using UnityEngine; + +namespace Niantic.ARDK.VirtualStudio.AR +{ + internal sealed class _RemoteEditorARSession: + _IARSession + { + private DepthPointCloudGenerator _depthPointCloudGen; + + private Dictionary _editorAnchors = + new Dictionary(); + private Dictionary _editorToDeviceAnchorIdentifiers = new Dictionary(); + private Dictionary _deviceToEditorAnchorIdentifiers = new Dictionary(); + + internal _RemoteEditorARSession(Guid stageIdentifier) + { + _FriendTypeAsserter.AssertCallerIs(typeof(ARSessionFactory)); + + StageIdentifier = stageIdentifier; + ARSessionChangesCollector = new ARSessionChangesCollector(this); + + _EasyConnection.Register(HandleDidUpdateFrame); + + _EasyConnection.Register(HandleDidAddMaps); + _EasyConnection.Register(HandleDidUpdateMaps); + + _EasyConnection.Register(HandleAddedAnchor); + _EasyConnection.Register(HandleDidAddAnchors); + _EasyConnection.Register(HandleDidUpdateAnchors); + _EasyConnection.Register(HandleDidMergeAnchors); + _EasyConnection.Register(HandleDidRemoveAnchors); + + _EasyConnection.Register + ( + HandleCameraDidChangeTrackingState + ); + + _EasyConnection.Register(HandleSessionWasInterrupted); + _EasyConnection.Register(HandleSessionInterruptionEnded); + _EasyConnection.Register(HandleDidFailWithError); + + _EasyConnection.Send + ( + new ARSessionInitMessage + { + StageIdentifier = stageIdentifier, +#if UNITY_EDITOR_OSX // Only can do image compression on OSX + ImageCompressionQuality = _RemoteBufferConfiguration.ImageCompression, +#endif + TargetImageFramerate = _RemoteBufferConfiguration.ImageFramerate, + TargetBufferFramerate = _RemoteBufferConfiguration.AwarenessFramerate, + TargetFeaturePointFramerate = _RemoteBufferConfiguration.FeaturePointFramerate, + }, + TransportType.ReliableOrdered + ); + } + + ~_RemoteEditorARSession() + { + ARLog._Error("_RemoteEditorARSession should be destroyed by an explicit call to Dispose()."); + } + + private bool _isDestroyed; + public void Dispose() + { + if (_isDestroyed) + return; + + _isDestroyed = true; + GC.SuppressFinalize(this); + + var handler = Deinitialized; + if (handler != null) + { + var args = new ARSessionDeinitializedArgs(); + handler(args); + } + + _EasyConnection.Unregister(); + _EasyConnection.Unregister(); + + _EasyConnection.Unregister(); + _EasyConnection.Unregister(); + _EasyConnection.Unregister(); + _EasyConnection.Unregister(); + _EasyConnection.Unregister(); + + _EasyConnection.Unregister(); + _EasyConnection.Unregister(); + + _EasyConnection.Unregister(); + _EasyConnection.Unregister(); + _EasyConnection.Unregister(); + _EasyConnection.Unregister(); + + _EasyConnection.Send(new ARSessionDestroyMessage(), TransportType.ReliableOrdered); + + // Dispose of any generators that we've created. + DisposeGenerators(); + } + + private void DisposeGenerators() + { + var depthPointCloudGen = _depthPointCloudGen; + if (depthPointCloudGen != null) + { + _depthPointCloudGen = null; + depthPointCloudGen.Dispose(); + } + } + + public Guid StageIdentifier { get; } + + private IARFrame _currentFrame; + /// + public IARFrame CurrentFrame + { + get => _currentFrame; + internal set + { + _SessionFrameSharedLogic._MakeSessionFrameBecomeNonCurrent(this); + _currentFrame = value; + } + } + + /// + public ARFrameDisposalPolicy DefaultFrameDisposalPolicy { get; set; } + + public IARConfiguration Configuration { get; private set; } + + private float _worldScale = 1.0f; + public float WorldScale + { + get => _worldScale; + set + { + _EasyConnection.Send + ( + new ARSessionSetWorldScaleMessage { WorldScale = value }, + TransportType.ReliableOrdered + ); + + _worldScale = value; + } + } + + public ARSessionState State { get; private set; } + + public ARSessionChangesCollector ARSessionChangesCollector { get; } + + public ARSessionRunOptions RunOptions { get; private set; } + + public void Run + ( + IARConfiguration configuration, + ARSessionRunOptions options = ARSessionRunOptions.None + ) + { + ARSessionChangesCollector._CollectChanges(configuration, ref options); + + if (!_ARConfigurationValidator.RunAllChecks(this, configuration)) + return; + + Configuration = configuration; + RunOptions = options; + + State = ARSessionState.Running; + + // Need to destroy the generators so they can be recreated once we get new depth data + DisposeGenerators(); + + if ((RunOptions & ARSessionRunOptions.RemoveExistingMesh) != 0) + _meshDataParser.Clear(); + + var message = new ARSessionRunMessage + { + arConfiguration = configuration, + runOptions = options + }; + + ARLog._DebugFormat("Running _RemoteEditorARSession with options: {0}", false, options); + _EasyConnection.Send(message, TransportType.ReliableOrdered); + + var handler = _onDidRun; + if (handler != null) + handler(new ARSessionRanArgs()); + } + + public void Pause() + { + if (State != ARSessionState.Running) + return; + + State = ARSessionState.Paused; + _EasyConnection.Send(new ARSessionPauseMessage(), TransportType.ReliableOrdered); + + var handler = Paused; + handler?.Invoke(new ARSessionPausedArgs()); + } + + public IARAnchor AddAnchor(Matrix4x4 transform) + { + var identifier = Guid.NewGuid(); + var anchor = new _SerializableARBasicAnchor(transform, identifier); + + _editorAnchors.Add(identifier, anchor); + + ARLog._DebugFormat("Sending AddAnchor request (editor id: {0})", false, identifier); + + _EasyConnection.Send + ( + new ARSessionAddAnchorMessage { Anchor = anchor }, + TransportType.ReliableOrdered + ); + + return anchor; + } + + public void RemoveAnchor(IARAnchor anchor) + { + ARLog._DebugFormat("Sending RemoveAnchor request (editor id: {0})", false, anchor.Identifier); + var deviceIdentifier = _editorToDeviceAnchorIdentifiers[anchor.Identifier]; + + _EasyConnection.Send + ( + new ARSessionRemoveAnchorMessage { DeviceAnchorIdentifier = deviceIdentifier }, + TransportType.ReliableOrdered + ); + } + + public AwarenessInitializationStatus GetAwarenessInitializationStatus + ( + out AwarenessInitializationError error, + out string errorMessage + ) + { + ARLog._Warn + ( + "Checking the status of Awareness features in a Remote ARSession is not yet implemented. " + + "Will always return a Ready status." + ); + + error = AwarenessInitializationError.None; + errorMessage = string.Empty; + + return AwarenessInitializationStatus.Ready; + } + + private void HandleDidUpdateFrame(ARSessionFrameUpdatedMessage message) + { + var frame = message.Frame; + UpdateGenerators(frame); + + _InvokeFrameUpdated(frame); + } + + private void _InvokeFrameUpdated(IARFrame frame) + { + CurrentFrame = frame; + + var handler = FrameUpdated; + if (handler != null) + { + var args = new FrameUpdatedArgs(frame); + handler(args); + } + } + + // TODO: Pull depth point cloud generation into an extension so this code isn't duplicated + // from _NativeARSession + private void UpdateGenerators(IARFrame frame) + { + if (!(Configuration is IARWorldTrackingConfiguration worldConfig)) + return; + + if (!worldConfig.IsDepthPointCloudEnabled) + return; + + var depthBuffer = frame.Depth; + if (depthBuffer == null || !depthBuffer.IsKeyframe) + return; + + // Create a generator if needed + if (_depthPointCloudGen == null) + { + _depthPointCloudGen = new DepthPointCloudGenerator(); + } + + // Generate the point cloud + var pointCloud = _depthPointCloudGen.GeneratePointCloud(frame.Depth, frame.Camera); + + var arFrame = (_IARFrame)frame; + arFrame.DepthPointCloud = pointCloud; + } + + private void HandleAddedAnchor(ARSessionAddedCustomAnchorMessage message) + { + ARLog._DebugFormat + ( + "Added anchor (editor: {0}, device: {1} ", + false, + message.EditorIdentifier, + message.Anchor.Identifier + ); + + // There is a small chance this message will get received/handled after the anchor gets + // surfaced through HandleDidAddAnchors, but that will get fixed once networking reliability + // gets fixed. So just add the anchors here instead of also adding them in HandleDidAddAnchors. + + _editorToDeviceAnchorIdentifiers.Add(message.EditorIdentifier, message.Anchor.Identifier); + _deviceToEditorAnchorIdentifiers.Add(message.Anchor.Identifier, message.EditorIdentifier); + } + + private void HandleDidAddAnchors(ARSessionAnchorsAddedMessage message) + { + var anchors = + new IARAnchor + [ + message.Anchors.Length + + message.PlaneAnchors.Length + + message.ImageAnchors.Length + ]; + + var i = 0; + foreach (var anchor in message.Anchors) + { + // This returns the same IARAnchor object as in the AddAnchor method, + // same as in _NativeARSession. + if (_deviceToEditorAnchorIdentifiers.TryGetValue(anchor.Identifier, out Guid id)) + { + var editorAnchor = _editorAnchors[id]; + editorAnchor.Transform = anchor.Transform; // This might not be needed + anchors[i++] = editorAnchor; + } + else + { + ARLog._WarnFormat + ( + "An anchor was added by the device session that was not added by the editor session." + ); + + anchors[i++] = anchor; + } + } + + foreach (var anchor in message.PlaneAnchors) + { + anchors[i++] = anchor; + } + + foreach (var anchor in message.ImageAnchors) + { + anchors[i++] = anchor; + } + + var handler = AnchorsAdded; + if (handler != null) + { + var args = new AnchorsArgs(anchors); + handler(args); + } + } + + private void HandleDidUpdateAnchors(ARSessionAnchorsUpdatedMessage message) + { + var anchors = + new IARAnchor + [ + message.Anchors.Length + + message.PlaneAnchors.Length + + message.ImageAnchors.Length + ]; + + var i = 0; + foreach (var anchor in message.Anchors) + { + if (_deviceToEditorAnchorIdentifiers.TryGetValue(anchor.Identifier, out Guid id)) + { + var editorAnchor = _editorAnchors[id]; + editorAnchor.Transform = anchor.Transform; + anchors[i++] = anchor; + } + else + { + ARLog._WarnFormat + ( + "An anchor was updated by the device session that was not added by the editor session." + ); + + anchors[i++] = anchor; + } + } + + foreach (var anchor in message.PlaneAnchors) + { + anchors[i++] = anchor; + } + + foreach (var anchor in message.ImageAnchors) + { + anchors[i++] = anchor; + } + + var handler = AnchorsUpdated; + if (handler != null) + { + var args = new AnchorsArgs(anchors); + handler(args); + } + } + + private void HandleDidRemoveAnchors(ARSessionAnchorsRemovedMessage message) + { + var anchors = + new IARAnchor + [ + message.Anchors.Length + + message.PlaneAnchors.Length + + message.ImageAnchors.Length + ]; + + var i = 0; + foreach (var anchor in message.Anchors) + { + if (_deviceToEditorAnchorIdentifiers.TryGetValue(anchor.Identifier, out Guid id)) + { + var editorAnchor = _editorAnchors[id]; + anchors[i++] = editorAnchor; + + _editorAnchors.Remove(id); + _editorToDeviceAnchorIdentifiers.Remove(id); + _deviceToEditorAnchorIdentifiers.Remove(anchor.Identifier); + } + else + { + ARLog._WarnFormat + ( + "An anchor was removed by the device session that was not added by the editor session." + ); + + anchors[i++] = anchor; + } + } + + foreach (var anchor in message.PlaneAnchors) + { + anchors[i++] = anchor; + } + + foreach (var anchor in message.ImageAnchors) + { + anchors[i++] = anchor; + } + + var handler = AnchorsRemoved; + if (handler != null) + { + var args = new AnchorsArgs(anchors); + handler(args); + } + } + + private void HandleDidMergeAnchors(ARSessionAnchorsMergedMessage message) + { + IARAnchor parent = message.ParentAnchor; + + var handler = AnchorsMerged; + if (handler != null) + { + var args = new AnchorsMergedArgs(parent, message.ChildAnchors); + handler(args); + } + } + + private void HandleDidAddMaps(ARSessionMapsAddedMessage message) + { + var handler = MapsAdded; + if (handler != null) + { + var args = new MapsArgs(message.Maps); + handler(args); + } + } + + private void HandleDidUpdateMaps(ARSessionMapsUpdatedMessage message) + { + var handler = MapsUpdated; + if (handler != null) + { + var args = new MapsArgs(message.Maps); + handler(args); + } + } + + private void HandleCameraDidChangeTrackingState + ( + ARSessionCameraTrackingStateChangedMessage message + ) + { + var camera = message.Camera; + + var handler = CameraTrackingStateChanged; + if (handler != null) + { + var args = new CameraTrackingStateChangedArgs(camera, camera.TrackingState); + handler(args); + } + } + + private void HandleSessionWasInterrupted(ARSessionWasInterruptedMessage message) + { + var handler = SessionInterrupted; + handler?.Invoke(new ARSessionInterruptedArgs()); + } + + private void HandleSessionInterruptionEnded(ARSessionInterruptionEndedMessage message) + { + var handler = SessionInterruptionEnded; + if (handler != null) + handler(new ARSessionInterruptionEndedArgs()); + } + + private void HandleDidFailWithError(ARSessionFailedMessage message) + { + var handler = SessionFailed; + if (handler != null) + { + var args = new ARSessionFailedArgs(message.Error); + handler(args); + } + } + + private ArdkEventHandler _onDidRun; + public event ArdkEventHandler Ran + { + add + { + _onDidRun += value; + + if (State == ARSessionState.Running) + value(new ARSessionRanArgs()); + } + remove => _onDidRun -= value; + } + + public event ArdkEventHandler Paused; + public event ArdkEventHandler Deinitialized; + + public event ArdkEventHandler SessionInterrupted; + public event ArdkEventHandler SessionInterruptionEnded; + public event ArdkEventHandler SessionFailed; + public event ArdkEventHandler CameraTrackingStateChanged; + + public event ArdkEventHandler FrameUpdated; + public event ArdkEventHandler AnchorsMerged; + public event ArdkEventHandler AnchorsAdded; + public event ArdkEventHandler AnchorsUpdated; + public event ArdkEventHandler AnchorsRemoved; + public event ArdkEventHandler MapsAdded; + public event ArdkEventHandler MapsUpdated; + + RuntimeEnvironment IARSession.RuntimeEnvironment { get => RuntimeEnvironment.Remote; } + + public bool IsPlayback { get => false; } + + public IARMesh Mesh + { + get => _meshDataParser; + } + + private readonly _MeshDataParser _meshDataParser = new _MeshDataParser(); + + void IARSession.SetupLocationService(ILocationService locationService) + { + // Todo: figure out support + throw new NotSupportedException("LocationService is not supported with Remote ARSessions."); + } + + event ArdkEventHandler IARSession.QueryingShouldSessionAttemptRelocalization + { + add { /* Do nothing. */ } + remove { /* Do nothing. */} + } + } +} diff --git a/Assets/ARDK/VirtualStudio/AR/_RemoteEditorARSession.cs.meta b/Assets/ARDK/VirtualStudio/AR/_RemoteEditorARSession.cs.meta new file mode 100644 index 0000000..70c947a --- /dev/null +++ b/Assets/ARDK/VirtualStudio/AR/_RemoteEditorARSession.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 17ab42765d074f9a9a0b616038122156 +timeCreated: 1595613049 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/ISessionMediator.cs b/Assets/ARDK/VirtualStudio/ISessionMediator.cs new file mode 100644 index 0000000..fc8a479 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/ISessionMediator.cs @@ -0,0 +1,13 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using Niantic.ARDK.Utilities.Collections; + +namespace Niantic.ARDK.VirtualStudio +{ + public interface ISessionMediator : IDisposable + { + //bool HasSession(Guid stageIdentifier); + + } +} \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/ISessionMediator.cs.meta b/Assets/ARDK/VirtualStudio/ISessionMediator.cs.meta new file mode 100644 index 0000000..f19238c --- /dev/null +++ b/Assets/ARDK/VirtualStudio/ISessionMediator.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c9ef94e8891d40b9bbfacc21f241d82a +timeCreated: 1579731590 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/IVirtualStudioManager.cs b/Assets/ARDK/VirtualStudio/IVirtualStudioManager.cs new file mode 100644 index 0000000..81382ce --- /dev/null +++ b/Assets/ARDK/VirtualStudio/IVirtualStudioManager.cs @@ -0,0 +1,33 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.Networking; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.VirtualStudio.AR; +using Niantic.ARDK.VirtualStudio.AR.Networking; +using Niantic.ARDK.VirtualStudio.Networking; + +namespace Niantic.ARDK.VirtualStudio +{ + internal interface _IVirtualStudioManager: IDisposable + { + _IEditorARSessionMediator ArSessionMediator { get; } + + _IEditorMultipeerSessionMediator MultipeerMediator { get; } + + _IEditorARNetworkingSessionMediator ArNetworkingMediator { get; } + + MockPlayConfiguration PlayConfiguration { get; } + + MockPlayer LocalPlayer { get; } + + MockPlayer GetPlayer(string playerName); + + MockPlayer GetPlayer(Guid stageIdentifier); + + MockPlayer GetPlayerWithPeer(IPeer peer); + + void InitializeForConfiguration(MockPlayConfiguration playConfiguration); + } +} \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/IVirtualStudioManager.cs.meta b/Assets/ARDK/VirtualStudio/IVirtualStudioManager.cs.meta new file mode 100644 index 0000000..33b1154 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/IVirtualStudioManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 65285be301a5e4c0a92481628b3eb07c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VirtualStudio/MockArdkPlayerProfile.cs b/Assets/ARDK/VirtualStudio/MockArdkPlayerProfile.cs new file mode 100644 index 0000000..2539954 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/MockArdkPlayerProfile.cs @@ -0,0 +1,97 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.AR; + +using UnityEngine; + +namespace Niantic.ARDK.VirtualStudio +{ + [Serializable] + public sealed class MockArdkPlayerProfile + { + [SerializeField] private string _playerName; + [SerializeField] private bool _isActive = false; + + [SerializeField] private bool _usingAR = false; + [SerializeField] private bool _usingNetwork = false; + [SerializeField] private bool _usingARNetworking = false; + + public string PlayerName + { + get { return _playerName; } + } + + public bool IsActive + { + get { return _isActive; } + internal set { _isActive = value; } + } + + public bool UsingAR + { + get { return _usingAR; } + internal set { _usingAR = value; } + } + + public bool UsingNetwork + { + get { return _usingNetwork; } + internal set { _usingNetwork = value; } + } + + public bool UsingARNetworking + { + get { return _usingARNetworking; } + internal set { _usingARNetworking = value; } + } + + // Todo (long term): + // Revisit idea of enabling using either Mock or Remote AR in conjunction with Mock networking + internal RuntimeEnvironment RuntimeEnvironment + { + get { return RuntimeEnvironment.Mock; } + } + + internal Func SpawnPlayerObjectDelegate; + + public MockArdkPlayerProfile + ( + string playerName, + bool usingNetwork, + bool usingAR, + bool usingARNetworking, + bool isActive = true + ) + { + _playerName = playerName; + _usingNetwork = usingNetwork; + _usingAR = usingAR; + _usingARNetworking = usingARNetworking; + _isActive = isActive; + } + + internal GameObject SpawnPlayerObject() + { + return SpawnPlayerObjectDelegate(this); + } + + public MockPlayer GetPlayer() + { + return _VirtualStudioManager.Instance.GetPlayer(_playerName); + } + + public override string ToString() + { + return string.Format + ( + "{0}'s Profile (Networked [{1}], AR [{2}], ARNetworking [{3}])", + PlayerName, + UsingNetwork, + UsingAR, + UsingARNetworking + ); + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/MockArdkPlayerProfile.cs.meta b/Assets/ARDK/VirtualStudio/MockArdkPlayerProfile.cs.meta new file mode 100644 index 0000000..8f32407 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/MockArdkPlayerProfile.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5366ef3c9b074d6f995895aa3ddfb156 +timeCreated: 1579734483 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/MockPlayConfiguration.cs b/Assets/ARDK/VirtualStudio/MockPlayConfiguration.cs new file mode 100644 index 0000000..ad5cc1a --- /dev/null +++ b/Assets/ARDK/VirtualStudio/MockPlayConfiguration.cs @@ -0,0 +1,180 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; + +using Niantic.ARDK.AR.Configuration; +using Niantic.ARDK.External; +using Niantic.ARDK.Networking; +using Niantic.ARDK.Utilities.Collections; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; + +namespace Niantic.ARDK.VirtualStudio +{ + [CreateAssetMenu(fileName = "MockPlayConfiguration", menuName = "ARDK/MockPlayConfiguration", order = 0)] + public class MockPlayConfiguration: + ScriptableObject + { + [SerializeField] + private List _profiles; + + /// (Optional) Prefab that will spawn to represent active mock players. These spawned + /// GameObjects can be moved in the Unity Editor to change the player's broadcasted pose. + [SerializeField] + private GameObject _mockPlayerPrefab; + + private MockArdkPlayerProfile[] _activeProfiles; + + private _IVirtualStudioManager _virtualStudioManager; + + [NonSerialized] + internal bool _Initialized; + + public MockArdkPlayerProfile[] ActiveProfiles + { + get + { + if (!_Initialized) + _Initialize(); + + return _activeProfiles; + } + } + + private IReadOnlyCollection _readonlyProfiles; + + public IReadOnlyCollection Profiles + { + get + { + if (_readonlyProfiles == null) + _readonlyProfiles = _profiles.AsArdkReadOnly(); + + return _readonlyProfiles; + } + } + + /// + /// Initialize method for when when a non-Inspector defined MockPlayConfiguration + /// is needed. + /// + /// + /// + public void SetInspectorValues + ( + List profiles, + GameObject playerPrefab + ) + { + _profiles = profiles; + _mockPlayerPrefab = playerPrefab; + } + + /// + /// Constructs the required ARSession, MultipeerNetworking, and ARNetworking sessions for all + /// the mock players as defined in the list of MockArdkPlayerProfiles. + /// + internal void _Initialize(_IVirtualStudioManager virtualStudioManager = null) + { + if (_Initialized) + return; + + ARLog._DebugFormat("Initializing all mock players in {0}", objs: name); + _Initialized = true; + _virtualStudioManager = virtualStudioManager ?? _VirtualStudioManager.Instance; + + var activeProfiles = new List(); + + foreach (var profile in _profiles) + { + if (!profile.IsActive) + continue; + + profile.SpawnPlayerObjectDelegate = SpawnPlayerObject; + activeProfiles.Add(profile); + } + + _activeProfiles = activeProfiles.ToArray(); + _virtualStudioManager.InitializeForConfiguration(this); + } + + /// + /// Invokes the Join method on all the active players' IMultipeerNetworking components. + /// + /// Metadata of session to join. + public void ConnectAllPlayersNetworkings(byte[] sessionMetadata) + { + if (!_Initialized) + _Initialize(); + + foreach (var profile in ActiveProfiles) + { + var player = profile.GetPlayer(); + if (player.Networking != null) + player.Networking.Join(sessionMetadata); + } + } + + /// + /// Invokes the Run method on all the active player's IARSession components. + /// + /// ARConfiguration to run with. + public void RunAllPlayersARSessions(IARConfiguration arConfiguration = null) + { + if (!_Initialized) + _Initialize(); + + foreach (var profile in ActiveProfiles) + { + var player = profile.GetPlayer(); + var config = arConfiguration ?? GetARConfiguration(profile); + if (player.ARSession != null) + player.ARSession.Run(config); + } + } + + /// + /// Returns the MockPlayer that owns the MultipeerNetworking session that the input peer + /// is the local ("self") peer of. + /// + /// + public MockPlayer GetPlayerWithPeer(IPeer peer) + { + if (!_Initialized) + _Initialize(); + + return _virtualStudioManager.GetPlayerWithPeer(peer); + } + + /// + /// Invoked when a new MockPlayer is constructed. This base method simply spawns a + /// pre-defined prefab, but it can be overriden by a child implementation of desired. + /// This will only be invoked for players defined in this MockPlayConfiguration, + /// ie only for remote mock players. A GameObject can be set for the local player through + /// the MockPlayer.SetPlayerObject method. + /// + /// + /// + protected virtual GameObject SpawnPlayerObject(MockArdkPlayerProfile profile) + { + if (_mockPlayerPrefab == null) + return null; + + var playerObject = Instantiate(_mockPlayerPrefab); + playerObject.name = profile.PlayerName + "_mock"; + + return playerObject; + } + + internal IARConfiguration GetARConfiguration(MockArdkPlayerProfile profile) + { + var config = ARWorldTrackingConfigurationFactory.Create(); + config.PlaneDetection = PlaneDetection.Horizontal | PlaneDetection.Vertical; + config.IsSharedExperienceEnabled = profile.UsingARNetworking; + + return config; + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/MockPlayConfiguration.cs.meta b/Assets/ARDK/VirtualStudio/MockPlayConfiguration.cs.meta new file mode 100644 index 0000000..8a786fc --- /dev/null +++ b/Assets/ARDK/VirtualStudio/MockPlayConfiguration.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 0a2a1ca87bf94f0eb168ebe0f4e9fb85 +timeCreated: 1580163037 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/MockPlayer.cs b/Assets/ARDK/VirtualStudio/MockPlayer.cs new file mode 100644 index 0000000..3707be8 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/MockPlayer.cs @@ -0,0 +1,240 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.Networking; +using Niantic.ARDK.VirtualStudio.AR; +using Niantic.ARDK.VirtualStudio.AR.Networking; +using Niantic.ARDK.Networking; +using Niantic.ARDK.Networking.MultipeerNetworkingEventArgs; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Logging; +using Niantic.ARDK.VirtualStudio.AR.Networking.Mock; +using Niantic.ARDK.VirtualStudio.Networking; +using Niantic.ARDK.VirtualStudio.Networking.Mock; + +using UnityEngine; + +namespace Niantic.ARDK.VirtualStudio +{ + public sealed class MockPlayer + { + public IARSession ARSession + { + get { return _arSession; } + } + + public IMultipeerNetworking Networking + { + get { return _networking; } + } + + public IARNetworking ARNetworking + { + get { return _arNetworking; } + } + + public bool IsLocal { get; private set; } + + public string Name + { + get { return _playerName; } + } + + public GameObject GameObject + { + get { return _playerObject; } + } + + private IARSession _arSession; + private _MockMultipeerNetworking _networking; + private _MockARNetworking _arNetworking; + + private MockArdkPlayerProfile _playerProfile; + private string _playerName; + + private GameObject _playerObject; + private Transform _playerTransform; + + private MessageHandlerBase _messageHandler; + + internal MockPlayer + ( + _IVirtualStudioManager virtualStudioMaster, + MockArdkPlayerProfile playerProfile = null + ) + { + if (playerProfile != null) + { + _playerProfile = playerProfile; + _playerName = playerProfile.PlayerName; + SetMessageHandler(new DefaultMessageHandler()); + } + else + { + _playerName = _VirtualStudioManager.LOCAL_PLAYER_NAME; + IsLocal = true; + } + + ARLog._DebugFormat("Initialized Player {0}", objs: _playerName); + } + + internal void SetARSession(IARSession arSession) + { + _arSession = arSession; + + if (!IsLocal) + { + _arSession.Ran += + args => + { + if (_playerObject == null) + { + var playerObject = _playerProfile.SpawnPlayerObject(); + SetPlayerObject(playerObject); + } + }; + } + } + + internal void SetMultipeerNetworking(_MockMultipeerNetworking networking) + { + if (networking == null) + { + _networking.PeerDataReceived -= HandlePeerDataReceived; + _networking = null; + return; + } + + if (_networking != null) + { + ARLog._Warn + ( + "Multiple active MultipeerNetworking instances were found, but MockPlayer " + + "will only keep a reference to and listen for messages from the first one." + ); + return; + } + + networking.PeerDataReceived += HandlePeerDataReceived; + _networking = networking; + } + + internal void SetARNetworking(_MockARNetworking arNetworking) + { + _arNetworking = arNetworking; + } + + internal void SetTransform(Transform transform) + { + if (_playerTransform == null) + return; + + _playerTransform.SetPositionAndRotation(transform.position, transform.rotation); + } + + /// + /// Associates the input GameObject with this MockPlayer. If this MockPlayer has an + /// ARNetworking session, the transform of the GameObject will be used as the peer's pose. + /// + /// + public void SetPlayerObject(GameObject playerObject) + { + // Todo: Optionally destroy the old object and replace with new? + if (_playerObject != null) + { + ARLog._WarnFormat("The MockPlayer {0} already has a GameObject.", objs: this); + return; + } + + // Could happen if no mock player prefab is set on the MockPlayConfiguration + if (playerObject == null) + return; + + _playerObject = playerObject; + _playerTransform = playerObject.transform; + _UpdateLoop.Tick += BroadcastPoseOnTick; + } + + public void SetPeerState(PeerState state) + { + if (_arNetworking == null || !_arNetworking.Networking.IsConnected) + { + ARLog._Error("Cannot set the PeerState of a player not connected to an ARNetworking session."); + return; + } + + _arNetworking.BroadcastState(state); + } + + private void BroadcastPoseOnTick() + { + if (_arNetworking != null && + _arSession.State == ARSessionState.Running && + _arNetworking.LocalPeerState == PeerState.Stable) + { + _arNetworking.BroadcastPose + ( + Matrix4x4.TRS + ( + _playerTransform.position, + _playerTransform.rotation, + _playerTransform.localScale + ), + Time.deltaTime + ); + } + } + + /// Inject a custom MessageHandlerBase implementation for this player to handle network + /// messages through. If a custom one is not set, a default message handler that prints + /// messages to the console will be used. + /// @param handler + public void SetMessageHandler(MessageHandlerBase handler) + { + if (IsLocal) + { + var msg = + "The local player should handle messages by subscribing to the " + + "IMultipeerNetworking.PeerDataReceived event."; + + ARLog._Error(msg); + return; + } + + _messageHandler = handler; + _messageHandler.SetOwningPlayer(this); + } + + private void HandlePeerDataReceived(PeerDataReceivedArgs args) + { + if (_messageHandler != null) + _messageHandler.HandleMessage(args); + } + + public override string ToString() + { + return ToString(-1); + } + + public string ToString(int identifierLength) + { + var peerString = string.Empty; + + if (Networking == null || !Networking.IsConnected) + { + peerString = "None"; + } + else + { + if (identifierLength < 0) + peerString = Networking.Self.ToString(); + else + peerString = Networking.Self.ToString(identifierLength); + } + + return string.Format("{0} ({1})", _playerName, peerString); + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/MockPlayer.cs.meta b/Assets/ARDK/VirtualStudio/MockPlayer.cs.meta new file mode 100644 index 0000000..eadb349 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/MockPlayer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f7641d0af1a9459ea2320348cfd8911d +timeCreated: 1580174168 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/Networking.meta b/Assets/ARDK/VirtualStudio/Networking.meta new file mode 100644 index 0000000..14da681 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Networking.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: dc88a80d654248dc90ad0d5477c62daf +timeCreated: 1579043184 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/Networking/ARSimHandlers.meta b/Assets/ARDK/VirtualStudio/Networking/ARSimHandlers.meta new file mode 100644 index 0000000..64c88d6 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Networking/ARSimHandlers.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 27a25bdfbd6742b5bb399e1d442ac391 +timeCreated: 1598482050 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/Networking/ARSimHandlers/MockARSimBase.cs b/Assets/ARDK/VirtualStudio/Networking/ARSimHandlers/MockARSimBase.cs new file mode 100644 index 0000000..2864562 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Networking/ARSimHandlers/MockARSimBase.cs @@ -0,0 +1,119 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; + +using Niantic.ARDK.AR; +using Niantic.ARDK.Networking; +using Niantic.ARDK.Networking.MultipeerNetworkingEventArgs; +using Niantic.ARDK.Utilities.Logging; +using Niantic.ARDK.VirtualStudio.Networking.Mock; + +using UnityEngine; + +namespace Niantic.ARDK.VirtualStudio.Networking.ARSimHandlers +{ + /// + /// Extend this to mock an ARSim server. It will receive messages sent by clients, and provide + /// hooks to invoke ARM messages, statuses, and results. + /// Networking sessions that interact with this mock server need to be explicitly registered, + /// rather than having this tool automatically handle all created sessions. + /// Also adds a hook for invoking a `PersistentKeyValueUpdated` for registered networkings only, + /// since ARSim uses the Key-Value store for some functionality + /// + public abstract class MockARSimBase : IDisposable + { + private readonly List<_MockMultipeerNetworking> _routers = + new List<_MockMultipeerNetworking>(); + + public void RegisterNetworking(IMultipeerNetworking networking) + { + var router = networking as _MockMultipeerNetworking; + if (router == null) + { + ARLog._Error("Cannot register networking sessions that are not mock sessions"); + return; + } + + _routers.Add(router); + router.ArmDataReceivedFromClient += HandleDataReceivedFromClient; + } + + public void UnregisterNetworking(IMultipeerNetworking networking) + { + var router = networking as _MockMultipeerNetworking; + if (router == null) + { + ARLog._Error("Cannot unregister networking sessions that are not mock sessions"); + return; + } + + _routers.Remove(router); + router.ArmDataReceivedFromClient -= HandleDataReceivedFromClient; + } + + public void SendMessageToClients(uint tag, byte[] data) + { + if(_routers.Count == 0) + return; + + var args = new DataReceivedFromArmArgs(tag, data); + foreach (var router in _routers) + { + router._ReceiveDataFromArm(args); + } + } + + public void SendStatusToClients(uint status) + { + if(_routers.Count == 0) + return; + + var args = new SessionStatusReceivedFromArmArgs(status); + foreach (var router in _routers) + { + router._ReceiveStatusFromArm(args); + } + } + + public void SendResultToClients(uint outcome, byte[] details) + { + if(_routers.Count == 0) + return; + + var args = new SessionResultReceivedFromArmArgs(outcome, details); + foreach (var router in _routers) + { + router._ReceiveResultFromArm(args); + } + } + + // Only executes the event for the routers explicitly registered to this handler, since + // trying to execute on every connected session may lead to duplicate events. For + // the sake of mocking, just considering the explicit sessions should be enough. + public void SetKeyValuePair(string key, byte[] value) + { + foreach (var router in _routers) + { + router.ReceivePersistentKeyValue(key, value); + } + } + + public void Dispose() + { + foreach (var router in _routers) + { + router.ArmDataReceivedFromClient -= HandleDataReceivedFromClient; + } + + _routers.Clear(); + } + + protected abstract void DataReceivedFromClient(PeerDataReceivedArgs args); + + private void HandleDataReceivedFromClient(PeerDataReceivedArgs args) + { + DataReceivedFromClient(args); + } + } +} diff --git a/Assets/ARDK/VirtualStudio/Networking/ARSimHandlers/MockARSimBase.cs.meta b/Assets/ARDK/VirtualStudio/Networking/ARSimHandlers/MockARSimBase.cs.meta new file mode 100644 index 0000000..15f0eda --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Networking/ARSimHandlers/MockARSimBase.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 2dfd585b39b04003af7089fd10154989 +timeCreated: 1598482092 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/Networking/DefaultMessageHandler.cs b/Assets/ARDK/VirtualStudio/Networking/DefaultMessageHandler.cs new file mode 100644 index 0000000..425eb3e --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Networking/DefaultMessageHandler.cs @@ -0,0 +1,24 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Networking; +using Niantic.ARDK.Networking.MultipeerNetworkingEventArgs; + +using UnityEngine; + +namespace Niantic.ARDK.VirtualStudio.Networking +{ + public class DefaultMessageHandler : + MessageHandlerBase + { + public override void HandleMessage(PeerDataReceivedArgs args) + { + Debug.LogFormat + ( + "[Message Received] Tag: {0}, Sender: {1}, Data Length: {2}", + args.Tag, + args.Peer, + args.DataLength + ); + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/Networking/DefaultMessageHandler.cs.meta b/Assets/ARDK/VirtualStudio/Networking/DefaultMessageHandler.cs.meta new file mode 100644 index 0000000..7a474db --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Networking/DefaultMessageHandler.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 55181ea30f49444d8e5f39c690008fe5 +timeCreated: 1580174383 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/Networking/MessageHandlerBase.cs b/Assets/ARDK/VirtualStudio/Networking/MessageHandlerBase.cs new file mode 100644 index 0000000..aeb9ec8 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Networking/MessageHandlerBase.cs @@ -0,0 +1,24 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using Niantic.ARDK.Networking; +using Niantic.ARDK.Networking.MultipeerNetworkingEventArgs; + +namespace Niantic.ARDK.VirtualStudio.Networking +{ + public abstract class MessageHandlerBase + { + public MockPlayer OwningPlayer + { + get { return _owningPlayer; } + } + + private MockPlayer _owningPlayer; + + internal void SetOwningPlayer(MockPlayer player) + { + _owningPlayer = player; + } + + public abstract void HandleMessage(PeerDataReceivedArgs args); + } +} \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/Networking/MessageHandlerBase.cs.meta b/Assets/ARDK/VirtualStudio/Networking/MessageHandlerBase.cs.meta new file mode 100644 index 0000000..e7c2dda --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Networking/MessageHandlerBase.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 0102df732ac3455484945e29e53105b4 +timeCreated: 1585351011 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/Networking/_IEditorMultipeerSessionMediator.cs b/Assets/ARDK/VirtualStudio/Networking/_IEditorMultipeerSessionMediator.cs new file mode 100644 index 0000000..b4316cc --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Networking/_IEditorMultipeerSessionMediator.cs @@ -0,0 +1,24 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; + +using Niantic.ARDK.AR; +using Niantic.ARDK.Networking; +using Niantic.ARDK.Utilities.Collections; +using Niantic.ARDK.VirtualStudio.Networking.Mock; + +namespace Niantic.ARDK.VirtualStudio.Networking +{ + internal interface _IEditorMultipeerSessionMediator: + ISessionMediator + { + _MockMultipeerNetworking CreateNonLocalSession(Guid stageIdentifier, RuntimeEnvironment source); + + IReadOnlyCollection<_MockMultipeerNetworking> GetConnectedSessions(Guid stageIdentifier); + + _MockMultipeerNetworking GetSession(Guid stageIdentifier); + + IPeer GetHostIfSet(byte[] sessionMetadata); + } +} \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/Networking/_IEditorMultipeerSessionMediator.cs.meta b/Assets/ARDK/VirtualStudio/Networking/_IEditorMultipeerSessionMediator.cs.meta new file mode 100644 index 0000000..e1578be --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Networking/_IEditorMultipeerSessionMediator.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: b5ba64d8a9dc4c8a9ab24e6a5d0c576a +timeCreated: 1607713552 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/Networking/_MockMultipeerNetworking.cs b/Assets/ARDK/VirtualStudio/Networking/_MockMultipeerNetworking.cs new file mode 100644 index 0000000..7baa18c --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Networking/_MockMultipeerNetworking.cs @@ -0,0 +1,372 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Linq; + +using Niantic.ARDK.AR; +using Niantic.ARDK.Networking; +using Niantic.ARDK.Networking.Clock; +using Niantic.ARDK.Networking.MultipeerNetworkingEventArgs; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Collections; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; + +namespace Niantic.ARDK.VirtualStudio.Networking.Mock +{ + internal sealed class _MockMultipeerNetworking: + IMultipeerNetworking + { + private readonly _IVirtualStudioManager _virtualStudioManager; + + public Guid StageIdentifier { get; } + public bool IsConnected { get; private set; } + + /// + public IPeer Self { get; private set; } + + /// + public IPeer Host { get; private set; } + + /// + public IReadOnlyCollection OtherPeers + { + get { return _readOnlyPeers; } + } + + /// + public ICoordinatedClock CoordinatedClock + { + get + { + throw new NotImplementedException(); + } + } + + public byte[] JoinedSessionMetadata { get; private set; } + + private readonly Dictionary _peers = new Dictionary(); + private ARDKReadOnlyCollection _readOnlyPeers; + + internal _MockMultipeerNetworking + ( + Guid stageIdentifier, + _IVirtualStudioManager virtualStudioMaster + ) + { + _FriendTypeAsserter.AssertCallerIs(typeof(MultipeerNetworkingFactory)); + + StageIdentifier = stageIdentifier; + _virtualStudioManager = virtualStudioMaster; + + _readOnlyPeers = _peers.Values.AsArdkReadOnly(); + } + + private bool _isDestroyed; + public void Dispose() + { + GC.SuppressFinalize(this); + + if (_isDestroyed) + return; + + _isDestroyed = true; + + if (IsConnected) + Leave(); + + var handler = Deinitialized; + if (handler != null) + { + var args = new DeinitializedArgs(); + handler(args); + } + } + + public void Join(byte[] metadata, byte[] token = null, long timestamp = 0) + { + if (metadata == null || metadata.Length == 0) + throw new ArgumentException("Cannot be null or empty.", nameof(metadata)); + + if (IsConnected) + { + ARLog._Warn + ( + metadata.SequenceEqual(JoinedSessionMetadata) + ? "ARDK: Already joined this session." + : "ARDK: Already connected to a different session." + ); + return; + } + + JoinedSessionMetadata = metadata; + + Self = new _MockPeer(Guid.NewGuid(), StageIdentifier); + Host = _virtualStudioManager.MultipeerMediator.GetHostIfSet(metadata) ?? Self; + IsConnected = true; + + // Raise Connected event before calling AddPeer (which will raise AddedPeer), + // because peers can only be added to connected networkings + var handler = _connected; + if (handler != null) + handler(new ConnectedArgs(Self, Host)); + + if (_virtualStudioManager == null || _virtualStudioManager.MultipeerMediator == null) + return; + + var connectedNetworkings = + _virtualStudioManager.MultipeerMediator.GetConnectedSessions(StageIdentifier); + + if (connectedNetworkings != null && connectedNetworkings.Count > 0) + { + // If this networking joined an already existing session, + // add the relevant peers to each networking + foreach (var networking in connectedNetworkings) + { + if (networking.StageIdentifier != StageIdentifier) + { + AddPeer(networking.Self); + networking.AddPeer(Self); + } + } + } + } + + public void Leave() + { + if (!IsConnected) + return; + + var connectedNetworkings = + _virtualStudioManager.MultipeerMediator.GetConnectedSessions(StageIdentifier); + + if (connectedNetworkings != null && connectedNetworkings.Count > 0) + { + // Remove the peer from the remaining connected networkings + foreach (var networking in connectedNetworkings) + { + if (networking.StageIdentifier != StageIdentifier) + networking.RemovePeer(Self); + } + } + + JoinedSessionMetadata = null; + Self = null; + Host = null; + IsConnected = false; + _peers.Clear(); + + var handler = Disconnected; + if (handler != null) + handler(new DisconnectedArgs()); + } + + public void SendDataToPeer + ( + uint tag, + byte[] data, + IPeer peer, + TransportType transportType, + bool sendToSelf = false + ) + { + var receivers = new List { peer }; + SendDataToPeers(tag, data, receivers, transportType); + } + + public void SendDataToPeers + ( + uint tag, + byte[] data, + IEnumerable peers, + TransportType transportType, + bool sendToSelf = false + ) + { + if (!IsConnected) + { + ARLog._Error("Cannot send data to peers while not connected to a networking session."); + return; + } + + // In the native implementation, the local peer would always receive the message before + // other peers (since it is a local event and not sent through the network) if sending + // to self, which is why this ordering should be maintained. + if (sendToSelf) + ReceiveDataFromPeer(tag, Self, transportType, data); + + foreach (var peer in peers) + { + var mockPeer = (_MockPeer) peer; + var receiverNetworking = + _virtualStudioManager.MultipeerMediator.GetSession(mockPeer.StageIdentifier); + + receiverNetworking.ReceiveDataFromPeer(tag, Self, transportType, data); + } + } + + public void BroadcastData + ( + uint tag, + byte[] data, + TransportType transportType, + bool sendToSelf = false + ) + { + SendDataToPeers(tag, data, OtherPeers, transportType, sendToSelf); + } + + private void ReceiveDataFromPeer + ( + uint tag, + IPeer peer, + TransportType transportType, + byte[] data + ) + { + var handler = PeerDataReceived; + if (handler != null) + { + var args = + new PeerDataReceivedArgs(peer, tag, transportType, data); + + handler(args); + } + } + + /// + /// Internal event to notify listeners that an _EditorMultipeerNetworking has sent some data + /// to the Arm server. + /// + internal ArdkEventHandler ArmDataReceivedFromClient; + + public void SendDataToArm(uint tag, byte[] data) + { + var handler = ArmDataReceivedFromClient; + if (handler != null) + { + var args = new PeerDataReceivedArgs(Self, tag, TransportType.ReliableOrdered, data); + handler(args); + } + } + + public void StorePersistentKeyValue(string key, byte[] value) + { + var connectedNetworkings = + _virtualStudioManager.MultipeerMediator.GetConnectedSessions(StageIdentifier); + + foreach (var networking in connectedNetworkings) + networking.ReceivePersistentKeyValue(key, value); + } + + public void ReceivePersistentKeyValue(string key, byte[] value) + { + var handler = PersistentKeyValueUpdated; + if (handler != null) + handler(new PersistentKeyValueUpdatedArgs(key, value)); + } + + public void FailConnectionWithError(uint errorCode) + { + var handler = ConnectionFailed; + if (handler != null) + handler(new ConnectionFailedArgs(errorCode)); + } + + private void AddPeer(IPeer peer) + { + _peers.Add(peer.Identifier, peer); + + var handler = PeerAdded; + if (handler != null) + handler(new PeerAddedArgs(peer)); + } + + private void RemovePeer(IPeer peer) + { + _peers.Remove(peer.Identifier); + + if (peer.Equals(Host)) + Host = null; + + var handler = PeerRemoved; + if (handler != null) + handler(new PeerRemovedArgs(peer)); + } + + /// + /// Call to invoke a DataReceivedFromArm event on this _MockNetworkingCommandsRouter. + /// + /// + internal void _ReceiveDataFromArm(DataReceivedFromArmArgs args) + { + var handler = DataReceivedFromArm; + + if (handler != null) + handler(args); + } + + /// + /// Call to invoke a SessionStatusReceivedFromArm event on this _MockNetworkingCommandsRouter. + /// + /// + internal void _ReceiveStatusFromArm(SessionStatusReceivedFromArmArgs args) + { + var handler = SessionStatusReceivedFromArm; + + if (handler != null) + handler(args); + } + + /// + /// Call to invoke a SessionResultReceivedFromArm event on this _MockNetworkingCommandsRouter. + /// + /// + internal void _ReceiveResultFromArm(SessionResultReceivedFromArmArgs args) + { + var handler = SessionResultReceivedFromArm; + + if (handler != null) + handler(args); + } + + public RuntimeEnvironment RuntimeEnvironment + { + get { return RuntimeEnvironment.Mock; } + } + + public string ToString(int count) + { + return string.Format("_MockMultipeerNetworking (ID: {0})", StageIdentifier); + } + + public event ArdkEventHandler ConnectionFailed; + public event ArdkEventHandler Disconnected; + public event ArdkEventHandler PeerDataReceived; + public event ArdkEventHandler PeerAdded; + public event ArdkEventHandler PeerRemoved; + public event ArdkEventHandler PersistentKeyValueUpdated; + public event ArdkEventHandler Deinitialized; + + public event ArdkEventHandler DataReceivedFromArm; + public event ArdkEventHandler SessionStatusReceivedFromArm; + public event ArdkEventHandler SessionResultReceivedFromArm; + + private ArdkEventHandler _connected; + public event ArdkEventHandler Connected + { + add + { + _connected += value; + if (IsConnected) + { + var args = new ConnectedArgs(Self, Host); + value(args); + } + } + remove { _connected -= value; } + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/Networking/_MockMultipeerNetworking.cs.meta b/Assets/ARDK/VirtualStudio/Networking/_MockMultipeerNetworking.cs.meta new file mode 100644 index 0000000..474a870 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Networking/_MockMultipeerNetworking.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: b1cf105fd8fd491eb8778f138e61b2b4 +timeCreated: 1579819254 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/Networking/_MockNetworkingSessionsMediator.cs b/Assets/ARDK/VirtualStudio/Networking/_MockNetworkingSessionsMediator.cs new file mode 100644 index 0000000..1a6564b --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Networking/_MockNetworkingSessionsMediator.cs @@ -0,0 +1,268 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; + +using Niantic.ARDK.AR; +using Niantic.ARDK.Networking; +using Niantic.ARDK.Networking.MultipeerNetworkingEventArgs; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Collections; +using Niantic.ARDK.Utilities.Logging; +using Niantic.ARDK.VirtualStudio.Networking.Mock; + +using UnityEngine; + +namespace Niantic.ARDK.VirtualStudio.Networking +{ + internal sealed class _MockNetworkingSessionsMediator: + _IEditorMultipeerSessionMediator + { + private readonly Dictionary _stageIdentifierToSession = + new Dictionary(); + + // StageIdentifier --> SessionMetadata + // Since the _EditorMultipeerNetworking.JoinedSessionMetadata will be null when the disconnected + // event is raised, but this mediator needs to know which session was left + private readonly Dictionary _stageIdentifierToMetadata = + new Dictionary(); + + // StageIdentifier --> PeerIdentifier + // Need to keep track of mapping because IMultipeerNetworking.Self can be null + // when the disconnected event is raised, but this mediator needs to know which peer + // it was that left + private readonly Dictionary _stageToPeerIdentifier = new Dictionary(); + + // SessionMetadata --> Collection of all sessions connected with that metadata + private readonly Dictionary> _metadataToSession = + new Dictionary>(_ByteArrayComparer.Instance); + + private sealed class _MultipeerHelper + { + private readonly _MockNetworkingSessionsMediator _owner; + private readonly _MockMultipeerNetworking _networking; + + internal _MultipeerHelper + ( + _MockNetworkingSessionsMediator owner, + _MockMultipeerNetworking networking + ) + { + _owner = owner; + _networking = networking; + + networking.Connected += _Connected; + networking.Disconnected += _Disconnected; + networking.Deinitialized += Deinitialized; + } + + internal void _Dispose() + { + _networking.Connected -= _Connected; + _networking.Disconnected -= _Disconnected; + _networking.Deinitialized -= Deinitialized; + } + + private void _Connected(ConnectedArgs args) + { + _owner._HandleAnyConnected(_networking); + } + + private void _Disconnected(DisconnectedArgs args) + { + _owner._HandleAnyDisconnected(_networking); + } + + private void Deinitialized(DeinitializedArgs args) + { + _owner._stageIdentifierToSession.Remove(_networking.StageIdentifier); + _owner._multipeerHelpers.Remove(_networking); + } + } + + private static int _activeCount; + + internal static void _CheckActiveCountIsZero() + { + int activeCount = _activeCount; + if (activeCount != 0) + { + throw new InvalidOperationException + ( + "_MockNetworkingSessionsMediator active count is " + activeCount + "." + ); + } + } + + private readonly Dictionary _multipeerHelpers = + new Dictionary + ( + _ReferenceComparer.Instance + ); + + private _IVirtualStudioManager _virtualStudioManager; + + public _MockNetworkingSessionsMediator(_IVirtualStudioManager virtualStudioMaster) + { + _virtualStudioManager = virtualStudioMaster; + + MultipeerNetworkingFactory.NetworkingInitialized += HandleAnyInitialized; + MultipeerNetworkingFactory._NonLocalNetworkingInitialized += HandleAnyInitialized; + + Interlocked.Increment(ref _activeCount); + } + + private int _isDisposed; + public void Dispose() + { + // Dispose only once, in a thread safe manner. + if (Interlocked.CompareExchange(ref _isDisposed, 1, 0) != 0) + return; + + MultipeerNetworkingFactory.NetworkingInitialized -= HandleAnyInitialized; + MultipeerNetworkingFactory._NonLocalNetworkingInitialized -= HandleAnyInitialized; + + foreach (var networking in _stageIdentifierToSession.Values.ToArray()) + if (networking != null) + networking.Dispose(); + + foreach (var helper in _multipeerHelpers.Values) + helper._Dispose(); + + Interlocked.Decrement(ref _activeCount); + } + + public _MockMultipeerNetworking CreateNonLocalSession(Guid stageIdentifier, RuntimeEnvironment source) + { + var networking = + MultipeerNetworkingFactory._CreateVirtualStudioManagedNetworking + ( + source, + ServerConfiguration.ARBE, + stageIdentifier, + _virtualStudioManager, + isLocal: false + ); + + return (_MockMultipeerNetworking) networking; + } + + // Returned collection also includes the networking with the given stageIdentifier. + public IReadOnlyCollection<_MockMultipeerNetworking> GetConnectedSessions + ( + Guid stageIdentifier + ) + { + if (_stageIdentifierToMetadata.ContainsKey(stageIdentifier)) + { + var sessionMetadata = _stageIdentifierToMetadata[stageIdentifier]; + if (_metadataToSession.TryGetValue(sessionMetadata, out HashSet<_MockMultipeerNetworking> networkings)) + return networkings.AsArdkReadOnly(); + } + + return EmptyArdkReadOnlyCollection< _MockMultipeerNetworking>.Instance; + } + + private HashSet<_MockMultipeerNetworking> GetSessionsConnectedWithMetadata + ( + byte[] sessionMetadata + ) + { + HashSet<_MockMultipeerNetworking> networkings; + _metadataToSession.TryGetValue(sessionMetadata, out networkings); + return networkings; + } + + public _MockMultipeerNetworking GetSession(Guid stageIdentifier) + { + _MockMultipeerNetworking networking; + _stageIdentifierToSession.TryGetValue(stageIdentifier, out networking); + return networking; + } + + public IPeer GetHostIfSet(byte[] sessionMetadata) + { + HashSet<_MockMultipeerNetworking> networkings; + if (!_metadataToSession.TryGetValue(sessionMetadata, out networkings)) + { + // If this method was called before any networking implementations have raised AnyDidConnect + // using this sessionMetadata, the host will not have been set + return null; + } + + var connectedNetworking = networkings.First(); + return connectedNetworking.Host; + } + + private void HandleAnyInitialized(AnyMultipeerNetworkingInitializedArgs args) + { + var mockNetworking = args.Networking as _MockMultipeerNetworking; + if (mockNetworking == null) + { + ARLog._Error + ( + "While VirtualStudio is running mock networks, only other mock networking instances " + + "can be initialized." + ); + return; + } + + var helper = new _MultipeerHelper(this, mockNetworking); + _multipeerHelpers.Add(mockNetworking, helper); + + _stageIdentifierToSession.Add(mockNetworking.StageIdentifier, mockNetworking); + } + + private void _HandleAnyConnected(_MockMultipeerNetworking networking) + { + var joinedSessionMetadata = networking.JoinedSessionMetadata; + var connectedNetworkings = GetSessionsConnectedWithMetadata(joinedSessionMetadata); + + // This mapping has to be established first, to support the use case where + // messages are sent when handling a networking's DidAddPeer event + _stageToPeerIdentifier.Add(networking.StageIdentifier, networking.Self.Identifier); + _stageIdentifierToMetadata.Add(networking.StageIdentifier, joinedSessionMetadata); + + if (connectedNetworkings != null && connectedNetworkings.Count > 0) + connectedNetworkings.Add(networking); + else + { + // If this networking is the first to join, add a new entry to the dictionary + var hashset = new HashSet<_MockMultipeerNetworking> { networking }; + _metadataToSession.Add(joinedSessionMetadata, hashset); + } + } + + private void _HandleAnyDisconnected(_MockMultipeerNetworking networking) + { + byte[] sessionMetadata; + if (!_stageIdentifierToMetadata.TryGetValue(networking.StageIdentifier, out sessionMetadata)) + { + ARLog._Warn("Tried to disconnect a networking session that was not properly connected."); + return; + } + + var connectedNetworkings = GetSessionsConnectedWithMetadata(sessionMetadata); + if (connectedNetworkings == null || !connectedNetworkings.Contains(networking)) + { + ARLog._Warn("Tried to disconnect a networking session that was not properly connected."); + return; + } + + // Remove this networking from collections keeping track of connections + _stageIdentifierToMetadata.Remove(networking.StageIdentifier); + connectedNetworkings.Remove(networking); + + // Remove the networking's peer from collections keeping track of peers + _stageToPeerIdentifier.Remove(networking.StageIdentifier); + + if (connectedNetworkings.Count == 0) + { + // Clear metadata entry if no more networkings are connected with this metadata + _metadataToSession.Remove(sessionMetadata); + } + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/Networking/_MockNetworkingSessionsMediator.cs.meta b/Assets/ARDK/VirtualStudio/Networking/_MockNetworkingSessionsMediator.cs.meta new file mode 100644 index 0000000..aeedd48 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Networking/_MockNetworkingSessionsMediator.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 1ed40dae5681445ca0fde4608ea7e201 +timeCreated: 1579731608 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/Networking/_MockPeer.cs b/Assets/ARDK/VirtualStudio/Networking/_MockPeer.cs new file mode 100644 index 0000000..1d8c0d7 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Networking/_MockPeer.cs @@ -0,0 +1,23 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.Networking; + +namespace Niantic.ARDK.VirtualStudio.Networking.Mock +{ + /// + /// A remote representation of a peer. + /// + internal sealed class _MockPeer: + _Peer + { + public Guid StageIdentifier { get; private set; } + + public _MockPeer(Guid peerIdentifier, Guid stageIdentifier): + base(peerIdentifier) + { + StageIdentifier = stageIdentifier; + } + } +} diff --git a/Assets/ARDK/VirtualStudio/Networking/_MockPeer.cs.meta b/Assets/ARDK/VirtualStudio/Networking/_MockPeer.cs.meta new file mode 100644 index 0000000..08f69d8 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Networking/_MockPeer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 1966c7525897496591ac897ed630c4c3 +timeCreated: 1588273853 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/Networking/_RemoteEditorMultipeerNetworking.cs b/Assets/ARDK/VirtualStudio/Networking/_RemoteEditorMultipeerNetworking.cs new file mode 100644 index 0000000..a8d7406 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Networking/_RemoteEditorMultipeerNetworking.cs @@ -0,0 +1,555 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Linq; + +using Niantic.ARDK.AR; +using Niantic.ARDK.Utilities.Extensions; +using Niantic.ARDK.Networking; +using Niantic.ARDK.Networking.Clock; +using Niantic.ARDK.Networking.MultipeerNetworkingEventArgs; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Collections; +using Niantic.ARDK.Utilities.Logging; +using Niantic.ARDK.VirtualStudio.Remote; +using Niantic.ARDK.VirtualStudio.Remote.Data; + +using UnityEngine.Networking.PlayerConnection; + +namespace Niantic.ARDK.VirtualStudio.Remote +{ + /// + /// that will run on the editor to handle + /// logic for remote multipeer networking. + /// + /// All session command invoked through this object will be proxied to the remote device and all + /// events on the device will be proxied back to this object. + /// + internal sealed class _RemoteEditorMultipeerNetworking: + IMultipeerNetworking + { + public Guid StageIdentifier { get; } + public bool IsConnected { get; private set; } + + /// + public IPeer Self { get; private set; } + + /// + public IPeer Host { get; private set; } + + /// + public IReadOnlyCollection OtherPeers + { + get { return _readOnlyPeers; } + } + + /// + public ICoordinatedClock CoordinatedClock + { + get + { + // Todo: Implement a mock ICoordinatedClock + throw new NotSupportedException(); + } + } + + private readonly Dictionary _peers = new Dictionary(); + private ARDKReadOnlyCollection _readOnlyPeers; + + private byte[] _joinedSessionMetadata; + + public _RemoteEditorMultipeerNetworking(ServerConfiguration configuration, Guid stageIdentifier) + { + _FriendTypeAsserter.AssertCallerIs(typeof(MultipeerNetworkingFactory)); + + _readOnlyPeers = _peers.Values.AsArdkReadOnly(); + StageIdentifier = stageIdentifier; + + if (configuration.ClientMetadata == null) + configuration.GenerateRandomClientId(); + + _EasyConnection.Send + ( + new NetworkingInitMessage + { + Configuration = configuration, + StageIdentifier = stageIdentifier + }, + TransportType.ReliableOrdered + ); + + _RemoteConnection.Register + ( + NetworkingConnectedMessage.ID.Combine(stageIdentifier), + HandleDidConnectMessage + ); + + _RemoteConnection.Register + ( + NetworkingConnectionFailedWithErrorMessage + .ID.Combine(stageIdentifier), + HandleConnectionDidFailWithErrorMessage + ); + + _RemoteConnection.Register + ( + NetworkingDisconenctedMessage.ID.Combine(stageIdentifier), + HandleWillDisconnectMessage + ); + + _RemoteConnection.Register + ( + NetworkingPeerDataReceivedMessage.ID.Combine(stageIdentifier), + HandleDidReceiveDataFromPeer + ); + + _RemoteConnection.Register + ( + NetworkingPeerAddedMessage.ID.Combine(stageIdentifier), + HandleAddedPeerMessage + ); + + _RemoteConnection.Register + ( + NetworkingPeerRemovedMessage.ID.Combine(stageIdentifier), + HandleRemovedPeerMessage + ); + + _RemoteConnection.Register + ( + NetworkingDeinitializedMessage.ID.Combine(stageIdentifier), + HandleDeinitializingMessage + ); + + _RemoteConnection.Register + ( + NetworkingPersistentKeyValueUpdatedMessage.ID.Combine(stageIdentifier), + HandleUpdatedPersistentKeyValueMessage + ); + + _RemoteConnection.Register + ( + NetworkingDataReceivedFromArmMessage.ID.Combine(stageIdentifier), + HandleDataReceivedFromArmMessage + ); + + _RemoteConnection.Register + ( + NetworkingStatusReceivedFromArmMessage.ID.Combine(stageIdentifier), + HandleStatusReceivedFromArmMessage + ); + + _RemoteConnection.Register + ( + NetworkingResultReceivedFromArmMessage.ID.Combine(stageIdentifier), + HandleResultReceivedFromArmMessage + ); + } + + ~_RemoteEditorMultipeerNetworking() + { + ARLog._Error("_RemoteEditorMultipeerNetworking should be destroyed by an explicit call to Dispose()."); + } + + private bool _isDestroyed; + public void Dispose() + { + GC.SuppressFinalize(this); + + if (_isDestroyed) + return; + + _isDestroyed = true; + + if (IsConnected) + Leave(); + + var handler = Deinitialized; + if (handler != null) + handler(new DeinitializedArgs()); + + _RemoteConnection.Send + ( + NetworkingDestroyMessage.ID.Combine(StageIdentifier), + new NetworkingDestroyMessage().SerializeToArray(), + TransportType.ReliableOrdered + ); + } + + public void Join(byte[] metadata, byte[] token = null, long timestamp = 0) + { + if (metadata == null) + throw new ArgumentNullException(nameof(metadata)); + + if (IsConnected) + { + ARLog._Warn + ( + metadata.SequenceEqual(_joinedSessionMetadata) + ? "ARDK: Already joined this session." + : "ARDK: Already connected to a different session." + ); + return; + } + + _RemoteConnection.Send + ( + NetworkingJoinMessage.ID.Combine(StageIdentifier), + new NetworkingJoinMessage() { Metadata = metadata }.SerializeToArray(), + TransportType.ReliableOrdered + ); + } + + public void Leave() + { + if (!IsConnected) + return; + + _RemoteConnection.Send + ( + NetworkingLeaveMessage.ID.Combine(StageIdentifier), + new NetworkingLeaveMessage().SerializeToArray(), + TransportType.ReliableOrdered + ); + } + + public void SendDataToPeer + ( + uint tag, + byte[] data, + IPeer peer, + TransportType transportType, + bool sendToSelf = false + ) + { + var receivers = new List { peer }; + SendDataToPeers(tag, data, receivers, transportType); + } + + public void SendDataToPeers + ( + uint tag, + byte[] data, + IEnumerable peers, + TransportType transportType, + bool sendToSelf = false + ) + { + if (!IsConnected) + { + ARLog._Error("Cannot send data to peers while not connected to a networking session."); + return; + } + + // Same here as in _NativeMutlipeerNetworking + if (sendToSelf) + { + var handler = PeerDataReceived; + if (handler != null) + { + var args = new PeerDataReceivedArgs(Self, tag, transportType, data); + handler(args); + } + } + + var message = + new NetworkingSendDataToPeersMessage + { + TransportType = (byte) transportType, + Peers = peers.Select(peer => peer.Identifier).ToArray(), + Tag = tag, + Data = data + }; + + _RemoteConnection.Send + ( + NetworkingSendDataToPeersMessage.ID.Combine(StageIdentifier), + message.SerializeToArray(), + TransportType.ReliableOrdered + ); + } + + public void BroadcastData + ( + uint tag, + byte[] data, + TransportType transportType, + bool sendToSelf = false + ) + { + SendDataToPeers(tag, data, OtherPeers, transportType, sendToSelf); + } + + public void SendDataToArm(uint tag, byte[] data) + { + var message = + new NetworkingSendDataToArmMessage + { + Tag = tag, + Data = data + }; + + _RemoteConnection.Send + ( + NetworkingSendDataToArmMessage.ID.Combine(StageIdentifier), + message.SerializeToArray(), + TransportType.ReliableOrdered + ); + } + + public void StorePersistentKeyValue(string key, byte[] value) + { + var message = + new NetworkingStorePersistentKeyValueMessage + { + Key = System.Text.Encoding.UTF8.GetBytes(key), + Value = value + }; + + _RemoteConnection.Send + ( + NetworkingStorePersistentKeyValueMessage.ID.Combine(StageIdentifier), + message.SerializeToArray(), + TransportType.ReliableOrdered + ); + } + + private void HandleDidConnectMessage(MessageEventArgs e) + { + var message = e.data.DeserializeFromArray(); + + IsConnected = true; + Self = _Peer.FromIdentifier(message.SelfIdentifier); + Host = _Peer.FromIdentifier(message.HostIdentifier); + + var handler = _connected; + if (handler != null) + handler(new ConnectedArgs(Self, Host)); + } + + private void HandleConnectionDidFailWithErrorMessage(MessageEventArgs e) + { + var message = e.data.DeserializeFromArray(); + + var handler = ConnectionFailed; + if (handler != null) + handler(new ConnectionFailedArgs(message.ErrorCode)); + } + + private void HandleWillDisconnectMessage(MessageEventArgs e) + { + _joinedSessionMetadata = null; + IsConnected = false; + Self = null; + Host = null; + _peers.Clear(); + + var handler = Disconnected; + if (handler != null) + handler(new DisconnectedArgs()); + } + + private void HandleDidReceiveDataFromPeer(MessageEventArgs e) + { + var message = e.data.DeserializeFromArray(); + var peer = _Peer.FromIdentifier(message.PeerIdentifier); + + var handler = PeerDataReceived; + if (handler != null) + { + var args = + new PeerDataReceivedArgs + ( + peer, + message.Tag, + (TransportType) message.TransportType, + message.Data + ); + + handler(args); + } + } + + private void HandleAddedPeerMessage(MessageEventArgs e) + { + var message = e.data.DeserializeFromArray(); + var peer = _Peer.FromIdentifier(message.PeerIdentifier); + + _peers.Add(peer.Identifier, peer); + + var handler = PeerAdded; + if (handler != null) + handler(new PeerAddedArgs(_Peer.FromIdentifier(message.PeerIdentifier))); + } + + private void HandleRemovedPeerMessage(MessageEventArgs e) + { + var message = e.data.DeserializeFromArray(); + var peer = _Peer.FromIdentifier(message.PeerIdentifier); + + _peers.Remove(peer.Identifier); + + if (peer.Equals(Host)) + Host = null; + + var handler = PeerRemoved; + if (handler != null) + handler(new PeerRemovedArgs(_Peer.FromIdentifier(message.PeerIdentifier))); + } + + private void HandleUpdatedPersistentKeyValueMessage(MessageEventArgs e) + { + var message = e.data.DeserializeFromArray(); + var key = System.Text.Encoding.UTF8.GetString(message.Key); + var value = message.Value; + + var handler = PersistentKeyValueUpdated; + if (handler != null) + handler(new PersistentKeyValueUpdatedArgs(key, value)); + } + + private void HandleResultReceivedFromArmMessage(MessageEventArgs e) + { + var message = e.data.DeserializeFromArray(); + + var handler = SessionResultReceivedFromArm; + if (handler != null) + handler(new SessionResultReceivedFromArmArgs(message.Outcome, message.Details)); + } + + private void HandleStatusReceivedFromArmMessage(MessageEventArgs e) + { + var message = e.data.DeserializeFromArray(); + + var handler = SessionStatusReceivedFromArm; + if (handler != null) + handler(new SessionStatusReceivedFromArmArgs(message.Status)); + } + + private void HandleDataReceivedFromArmMessage(MessageEventArgs e) + { + var message = e.data.DeserializeFromArray(); + + var handler = DataReceivedFromArm; + if (handler != null) + { + var args = new DataReceivedFromArmArgs(message.Tag, message.Data); + handler(args); + } + } + + private void HandleDeinitializingMessage(MessageEventArgs e) + { + var handler = Deinitialized; + if (handler != null) + handler(new DeinitializedArgs()); + + _RemoteConnection.Unregister + ( + NetworkingConnectedMessage.ID.Combine(StageIdentifier), + HandleDidConnectMessage + ); + + _RemoteConnection.Unregister + ( + NetworkingConnectionFailedWithErrorMessage.ID.Combine(StageIdentifier), + HandleConnectionDidFailWithErrorMessage + ); + + _RemoteConnection.Unregister + ( + NetworkingDisconenctedMessage.ID.Combine(StageIdentifier), + HandleWillDisconnectMessage + ); + + _RemoteConnection.Unregister + ( + NetworkingPeerDataReceivedMessage.ID.Combine(StageIdentifier), + HandleDidReceiveDataFromPeer + ); + + _RemoteConnection.Unregister + ( + NetworkingPeerAddedMessage.ID.Combine(StageIdentifier), + HandleAddedPeerMessage + ); + + _RemoteConnection.Unregister + ( + NetworkingPeerRemovedMessage.ID.Combine(StageIdentifier), + HandleRemovedPeerMessage + ); + + _RemoteConnection.Unregister + ( + NetworkingDeinitializedMessage.ID.Combine(StageIdentifier), + HandleDeinitializingMessage + ); + + _RemoteConnection.Unregister + ( + NetworkingPersistentKeyValueUpdatedMessage.ID.Combine(StageIdentifier), + HandleUpdatedPersistentKeyValueMessage + ); + + _RemoteConnection.Unregister + ( + NetworkingDataReceivedFromArmMessage.ID.Combine(StageIdentifier), + HandleDataReceivedFromArmMessage + ); + + _RemoteConnection.Unregister + ( + NetworkingStatusReceivedFromArmMessage.ID.Combine(StageIdentifier), + HandleStatusReceivedFromArmMessage + ); + + _RemoteConnection.Unregister + ( + NetworkingResultReceivedFromArmMessage.ID.Combine(StageIdentifier), + HandleResultReceivedFromArmMessage + ); + } + + public RuntimeEnvironment RuntimeEnvironment + { + get { return RuntimeEnvironment.Remote; } + } + + public string ToString(int count) + { + return string.Format("_RemoteMultipeerNetworking (ID: {0})", StageIdentifier); + } + + public event ArdkEventHandler ConnectionFailed; + public event ArdkEventHandler Disconnected; + public event ArdkEventHandler PeerDataReceived; + public event ArdkEventHandler PeerAdded; + public event ArdkEventHandler PeerRemoved; + public event ArdkEventHandler PersistentKeyValueUpdated; + public event ArdkEventHandler Deinitialized; + +#pragma warning disable CS0067 + public event ArdkEventHandler DataReceivedFromArm; + public event ArdkEventHandler SessionStatusReceivedFromArm; + public event ArdkEventHandler SessionResultReceivedFromArm; +#pragma warning restore CS0067 + + private ArdkEventHandler _connected; + public event ArdkEventHandler Connected + { + add + { + _connected += value; + if (IsConnected) + { + var args = new ConnectedArgs(Self, Host); + value(args); + } + } + remove { _connected -= value; } + } + + } +} \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/Networking/_RemoteEditorMultipeerNetworking.cs.meta b/Assets/ARDK/VirtualStudio/Networking/_RemoteEditorMultipeerNetworking.cs.meta new file mode 100644 index 0000000..48596e7 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Networking/_RemoteEditorMultipeerNetworking.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9368799ff9bf49d8a6f11210b52bfda2 +timeCreated: 1579738620 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/Remote.meta b/Assets/ARDK/VirtualStudio/Remote.meta new file mode 100644 index 0000000..d3922d3 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 190b8a72e2df74546bc5c7ab8ef07796 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VirtualStudio/Remote/AR.meta b/Assets/ARDK/VirtualStudio/Remote/AR.meta new file mode 100644 index 0000000..d3c2d30 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/AR.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 8691df3bf7ad049babab2f77bd636bcb +folderAsset: yes +timeCreated: 1546554970 +licenseType: Pro +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VirtualStudio/Remote/AR/Networking.meta b/Assets/ARDK/VirtualStudio/Remote/AR/Networking.meta new file mode 100644 index 0000000..ad2ba57 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/AR/Networking.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 7ff47b23143cb4707bc08a1faa9903aa +folderAsset: yes +timeCreated: 1546554932 +licenseType: Pro +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VirtualStudio/Remote/AR/Networking/_RemoteDeviceARNetworkingConstructor.cs b/Assets/ARDK/VirtualStudio/Remote/AR/Networking/_RemoteDeviceARNetworkingConstructor.cs new file mode 100644 index 0000000..5c6a041 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/AR/Networking/_RemoteDeviceARNetworkingConstructor.cs @@ -0,0 +1,150 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.ARSessionEventArgs; +using Niantic.ARDK.Networking; +using Niantic.ARDK.Networking.MultipeerNetworkingEventArgs; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Logging; +using Niantic.ARDK.VirtualStudio.Remote; +using Niantic.ARDK.VirtualStudio.Remote.Data; + +namespace Niantic.ARDK.VirtualStudio.Remote +{ + /// A static wrapper class for listening for messages from the editor to create a parallel + /// ARNetworking running on device + internal static class _RemoteDeviceARNetworkingConstructor + { + public static _RemoteDeviceARNetworkingHandler Handler + { + get + { + return _handler; + } + } + + private static _RemoteDeviceARNetworkingHandler _handler; + + private static IDisposable _executor; + private static ARNetworkingInitMessage _initMessage; + + private static bool _shouldTryToConstruct; + + public static void RegisterForInitMessage() + { + _RemoteDeviceARSessionConstructor.HandlerInitialized += OnOtherHandlerInitialized; + _RemoteDeviceMultipeerNetworkingConstructor.HandlerInitialized += OnOtherHandlerInitialized; + + // Listen for an init... + _executor = _EasyConnection.Register + ( + initMessage => + { + _initMessage = initMessage; + _shouldTryToConstruct = true; + TryToConstruct(); + } + ); + } + + internal static void _Deinitialize() + { + _RemoteDeviceARSessionConstructor.HandlerInitialized -= OnOtherHandlerInitialized; + _RemoteDeviceMultipeerNetworkingConstructor.HandlerInitialized -= OnOtherHandlerInitialized; + + _initMessage = null; + _shouldTryToConstruct = false; + + if (_handler != null) + { + _handler.Dispose(); + _handler = null; + } + + if (_executor != null) + { + _executor.Dispose(); + _executor = null; + } + } + + private static void TryToConstruct() + { + if (Handler != null) + { + ARLog._Error("A _RemoteDeviceARNetworking instance already exists."); + return; + } + + var arSessionDataSender = _RemoteDeviceARSessionConstructor.Handler; + if (arSessionDataSender == null) + return; + + if (arSessionDataSender.InnerARSession.StageIdentifier != _initMessage.StageIdentifier) + { + var msg = "ARNetworking's stage identifier must match previously constructed ARSession's."; + ARLog._Error(msg); + return; + } + + // Need to set it false here so that a construction of a networking doesn't trigger + // another call of this method before this call has finished. + _shouldTryToConstruct = false; + + _RemoteDeviceARNetworkingHandler deviceArNetworkingHandler; + if (_initMessage.ConstructFromExistingNetworking) + { + _RemoteDeviceMultipeerNetworkingHandler networkingHandler; + _RemoteDeviceMultipeerNetworkingConstructor.CurrentHandlers.TryGetValue + ( + _initMessage.StageIdentifier, + out networkingHandler + ); + + if (networkingHandler == null) + { + _shouldTryToConstruct = true; + return; + } + + deviceArNetworkingHandler = + new _RemoteDeviceARNetworkingHandler + ( + arSessionDataSender.InnerARSession, + networkingHandler.InnerNetworking + ); + } + else + { + var networking = + _RemoteDeviceMultipeerNetworkingConstructor.Construct + ( + _initMessage.ServerConfiguration, + _initMessage.StageIdentifier + ); + + deviceArNetworkingHandler = + new _RemoteDeviceARNetworkingHandler + ( + arSessionDataSender.InnerARSession, + networking.InnerNetworking + ); + } + + _handler = deviceArNetworkingHandler; + deviceArNetworkingHandler.InnerARNetworking.Deinitialized += (_) => + { + _handler.Dispose(); + _handler = null; + }; + } + + private static void OnOtherHandlerInitialized() + { + if (_shouldTryToConstruct) + TryToConstruct(); + } + } +} diff --git a/Assets/ARDK/VirtualStudio/Remote/AR/Networking/_RemoteDeviceARNetworkingConstructor.cs.meta b/Assets/ARDK/VirtualStudio/Remote/AR/Networking/_RemoteDeviceARNetworkingConstructor.cs.meta new file mode 100644 index 0000000..30396f6 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/AR/Networking/_RemoteDeviceARNetworkingConstructor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 525c2413fa3a64fd9be3f967f20c0e1f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VirtualStudio/Remote/AR/Networking/_RemoteDeviceARNetworkingHandler.cs b/Assets/ARDK/VirtualStudio/Remote/AR/Networking/_RemoteDeviceARNetworkingHandler.cs new file mode 100644 index 0000000..277bd35 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/AR/Networking/_RemoteDeviceARNetworkingHandler.cs @@ -0,0 +1,89 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.Networking; +using Niantic.ARDK.AR.Networking.ARNetworkingEventArgs; +using Niantic.ARDK.Networking; +using Niantic.ARDK.Utilities.Logging; +using Niantic.ARDK.VirtualStudio.Remote.Data; + +using UnityEngine; + +namespace Niantic.ARDK.VirtualStudio.Remote +{ + internal sealed class _RemoteDeviceARNetworkingHandler + { + private readonly IARNetworking _arNetworking; + + internal IARNetworking InnerARNetworking + { + get { return _arNetworking; } + } + + internal _RemoteDeviceARNetworkingHandler(IARSession arSession, IMultipeerNetworking networking) + { + _arNetworking = ARNetworkingFactory.Create(arSession, networking); + + _arNetworking.PeerStateReceived += HandlePeerStateReceived; + _arNetworking.PeerPoseReceived += HandlePeerPoseReceived; + _arNetworking.Deinitialized += HandleDeinitialized; + + _EasyConnection.Register(message => Dispose()); + } + + ~_RemoteDeviceARNetworkingHandler() + { + ARLog._Error("_RemoteDeviceARNetworkingHandler should be destroyed by an explicit call to Dispose()."); + } + + private bool _isDestroyed; + + public void Dispose() + { + GC.SuppressFinalize(this); + + if (_isDestroyed) + return; + + _isDestroyed = true; + + _arNetworking.PeerStateReceived -= HandlePeerStateReceived; + _arNetworking.PeerPoseReceived -= HandlePeerPoseReceived; + _arNetworking.Deinitialized -= HandleDeinitialized; + + _EasyConnection.Unregister(); + + _arNetworking?.Dispose(); + } + + private void HandlePeerStateReceived(PeerStateReceivedArgs args) + { + var message = + new ARNetworkingPeerStateReceivedMessage + { + PeerState = args.State, + PeerIdentifier = args.Peer.Identifier + }; + + _EasyConnection.Send(message); + } + + private void HandlePeerPoseReceived(PeerPoseReceivedArgs args) + { + var message = + new ARNetworkingPeerPoseReceivedMessage + { + PeerIdentifier = args.Peer.Identifier, Pose = args.Pose + }; + + _EasyConnection.Send(message); + } + + private void HandleDeinitialized(ARNetworkingDeinitializedArgs args) + { + _EasyConnection.Send(new ARNetworkingDeinitializedMessage()); + } + } +} diff --git a/Assets/ARDK/VirtualStudio/Remote/AR/Networking/_RemoteDeviceARNetworkingHandler.cs.meta b/Assets/ARDK/VirtualStudio/Remote/AR/Networking/_RemoteDeviceARNetworkingHandler.cs.meta new file mode 100644 index 0000000..18b1e05 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/AR/Networking/_RemoteDeviceARNetworkingHandler.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 32199763f3be481fb063b4444a447e8d +timeCreated: 1544649529 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/Remote/AR/_RemoteBufferConfiguration.cs b/Assets/ARDK/VirtualStudio/Remote/AR/_RemoteBufferConfiguration.cs new file mode 100644 index 0000000..79f5bb3 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/AR/_RemoteBufferConfiguration.cs @@ -0,0 +1,42 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using UnityEngine; + +namespace Niantic.ARDK.VirtualStudio.Remote +{ + internal static class _RemoteBufferConfiguration + { + private const string _REMOTE_IMAGE_COMPRESSION = "ARDK_Image_Compression"; + private const string _REMOTE_IMAGE_FRAMERATE = "ARDK_Image_Framerate"; + private const string _REMOTE_AWARENESS_FRAMERATE = "ARDK_Awareness_Framerate"; + private const string _REMOTE_FEATURE_POINT_FRAMERATE = "ARDK_Feature_Point_Framerate"; + + private const int _DefaultImageCompression = 30; + private const int _DefaultImageFramerate = 12; + private const int _DefaultAwarenessFramerate = 10; + private const int _DefaultFeaturePointFramerate = 12; + + public static int ImageCompression + { + get => PlayerPrefs.GetInt(_REMOTE_IMAGE_COMPRESSION, _DefaultImageCompression); + set => PlayerPrefs.SetInt(_REMOTE_IMAGE_COMPRESSION, value); + } + + public static int ImageFramerate + { + get => PlayerPrefs.GetInt(_REMOTE_IMAGE_FRAMERATE, _DefaultImageFramerate); + set => PlayerPrefs.SetInt(_REMOTE_IMAGE_FRAMERATE, value); + } + + public static int AwarenessFramerate + { + get => PlayerPrefs.GetInt(_REMOTE_AWARENESS_FRAMERATE, _DefaultAwarenessFramerate); + set => PlayerPrefs.SetInt(_REMOTE_AWARENESS_FRAMERATE, value); + } + + public static int FeaturePointFramerate + { + get => PlayerPrefs.GetInt(_REMOTE_FEATURE_POINT_FRAMERATE, _DefaultFeaturePointFramerate); + set => PlayerPrefs.SetInt(_REMOTE_FEATURE_POINT_FRAMERATE, value); + } + } +} diff --git a/Assets/ARDK/VirtualStudio/Remote/AR/_RemoteBufferConfiguration.cs.meta b/Assets/ARDK/VirtualStudio/Remote/AR/_RemoteBufferConfiguration.cs.meta new file mode 100644 index 0000000..fda952b --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/AR/_RemoteBufferConfiguration.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 830e8d4017e640249df235c5af03f9d4 +timeCreated: 1628002543 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/Remote/AR/_RemoteDeviceARSessionConstructor.cs b/Assets/ARDK/VirtualStudio/Remote/AR/_RemoteDeviceARSessionConstructor.cs new file mode 100644 index 0000000..3a5d4d2 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/AR/_RemoteDeviceARSessionConstructor.cs @@ -0,0 +1,108 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.Utilities.Logging; +using Niantic.ARDK.VirtualStudio.Remote.Data; + +using UnityEngine; + +namespace Niantic.ARDK.VirtualStudio.Remote +{ + /// A static wrapper class for listening for messages from the editor to create a parallel + /// ARSession running on device. + internal static class _RemoteDeviceARSessionConstructor + { + public static Action HandlerInitialized; + + public static _RemoteDeviceARSessionHandler Handler + { + get + { + return _handler; + } + } + + private static _RemoteDeviceARSessionHandler _handler; + private static IDisposable _executor; + + public static void RegisterForInitMessage() + { + _executor = _EasyConnection.Register(Construct); + } + + internal static void _Deinitialize() + { + if (_handler != null) + { + _handler.Dispose(); + _handler = null; + } + + if (_executor != null) + { + _executor.Dispose(); + _executor = null; + } + } + + private static void Construct(ARSessionInitMessage message) + { + Construct + ( + message.StageIdentifier, + message.ImageCompressionQuality, + message.TargetImageFramerate, + message.TargetBufferFramerate, + message.TargetFeaturePointFramerate + ); + } + + public static _RemoteDeviceARSessionHandler Construct + ( + Guid stageIdentifier, + int compressionQuality, + int imageFramerate, + int awarenessFramerate, + int featurePointFramerate + ) + { + if (Handler != null) + { + ARLog._Error("A _RemoteARSessionMessageHandler instance already exists."); + return null; + } + + ARLog._DebugFormat + ( + "Constructing remote ARSession with compressionQuality: {0}, imageFramerate: {1}, " + + "awarenessFramerate: {2}, featurePointFramerate: {3}", + false, + compressionQuality, + imageFramerate, + awarenessFramerate, + featurePointFramerate + ); + + var session = + new _RemoteDeviceARSessionHandler + ( + stageIdentifier, + compressionQuality, + imageFramerate, + awarenessFramerate, + featurePointFramerate + ); + + _handler = session; + session.InnerARSession.Deinitialized += _ => + { + _handler.Dispose(); + _handler = null; + }; + + HandlerInitialized?.Invoke(); + return session; + } + } +} diff --git a/Assets/ARDK/VirtualStudio/Remote/AR/_RemoteDeviceARSessionConstructor.cs.meta b/Assets/ARDK/VirtualStudio/Remote/AR/_RemoteDeviceARSessionConstructor.cs.meta new file mode 100644 index 0000000..b58f4ab --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/AR/_RemoteDeviceARSessionConstructor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: efc65fd5c2be4411c951190a07205919 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VirtualStudio/Remote/AR/_RemoteDeviceARSessionHandler.cs b/Assets/ARDK/VirtualStudio/Remote/AR/_RemoteDeviceARSessionHandler.cs new file mode 100644 index 0000000..b634da5 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/AR/_RemoteDeviceARSessionHandler.cs @@ -0,0 +1,333 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Linq; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.Anchors; +using Niantic.ARDK.AR.ARSessionEventArgs; +using Niantic.ARDK.AR.Configuration; +using Niantic.ARDK.AR.Camera; +using Niantic.ARDK.AR.Frame; +using Niantic.ARDK.AR.Mesh; +using Niantic.ARDK.AR.SLAM; +using Niantic.ARDK.Networking; +using Niantic.ARDK.Utilities.Extensions; +using Niantic.ARDK.Utilities.Logging; +using Niantic.ARDK.VirtualStudio.Remote.Data; + +using UnityEngine; + +namespace Niantic.ARDK.VirtualStudio.Remote +{ + internal sealed class _RemoteDeviceARSessionHandler + { + private readonly IARSession _session; + + public IARSession InnerARSession + { + get => _session; + } + + private readonly int _imageCompressionQuality; + private readonly float _targetImageFrameDelta; + private readonly float _targetAwarenessFrameDelta; + private readonly float _targetFeaturePointFrameDelta; + private Dictionary _addedAnchors = new Dictionary(); + + internal _RemoteDeviceARSessionHandler + ( + Guid stageIdentifier, + int imageCompressionQuality, + int targetImageFramerate, + int targetAwarenessFramerate, + int targetFeaturePointFramerate + ) + { + _session = ARSessionFactory.Create(stageIdentifier); + + _imageCompressionQuality = imageCompressionQuality; + _targetImageFrameDelta = 1.0f / targetImageFramerate; + _targetAwarenessFrameDelta = 1.0f / targetAwarenessFramerate; + _targetFeaturePointFrameDelta = 1.0f / targetFeaturePointFramerate; + + _EasyConnection.Register(HandleRunMessage); + _EasyConnection.Register(HandlePauseMessage); + _EasyConnection.Register(HandleAddAnchorMessage); + _EasyConnection.Register(HandleRemoveAnchorMessage); + _EasyConnection.Register(HandleSetWorldScaleMessage); + _EasyConnection.Register(HandleDestroyMessage); + + _session.FrameUpdated += OnFrameUpdated; + _session.AnchorsAdded += OnAnchorsAdded; + _session.AnchorsUpdated += OnAnchorsUpdated; + _session.AnchorsRemoved += OnAnchorsRemoved; + _session.AnchorsMerged += OnAnchorsMerged; + _session.MapsAdded += OnMapsAdded; + _session.MapsUpdated += OnMapsUpdated; + + _session.CameraTrackingStateChanged += OnCameraTrackingStateChanged; + _session.SessionInterrupted += OnSessionInterrupted; + _session.SessionInterruptionEnded += OnSessionInterruptionEnded; + _session.SessionFailed += OnSessionFailed; + } + + private bool _isDestroyed; + + ~_RemoteDeviceARSessionHandler() + { + ARLog._Error("_RemoteDeviceARSessionHandler should be destroyed by an explicit call to Dispose()."); + } + + public void Dispose() + { + GC.SuppressFinalize(this); + + if (_isDestroyed) + return; + + _isDestroyed = true; + + _EasyConnection.Unregister(); + _EasyConnection.Unregister(); + _EasyConnection.Unregister(); + _EasyConnection.Unregister(); + _EasyConnection.Unregister(); + _EasyConnection.Unregister(); + + _session.FrameUpdated -= OnFrameUpdated; + _session.AnchorsAdded -= OnAnchorsAdded; + _session.AnchorsUpdated -= OnAnchorsUpdated; + _session.AnchorsRemoved -= OnAnchorsRemoved; + _session.AnchorsMerged -= OnAnchorsMerged; + _session.MapsAdded -= OnMapsAdded; + _session.MapsUpdated -= OnMapsUpdated; + + _session.CameraTrackingStateChanged -= OnCameraTrackingStateChanged; + _session.SessionInterrupted -= OnSessionInterrupted; + _session.SessionInterruptionEnded -= OnSessionInterruptionEnded; + _session.SessionFailed -= OnSessionFailed; + + _session.Dispose(); + } + +#region CallbackFowarding + + private static float _lastImageCaptureTime; + private static float _lastAwarenessCaptureTime; + private static float _lastPointCloudCaptureTime; + + private void OnFrameUpdated(FrameUpdatedArgs args) + { + var frame = args.Frame; + + var includeImageBuffers = false; + var includeAwarenessBuffers = false; + var includeFeaturePoints = false; + + var unscaledTime = Time.unscaledTime; + + if ((unscaledTime - _lastImageCaptureTime) > _targetImageFrameDelta) + { + includeImageBuffers = true; + _lastImageCaptureTime = unscaledTime; + } + + if ((unscaledTime - _lastAwarenessCaptureTime) > _targetAwarenessFrameDelta) + { + includeAwarenessBuffers = true; + _lastAwarenessCaptureTime = unscaledTime; + } + + if ((unscaledTime - _lastPointCloudCaptureTime) > _targetFeaturePointFrameDelta) + { + includeFeaturePoints = true; + _lastPointCloudCaptureTime = unscaledTime; + } + + // Todo: Should be sending UnreliableOrdered, but Unreliable protocols won’t deliver any + // message if payload size is ~1.8KB or more. + _EasyConnection.Send + ( + new ARSessionFrameUpdatedMessage + { + Frame = frame._AsSerializable + ( + includeImageBuffers: includeImageBuffers, + includeAwarenessBuffers: includeAwarenessBuffers, + compressionLevel: _imageCompressionQuality, + includeFeaturePoints: includeFeaturePoints + ) + }, + TransportType.ReliableUnordered + ); + } + + private static void OnAnchorsAdded(AnchorsArgs args) + { + var anchors = AnchorExtensions.ClassifyAsSerializableAnchors(args.Anchors); + + // TODO: We could just serialize everything in a single array. + // The serializer knows what to do! + _EasyConnection.Send + ( + new ARSessionAnchorsAddedMessage + { + Anchors = anchors.BasicAnchors.ToArray(), + PlaneAnchors = anchors.PlaneAnchors.ToArray(), + ImageAnchors = anchors.ImageAnchors.ToArray(), + } + ); + } + + private static void OnAnchorsUpdated(AnchorsArgs args) + { + var anchors = AnchorExtensions.ClassifyAsSerializableAnchors(args.Anchors); + + _EasyConnection.Send + ( + new ARSessionAnchorsUpdatedMessage + { + Anchors = anchors.BasicAnchors.ToArray(), + PlaneAnchors = anchors.PlaneAnchors.ToArray(), + ImageAnchors = anchors.ImageAnchors.ToArray(), + } + ); + } + + private static void OnAnchorsRemoved(AnchorsArgs args) + { + var anchors = AnchorExtensions.ClassifyAsSerializableAnchors(args.Anchors); + + _EasyConnection.Send + ( + new ARSessionAnchorsRemovedMessage + { + Anchors = anchors.BasicAnchors.ToArray(), + PlaneAnchors = anchors.PlaneAnchors.ToArray(), + ImageAnchors = anchors.ImageAnchors.ToArray(), + } + ); + } + + private static void OnAnchorsMerged(AnchorsMergedArgs args) + { + var parentQuery = ((IARPlaneAnchor)args.Parent)._AsSerializablePlane(); + + var childrenArray = + ( + from child in args.Children + select ((IARPlaneAnchor)child)._AsSerializablePlane() + ).ToArray(); + + _EasyConnection.Send + ( + new ARSessionAnchorsMergedMessage + { + ParentAnchor = parentQuery, ChildAnchors = childrenArray + } + ); + } + + private static void OnMapsAdded(MapsArgs args) + { + var serializableMaps = args.Maps._AsSerializableArray(); + _EasyConnection.Send(new ARSessionMapsAddedMessage { Maps = serializableMaps }); + } + + private static void OnMapsUpdated(MapsArgs args) + { + var serializableMaps = args.Maps._AsSerializableArray(); + _EasyConnection.Send(new ARSessionMapsUpdatedMessage { Maps = serializableMaps }); + } + + private static void OnCameraTrackingStateChanged(CameraTrackingStateChangedArgs args) + { + var serializableCamera = args.Camera._AsSerializable(); + if (serializableCamera == null) + return; + + _EasyConnection.Send + ( + new ARSessionCameraTrackingStateChangedMessage { Camera = serializableCamera } + ); + } + + private static void OnSessionInterrupted(ARSessionInterruptedArgs args) + { + _EasyConnection.Send(new ARSessionWasInterruptedMessage()); + } + + private static void OnSessionInterruptionEnded(ARSessionInterruptionEndedArgs args) + { + _EasyConnection.Send(new ARSessionInterruptionEndedMessage()); + } + + private static void OnSessionFailed(ARSessionFailedArgs args) + { + _EasyConnection.Send(new ARSessionFailedMessage { Error = args.Error }); + } +#endregion + +#region EditorRequests + private void HandleRunMessage(ARSessionRunMessage message) + { + IARConfiguration configuration; + + if (message.arConfiguration != null) + configuration = message.arConfiguration; + else + throw new Exception("No valid configuration passed to PlayerARSession"); + + _session.Run(configuration, message.runOptions); + } + + private void HandlePauseMessage(ARSessionPauseMessage message) + { + _session.Pause(); + } + + private void HandleAddAnchorMessage(ARSessionAddAnchorMessage message) + { + var deviceAnchor = _session.AddAnchor(message.Anchor.Transform); + _addedAnchors.Add(deviceAnchor.Identifier, deviceAnchor); + + _EasyConnection.Send + ( + new ARSessionAddedCustomAnchorMessage + { + Anchor = deviceAnchor._AsSerializable(), + EditorIdentifier = message.Anchor.Identifier + } + ); + } + + private void HandleRemoveAnchorMessage(ARSessionRemoveAnchorMessage message) + { + if (_addedAnchors.TryGetValue(message.DeviceAnchorIdentifier, out IARAnchor anchor)) + { + _session.RemoveAnchor(anchor); + } + else + { + ARLog._ErrorFormat + ( + "No anchor with identifier {0} was found to remove.", + message.DeviceAnchorIdentifier + ); + } + } + + private void HandleSetWorldScaleMessage(ARSessionSetWorldScaleMessage message) + { + _session.WorldScale = message.WorldScale; + } + + private void HandleDestroyMessage(ARSessionDestroyMessage message) + { + Dispose(); + } +#endregion + } +} diff --git a/Assets/ARDK/VirtualStudio/Remote/AR/_RemoteDeviceARSessionHandler.cs.meta b/Assets/ARDK/VirtualStudio/Remote/AR/_RemoteDeviceARSessionHandler.cs.meta new file mode 100644 index 0000000..d55a0e8 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/AR/_RemoteDeviceARSessionHandler.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 01b9a907c1b7a46ad9b5a714792172ba +timeCreated: 1547242018 +licenseType: Pro +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VirtualStudio/Remote/Data.meta b/Assets/ARDK/VirtualStudio/Remote/Data.meta new file mode 100644 index 0000000..766a3e9 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/Data.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 413a4babd6d094bc09e611f53d92d760 +folderAsset: yes +timeCreated: 1546554348 +licenseType: Pro +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VirtualStudio/Remote/Data/DeviceToEditor.cs b/Assets/ARDK/VirtualStudio/Remote/Data/DeviceToEditor.cs new file mode 100644 index 0000000..6fb5077 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/Data/DeviceToEditor.cs @@ -0,0 +1,232 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.Anchors; +using Niantic.ARDK.AR.Camera; +using Niantic.ARDK.AR.Awareness.Depth; +using Niantic.ARDK.AR.Networking; +using Niantic.ARDK.AR.Frame; +using Niantic.ARDK.AR.Mesh; +using Niantic.ARDK.Networking.MultipeerNetworkingEventArgs; + + +using UnityEngine; + +// TODO: comment + +namespace Niantic.ARDK.VirtualStudio.Remote.Data +{ +#region AR + [Serializable] + internal sealed class ARSessionFrameUpdatedMessage + { + public _SerializableARFrame Frame; + } + + [Serializable] + internal sealed class ARSessionMeshUpdatedMessage + { + public _SerializableARMeshData MeshData; + } + + [Serializable] + internal sealed class ARSessionAddedCustomAnchorMessage + { + public _SerializableARAnchor Anchor; + public Guid EditorIdentifier; + } + + [Serializable] + internal sealed class ARSessionAnchorsAddedMessage + { + public _SerializableARAnchor[] Anchors; + public _SerializableARPlaneAnchor[] PlaneAnchors; + public _SerializableARImageAnchor[] ImageAnchors; + } + + [Serializable] + internal sealed class ARSessionAnchorsUpdatedMessage + { + public _SerializableARAnchor[] Anchors; + public _SerializableARPlaneAnchor[] PlaneAnchors; + public _SerializableARImageAnchor[] ImageAnchors; + } + + [Serializable] + internal sealed class ARSessionAnchorsRemovedMessage + { + public _SerializableARAnchor[] Anchors; + public _SerializableARPlaneAnchor[] PlaneAnchors; + public _SerializableARImageAnchor[] ImageAnchors; + } + + [Serializable] + internal sealed class ARSessionAnchorsMergedMessage + { + public _SerializableARPlaneAnchor ParentAnchor; + public _SerializableARPlaneAnchor[] ChildAnchors; + } + + [Serializable] + internal sealed class ARSessionMapsAddedMessage + { + public ARDK.AR.SLAM._SerializableARMap[] Maps; + } + + [Serializable] + internal sealed class ARSessionMapsUpdatedMessage + { + public ARDK.AR.SLAM._SerializableARMap[] Maps; + } + + [Serializable] + internal sealed class ARSessionLocalizationUpdatedMessage + { + // TODO + } + + [Serializable] + internal sealed class ARSessionCameraTrackingStateChangedMessage + { + internal _SerializableARCamera Camera; + } + + [Serializable] + internal sealed class ARSessionWasInterruptedMessage + { + } + + [Serializable] + internal sealed class ARSessionInterruptionEndedMessage + { + } + + [Serializable] + internal sealed class ARSessionFailedMessage + { + public ARError Error; + } +#endregion + +#region Networking + [Serializable] + internal sealed class NetworkingConnectedMessage + { + public static readonly Guid ID = new Guid("4dae7981-fb53-499b-8e36-45072d00bcb5"); + + public Guid SelfIdentifier; + public Guid HostIdentifier; + } + + [Serializable] + internal sealed class NetworkingConnectionFailedWithErrorMessage + { + public static readonly Guid ID = new Guid("8abf4e4f-041d-4cea-b898-8018aedada87"); + + public uint ErrorCode; + } + + [Serializable] + internal sealed class NetworkingDisconenctedMessage + { + public static readonly Guid ID = new Guid("8437924b-728e-40b7-bc04-f16628716a53"); + } + + [Serializable] + internal sealed class NetworkingPeerDataReceivedMessage + { + public static readonly Guid ID = new Guid("c91b6ce0-3922-4ac7-a269-0c60e974e4db"); + + public uint Tag; + public byte[] Data; + public Guid PeerIdentifier; + public byte TransportType; + } + + [Serializable] + internal sealed class NetworkingPeerAddedMessage + { + public static readonly Guid ID = new Guid("e2abdcb8-0a74-4081-a716-75fec0e55e9c"); + + public Guid PeerIdentifier; + } + + [Serializable] + internal sealed class NetworkingPeerRemovedMessage + { + public static readonly Guid ID = new Guid("34b6a435-f9ed-420a-b2e3-6e866a52efe6"); + + public Guid PeerIdentifier; + } + + [Serializable] + internal sealed class NetworkingPersistentKeyValueUpdatedMessage + { + public static readonly Guid ID = new Guid("34b6a435-f9ed-420a-b2e3-6e866a52ffe6"); + + public byte[] Key; + public byte[] Value; + } + + [Serializable] + internal sealed class NetworkingDeinitializedMessage + { + public static readonly Guid ID = new Guid("c0e3f4b5-da75-498b-93ba-9139ec3eaa20"); + } + + [Serializable] + internal sealed class NetworkingDataReceivedFromArmMessage + { + public static readonly Guid ID = new Guid("c91b6ce0-3922-4ac7-a269-0c60e974e4dc"); + + public uint Tag; + public byte[] Data; + } + + [Serializable] + internal sealed class NetworkingStatusReceivedFromArmMessage + { + public static readonly Guid ID = new Guid("c91b6ce0-3922-4ac7-a269-0c60e974e4dd"); + + public uint Status; + } + + [Serializable] + internal sealed class NetworkingResultReceivedFromArmMessage + { + public static readonly Guid ID = new Guid("c91b6ce0-3922-4ac7-a269-0c60e974e4de"); + + public uint Outcome; + public byte[] Details; + } + +#endregion + +#region ARNetworking + [Serializable] + internal sealed class ARNetworkingPeerStateReceivedMessage + { + public static readonly Guid ID = new Guid("464cc2a0-8b0d-483b-abf7-94e0c3809458"); + + public PeerState PeerState; + public Guid PeerIdentifier; + } + + [Serializable] + internal sealed class ARNetworkingPeerPoseReceivedMessage + { + public static readonly Guid ID = new Guid("464cc2a0-8b0d-483b-abf7-95e0c3809458"); + + public Matrix4x4 Pose; + public Guid PeerIdentifier; + } + + [Serializable] + internal sealed class ARNetworkingDeinitializedMessage + { + public static readonly Guid ID = new Guid("c0e3f4b5-da75-498b-93ba-9139ec3eaa29"); + } +#endregion +} diff --git a/Assets/ARDK/VirtualStudio/Remote/Data/DeviceToEditor.cs.meta b/Assets/ARDK/VirtualStudio/Remote/Data/DeviceToEditor.cs.meta new file mode 100644 index 0000000..d326cd1 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/Data/DeviceToEditor.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 339b72895eca54c5eb397f73c185bfde +timeCreated: 1546554311 +licenseType: Pro +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VirtualStudio/Remote/Data/EditorToDevice.cs b/Assets/ARDK/VirtualStudio/Remote/Data/EditorToDevice.cs new file mode 100644 index 0000000..eeb9726 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/Data/EditorToDevice.cs @@ -0,0 +1,149 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.Anchors; +using Niantic.ARDK.Networking; +using Niantic.ARDK.AR.Configuration; + +// TODO: comment + +namespace Niantic.ARDK.VirtualStudio.Remote.Data +{ + [Serializable] + internal sealed class RemoteConnectionDestroyMessage + { + } + +#region AR + [Serializable] + internal sealed class ARSessionInitMessage + { + public Guid StageIdentifier = Guid.Empty; + + public int ImageCompressionQuality = 30; + public int TargetImageFramerate = 12; + public int TargetBufferFramerate = 10; + public int TargetFeaturePointFramerate = 12; + } + + [Serializable] + internal sealed class ARSessionRunMessage + { + internal IARConfiguration arConfiguration = null; + public ARSessionRunOptions runOptions = 0; + } + + [Serializable] + internal sealed class ARSessionPauseMessage + { + } + + [Serializable] + internal sealed class ARSessionAddAnchorMessage + { + public _SerializableARAnchor Anchor = null; + } + + [Serializable] + internal sealed class ARSessionRemoveAnchorMessage + { + public Guid DeviceAnchorIdentifier; + } + + [Serializable] + internal sealed class ARSessionMergeAnchorMessage + { + public _SerializableARAnchor Anchor = null; + } + + [Serializable] + internal sealed class ARSessionSetWorldScaleMessage + { + public float WorldScale = 1.0f; + } + + [Serializable] + internal sealed class ARSessionDestroyMessage + { + } +#endregion + +#region Networking + [Serializable] + internal sealed class NetworkingInitMessage + { + public ServerConfiguration Configuration = ServerConfiguration.ARBE; + public Guid StageIdentifier = Guid.Empty; + } + + [Serializable] + internal sealed class NetworkingSendDataToPeersMessage + { + public static readonly Guid ID = new Guid("52c251b0-afb9-4e4d-ac31-b75cabec02f2"); + + public uint Tag = 0U; + public byte[] Data = null; + public Guid[] Peers = null; + public byte TransportType = 0; + public bool SendToSelf = true; + } + + [Serializable] + internal sealed class NetworkingJoinMessage + { + public static readonly Guid ID = new Guid("dc0b20d4-08b1-4d6b-9039-1a37f0b062fd"); + + public byte[] Metadata = null; + } + + [Serializable] + internal sealed class NetworkingLeaveMessage + { + public static readonly Guid ID = new Guid("dc0b20d4-08b1-4d6b-9039-1a37f0b062fe"); + + public byte[] Metadata = null; + } + + [Serializable] + internal sealed class NetworkingDestroyMessage + { + public static readonly Guid ID = new Guid("5fb6ceb9-56aa-4057-ad2f-4a3ebc5a5836"); + } + + [Serializable] + internal sealed class NetworkingStorePersistentKeyValueMessage + { + public static readonly Guid ID = new Guid("5fb6ceb9-57aa-4057-ad2f-4a3ebc5a5836"); + + public byte[] Key = null; + public byte[] Value = null; + } + + [Serializable] + internal sealed class NetworkingSendDataToArmMessage + { + public static readonly Guid ID = new Guid("52c251b0-afb9-4e4d-ac31-b75cabec02f3"); + + public uint Tag = 0U; + public byte[] Data = null; + } + + #endregion + +#region ARNetworking + [Serializable] + internal sealed class ARNetworkingInitMessage + { + public Guid StageIdentifier = Guid.Empty; + public ServerConfiguration ServerConfiguration = ServerConfiguration.ARBE; + public bool ConstructFromExistingNetworking = false; + } + + [Serializable] + internal sealed class ARNetworkingDestroyMessage + { + } +#endregion +} diff --git a/Assets/ARDK/VirtualStudio/Remote/Data/EditorToDevice.cs.meta b/Assets/ARDK/VirtualStudio/Remote/Data/EditorToDevice.cs.meta new file mode 100644 index 0000000..457e98e --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/Data/EditorToDevice.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: fc15e7f1d33f44abac9af92792064371 +timeCreated: 1546884176 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/Remote/Networking.meta b/Assets/ARDK/VirtualStudio/Remote/Networking.meta new file mode 100644 index 0000000..4068ab1 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/Networking.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 29ac4c795e49d4a648a6cb50d3fec4e5 +folderAsset: yes +timeCreated: 1546554922 +licenseType: Pro +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VirtualStudio/Remote/Networking/_RemoteDeviceMultipeerNetworkingConstructor.cs b/Assets/ARDK/VirtualStudio/Remote/Networking/_RemoteDeviceMultipeerNetworkingConstructor.cs new file mode 100644 index 0000000..92978bf --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/Networking/_RemoteDeviceMultipeerNetworkingConstructor.cs @@ -0,0 +1,93 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; + +using Niantic.ARDK.Networking; +using Niantic.ARDK.Networking.MultipeerNetworkingEventArgs; +using Niantic.ARDK.Utilities.Collections; +using Niantic.ARDK.VirtualStudio.Remote; +using Niantic.ARDK.VirtualStudio.Remote.Data; + +namespace Niantic.ARDK.VirtualStudio.Remote +{ + /// + /// A static wrapper class for listening for messages from the editor to create a parallel + /// _RemoteDeviceMultipeerNetworking running on device + /// + internal static class _RemoteDeviceMultipeerNetworkingConstructor + { + public static Action HandlerInitialized; + + public static _ReadOnlyDictionary CurrentHandlers + { + get; + private set; + } + + private static readonly + ConcurrentDictionary _handlers = + new ConcurrentDictionary(); + + private static IDisposable _executor; + + static _RemoteDeviceMultipeerNetworkingConstructor() + { + CurrentHandlers = new _ReadOnlyDictionary(_handlers); + } + + public static void RegisterForInitMessage() + { + _executor = _EasyConnection.Register(Construct); + } + + internal static void _Deinitialize() + { + var handlers = new List<_RemoteDeviceMultipeerNetworkingHandler>(_handlers.Values); + foreach (var handler in handlers) + handler.Dispose(); + + _handlers.Clear(); + + var executor = _executor; + if (executor != null) + { + _executor = null; + executor.Dispose(); + } + } + + private static void Construct(NetworkingInitMessage message) + { + Construct(message.Configuration, message.StageIdentifier); + } + + public static _RemoteDeviceMultipeerNetworkingHandler Construct + ( + ServerConfiguration serverConfiguration, + Guid stageIdentifier + ) + { + var handler = + new _RemoteDeviceMultipeerNetworkingHandler + ( + serverConfiguration, + stageIdentifier + ); + + if (!_handlers.TryAdd(handler.InnerNetworking.StageIdentifier, handler)) + throw new InvalidOperationException("Tried to create a networking with a StageIdentifier already in use."); + + handler.InnerNetworking.Deinitialized += + (ignored) => + { + _handlers.TryRemove(stageIdentifier, out _); + handler.Dispose(); + }; + + HandlerInitialized?.Invoke(); + return handler; + } + } +} diff --git a/Assets/ARDK/VirtualStudio/Remote/Networking/_RemoteDeviceMultipeerNetworkingConstructor.cs.meta b/Assets/ARDK/VirtualStudio/Remote/Networking/_RemoteDeviceMultipeerNetworkingConstructor.cs.meta new file mode 100644 index 0000000..d210f22 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/Networking/_RemoteDeviceMultipeerNetworkingConstructor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dc77a4ee378fd45a28c0c1795b732cbb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VirtualStudio/Remote/Networking/_RemoteDeviceMultipeerNetworkingHandler.cs b/Assets/ARDK/VirtualStudio/Remote/Networking/_RemoteDeviceMultipeerNetworkingHandler.cs new file mode 100644 index 0000000..a7e84f1 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/Networking/_RemoteDeviceMultipeerNetworkingHandler.cs @@ -0,0 +1,325 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.Networking; +using Niantic.ARDK.Networking.MultipeerNetworkingEventArgs; +using Niantic.ARDK.Utilities.Extensions; +using Niantic.ARDK.Utilities.Logging; +using Niantic.ARDK.VirtualStudio.Remote.Data; + +using UnityEngine.Networking.PlayerConnection; + +namespace Niantic.ARDK.VirtualStudio.Remote +{ + internal sealed class _RemoteDeviceMultipeerNetworkingHandler + { + private readonly IMultipeerNetworking _networking; + + internal IMultipeerNetworking InnerNetworking + { + get { return _networking; } + } + + internal _RemoteDeviceMultipeerNetworkingHandler(ServerConfiguration configuration, Guid stageIdentifier) + { + _networking = + MultipeerNetworkingFactory.Create(configuration, stageIdentifier); + + _networking.Connected += OnInternalConnected; + _networking.ConnectionFailed += OnInternalConnectionFailed; + _networking.Disconnected += OnInternalDisconnected; + _networking.PeerDataReceived += OnInternalPeerDataReceived; + _networking.PeerAdded += OnInternalPeerAdded; + _networking.PeerRemoved += OnInternalPeerRemoved; + _networking.Deinitialized += OnInternalDeinitializing; + _networking.PersistentKeyValueUpdated += OnInternalPersistentKeyValueUpdated; + _networking.DataReceivedFromArm += OnInternalDidReceiveDataFromArm; + _networking.SessionStatusReceivedFromArm += OnInternalDidReceiveStatusFromArm; + _networking.SessionResultReceivedFromArm += OnInternalDidReceiveResultFromArm; + + _RemoteConnection.Register + ( + NetworkingJoinMessage.ID.Combine(stageIdentifier), + HandleJoinMessage + ); + + _RemoteConnection.Register + ( + NetworkingLeaveMessage.ID.Combine(stageIdentifier), + HandleLeaveMessage + ); + + _RemoteConnection.Register + ( + NetworkingDestroyMessage.ID.Combine(stageIdentifier), + HandleDestroyMessage + ); + + _RemoteConnection.Register + ( + NetworkingSendDataToPeersMessage.ID.Combine(stageIdentifier), + HandleSendDataToPeersMessage + ); + + _RemoteConnection.Register + ( + NetworkingStorePersistentKeyValueMessage.ID.Combine(stageIdentifier), + HandleStorePersistentKeyValueMessage + ); + + _RemoteConnection.Register + ( + NetworkingSendDataToArmMessage.ID.Combine(stageIdentifier), + HandleSendDataToArmMessage + ); + } + + ~_RemoteDeviceMultipeerNetworkingHandler() + { + ARLog._Error("_RemoteDeviceMultipeerNetworkingHandler should be destroyed by an explicit call to Dispose()."); + } + + private bool _isDestroyed; + + public void Dispose() + { + GC.SuppressFinalize(this); + + if (_isDestroyed) + return; + + _isDestroyed = true; + + _networking.Connected -= OnInternalConnected; + _networking.ConnectionFailed -= OnInternalConnectionFailed; + _networking.Disconnected -= OnInternalDisconnected; + _networking.PeerDataReceived -= OnInternalPeerDataReceived; + _networking.PeerAdded -= OnInternalPeerAdded; + _networking.PeerRemoved -= OnInternalPeerRemoved; + _networking.Deinitialized -= OnInternalDeinitializing; + _networking.PersistentKeyValueUpdated -= OnInternalPersistentKeyValueUpdated; + _networking.DataReceivedFromArm -= OnInternalDidReceiveDataFromArm; + _networking.SessionStatusReceivedFromArm -= OnInternalDidReceiveStatusFromArm; + _networking.SessionResultReceivedFromArm -= OnInternalDidReceiveResultFromArm; + + var stageId = InnerNetworking.StageIdentifier; + _RemoteConnection.Unregister + ( + NetworkingJoinMessage.ID.Combine(stageId), + HandleJoinMessage + ); + + _RemoteConnection.Unregister + ( + NetworkingLeaveMessage.ID.Combine(stageId), + HandleLeaveMessage + ); + + _RemoteConnection.Unregister + ( + NetworkingSendDataToPeersMessage.ID.Combine(stageId), + HandleSendDataToPeersMessage + ); + + _RemoteConnection.Unregister + ( + NetworkingDestroyMessage.ID.Combine(stageId), + HandleDestroyMessage + ); + + _RemoteConnection.Unregister + ( + NetworkingStorePersistentKeyValueMessage.ID.Combine(stageId), + HandleStorePersistentKeyValueMessage + ); + + _networking.Dispose(); + } + + private void OnInternalConnected(ConnectedArgs args) + { + _RemoteConnection.Send + ( + NetworkingConnectedMessage.ID.Combine(InnerNetworking.StageIdentifier), + new NetworkingConnectedMessage + { + SelfIdentifier = args.Self.Identifier, HostIdentifier = args.Host.Identifier, + }.SerializeToArray() + ); + } + + private void OnInternalConnectionFailed(ConnectionFailedArgs args) + { + _RemoteConnection.Send + ( + NetworkingConnectionFailedWithErrorMessage.ID.Combine(InnerNetworking.StageIdentifier), + new NetworkingConnectionFailedWithErrorMessage + { + ErrorCode = args.ErrorCode, + }.SerializeToArray() + ); + } + + private void OnInternalDisconnected(DisconnectedArgs args) + { + _RemoteConnection.Send + ( + NetworkingDisconenctedMessage.ID.Combine(InnerNetworking.StageIdentifier), + new NetworkingDisconenctedMessage().SerializeToArray() + ); + } + + private void OnInternalPeerDataReceived(PeerDataReceivedArgs args) + { + _RemoteConnection.Send + ( + NetworkingPeerDataReceivedMessage.ID.Combine(InnerNetworking.StageIdentifier), + new NetworkingPeerDataReceivedMessage + { + Tag = args.Tag, + Data = args.CopyData(), + PeerIdentifier = args.Peer.Identifier, + TransportType = (byte)args.TransportType + }.SerializeToArray() + ); + } + + private void OnInternalPeerAdded(PeerAddedArgs args) + { + _RemoteConnection.Send + ( + NetworkingPeerAddedMessage.ID.Combine(InnerNetworking.StageIdentifier), + new NetworkingPeerAddedMessage + { + PeerIdentifier = args.Peer.Identifier + } + .SerializeToArray() + ); + } + + private void OnInternalPeerRemoved(PeerRemovedArgs args) + { + _RemoteConnection.Send + ( + NetworkingPeerRemovedMessage.ID.Combine(InnerNetworking.StageIdentifier), + new NetworkingPeerRemovedMessage + { + PeerIdentifier = args.Peer.Identifier + } + .SerializeToArray() + ); + } + + private void OnInternalDeinitializing(DeinitializedArgs args) + { + _RemoteConnection.Send + ( + NetworkingDeinitializedMessage.ID.Combine(InnerNetworking.StageIdentifier), + new NetworkingDeinitializedMessage().SerializeToArray() + ); + } + + private void OnInternalPersistentKeyValueUpdated(PersistentKeyValueUpdatedArgs args) + { + _RemoteConnection.Send + ( + NetworkingPersistentKeyValueUpdatedMessage.ID.Combine(InnerNetworking.StageIdentifier), + new NetworkingPersistentKeyValueUpdatedMessage() + { + Key = System.Text.Encoding.UTF8.GetBytes(args.Key), Value = args.CopyValue() + }.SerializeToArray() + ); + } + + private void OnInternalDidReceiveDataFromArm(DataReceivedFromArmArgs args) + { + _RemoteConnection.Send + ( + NetworkingDataReceivedFromArmMessage.ID.Combine(InnerNetworking.StageIdentifier), + new NetworkingDataReceivedFromArmMessage + { + Tag = args.Tag, + Data = args.CreateDataReader().ToArray(), + }.SerializeToArray() + ); + } + + private void OnInternalDidReceiveStatusFromArm(SessionStatusReceivedFromArmArgs args) + { + _RemoteConnection.Send + ( + NetworkingStatusReceivedFromArmMessage.ID.Combine(InnerNetworking.StageIdentifier), + new NetworkingStatusReceivedFromArmMessage + { + Status = args.Status, + }.SerializeToArray() + ); + } + + private void OnInternalDidReceiveResultFromArm(SessionResultReceivedFromArmArgs args) + { + _RemoteConnection.Send + ( + NetworkingResultReceivedFromArmMessage.ID.Combine(InnerNetworking.StageIdentifier), + new NetworkingResultReceivedFromArmMessage + { + Outcome = args.Outcome, + Details = args.CreateDetailsReader().ToArray(), + }.SerializeToArray() + ); + } + + private void HandleJoinMessage(MessageEventArgs e) + { + var message = e.data.DeserializeFromArray(); + + _networking.Join(message.Metadata); + } + + private void HandleLeaveMessage(MessageEventArgs e) + { + _networking.Leave(); + } + + private void HandleSendDataToPeersMessage(MessageEventArgs e) + { + var message = e.data.DeserializeFromArray(); + var peers = new IPeer[message.Peers.Length]; + + for (var i = 0; i < message.Peers.Length; i++) + peers[i] = _Peer.FromIdentifier(message.Peers[i]); + + _networking.SendDataToPeers + ( + message.Tag, + message.Data, + peers, + (TransportType)message.TransportType, + message.SendToSelf + ); + } + + private void HandleStorePersistentKeyValueMessage(MessageEventArgs e) + { + var message = e.data.DeserializeFromArray(); + + var key = System.Text.Encoding.UTF8.GetString(message.Key); + var value = message.Value; + + _networking.StorePersistentKeyValue(key, value); + } + + private void HandleSendDataToArmMessage(MessageEventArgs e) + { + var message = e.data.DeserializeFromArray(); + + _networking.SendDataToArm(message.Tag, message.Data); + } + + private void HandleDestroyMessage(MessageEventArgs e) + { + Dispose(); + } + } +} diff --git a/Assets/ARDK/VirtualStudio/Remote/Networking/_RemoteDeviceMultipeerNetworkingHandler.cs.meta b/Assets/ARDK/VirtualStudio/Remote/Networking/_RemoteDeviceMultipeerNetworkingHandler.cs.meta new file mode 100644 index 0000000..72a9842 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/Networking/_RemoteDeviceMultipeerNetworkingHandler.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 027e75ecb85894ff38e0374a962a9e36 +timeCreated: 1540483658 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/Remote/RemoteConnectionUI.cs b/Assets/ARDK/VirtualStudio/Remote/RemoteConnectionUI.cs new file mode 100644 index 0000000..fc7339c --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/RemoteConnectionUI.cs @@ -0,0 +1,230 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.Collections; +using System.Text; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.Networking; +using Niantic.ARDK.Networking; +using Niantic.ARDK.Utilities.Logging; +using Niantic.ARDK.VirtualStudio.Remote; +using Niantic.ARDK.VirtualStudio.Remote.Data; + +using UnityEngine; +using UnityEngine.UI; + +using Random = System.Random; + +namespace Niantic.ARDK.VirtualStudio.Remote +{ + /// + /// Handles the mobile display logic of Remote Connection. + /// + public class RemoteConnectionUI: MonoBehaviour + { + [Header("Pre-Connection UI")] + [SerializeField] + private GameObject _preSelectionUI = null; + + [SerializeField] + private Button _usbConnectButton = null; + + [SerializeField] + private Button _internetConnectButton = null; + + [Header("Connection Starting UI")] + [SerializeField] + private GameObject _postSelectionUI = null; + + [SerializeField] + private int pinLength = 6; + + [SerializeField] + private Text _pinDisplay = null; + + [Header("Connected UI")] + [SerializeField] + private Text _connectionStatusText = null; + + [SerializeField] + private Text _arSessionStatusText = null; + + [SerializeField] + private Text _networkingStatusText = null; + + [SerializeField] + private Text _arNetworkingStatusText = null; + + private bool _hasSelectedMode; + private IARSession _activeARSession; + + private Random _random = new Random(); + private const string PIN_DISPLAY_TEXT = "PIN: {0}"; + + private void Awake() + { + SubscribeToLifecycleEvents(); + + _preSelectionUI.SetActive(true); + _postSelectionUI.SetActive(false); + + // Setup selection stage. + Camera.main.backgroundColor = Color.black; + + _usbConnectButton.onClick.AddListener + ( + () => { StartConnection(_RemoteConnection.ConnectionMethod.USB); } + ); + + _internetConnectButton.onClick.AddListener + ( + () => { StartConnection(_RemoteConnection.ConnectionMethod.Internet); } + ); + + _RemoteConnection.Deinitialized += Reset; + } + + private void StartConnection(_RemoteConnection.ConnectionMethod connectionMethod) + { + string pin = null; + if (connectionMethod == _RemoteConnection.ConnectionMethod.Internet) + { + // Build a pin. + var pinBuilder = new StringBuilder(); + + for (var i = 0; i < pinLength; i++) + { + var nextChar = (char)_random.Next('A', 'Z'); + pinBuilder.Append(nextChar); + } + + pin = pinBuilder.ToString(); + // Add "PIN:" to the display text, but not the pin used to connect + _pinDisplay.text = string.Format(PIN_DISPLAY_TEXT, pin); + _pinDisplay.enabled = true; + } + else + { + _pinDisplay.enabled = false; + } + + _hasSelectedMode = true; + _preSelectionUI.SetActive(false); + _postSelectionUI.SetActive(true); + + // Connect using settings. + _RemoteConnection.InitIfNone(connectionMethod); + _RemoteConnection.Connect(pin); + } + + private void Reset() + { + _hasSelectedMode = false; + _preSelectionUI.SetActive(true); + _postSelectionUI.SetActive(false); + _pinDisplay.enabled = true; + Camera.main.backgroundColor = Color.blue; + } + + private void Update() + { + if (!_hasSelectedMode) + return; + + // UI is not visible when camera feed is rendering + if (_activeARSession != null && _activeARSession.State == ARSessionState.Running) + return; + + // Update connection info. + if (_RemoteConnection.IsConnected) + { + _connectionStatusText.text = "Connected to editor!"; + Camera.main.backgroundColor = Color.green; + _pinDisplay.enabled = false; + } + else if (_RemoteConnection.IsReady) + { + _connectionStatusText.text = "Waiting for connection..."; + Camera.main.backgroundColor = Color.blue; + } + else + { + _connectionStatusText.text = "Waiting for service..."; + Camera.main.backgroundColor = Color.magenta; + } + } + + private void OnDestroy() + { + _RemoteConnection.Deinitialize(); + } + + private void SubscribeToLifecycleEvents() + { + ARSessionFactory.SessionInitialized += + args => + { + ARLog._Debug("[Remote] ARSession Initialized: " + args.Session.StageIdentifier); + _activeARSession = args.Session; + _activeARSession.Deinitialized += _ => _activeARSession = null; + + UpdateStatusVisual(_arSessionStatusText, true); + + args.Session.Deinitialized += + deinitializedArgs => + { + ARLog._Debug("[Remote] ARSession Deinitialized."); + UpdateStatusVisual(_arSessionStatusText, false); + }; + }; + + MultipeerNetworkingFactory.NetworkingInitialized += + args => + { + ARLog._Debug("[Remote] MultipeerNetworking Initialized: " + args.Networking.StageIdentifier); + UpdateNetworkingsCount(); + UpdateStatusVisual(_networkingStatusText, true); + + args.Networking.Deinitialized += + deinitializedArgs => + { + ARLog._Debug("[Remote] MultipeerNetworking Deinitialized."); + + var networkingsCount = UpdateNetworkingsCount(); + UpdateStatusVisual(_networkingStatusText, networkingsCount > 0); + }; + }; + + ARNetworkingFactory.ARNetworkingInitialized += + args => + { + ARLog._Debug("[Remote] ARNetworking Initialized: " + args.ARNetworking.ARSession.StageIdentifier); + UpdateStatusVisual(_arNetworkingStatusText, true); + + args.ARNetworking.Deinitialized += + deinitializedArgs => + { + ARLog._Debug("[Remote] ARNetworking Deinitialized."); + UpdateStatusVisual(_arNetworkingStatusText, false); + }; + }; + } + + private readonly Color FADED_WHITE = new Color(1, 1, 1, 0.5f); + private void UpdateStatusVisual(Text statusText, bool isConstructed) + { + if (statusText != null) + { + statusText.fontStyle = isConstructed ? FontStyle.Bold : FontStyle.Normal; + statusText.color = isConstructed ? Color.white : FADED_WHITE; + } + } + + private int UpdateNetworkingsCount() + { + var networkingsCount = MultipeerNetworkingFactory.Networkings.Count; + _networkingStatusText.text = "MultipeerNetworking x" + networkingsCount; + return networkingsCount; + } + } +} diff --git a/Assets/ARDK/VirtualStudio/Remote/RemoteConnectionUI.cs.meta b/Assets/ARDK/VirtualStudio/Remote/RemoteConnectionUI.cs.meta new file mode 100644 index 0000000..bab06d4 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/RemoteConnectionUI.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 8a80c1b46f984d76b5428d192e7cb23f +timeCreated: 1544654386 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/Remote/_DeviceHandle.cs b/Assets/ARDK/VirtualStudio/Remote/_DeviceHandle.cs new file mode 100644 index 0000000..1308f9b --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/_DeviceHandle.cs @@ -0,0 +1,59 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Runtime.InteropServices; + +using Niantic.ARDK.Internals; + +namespace Niantic.ARDK.VirtualStudio.Remote +{ + /// + /// A handle for a device on remote connection. + /// + /// + /// This class structurally matches its native counter-part. + /// + [StructLayout(LayoutKind.Explicit)] + internal struct _DeviceHandle: IEquatable<_DeviceHandle> + { + /// + /// The UUID of the device. + /// + [FieldOffset(0)] + public Guid Identifier; + + public bool Equals(_DeviceHandle other) + { + return Identifier.Equals(other.Identifier); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) + return false; + + return obj is _DeviceHandle && Equals((_DeviceHandle)obj); + } + + public override int GetHashCode() + { + return Identifier.GetHashCode(); + } + + /// + /// Checks if two handles are the same. + /// + public static bool operator ==(_DeviceHandle left, _DeviceHandle right) + { + return left.Equals(right); + } + + /// + /// Checks if two handles are not the same. + /// + public static bool operator !=(_DeviceHandle left, _DeviceHandle right) + { + return !left.Equals(right); + } + } +} diff --git a/Assets/ARDK/VirtualStudio/Remote/_DeviceHandle.cs.meta b/Assets/ARDK/VirtualStudio/Remote/_DeviceHandle.cs.meta new file mode 100644 index 0000000..dad29b5 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/_DeviceHandle.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f46e429d00ba4875bb715d791c822937 +timeCreated: 1554415674 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/Remote/_EasyConnection.cs b/Assets/ARDK/VirtualStudio/Remote/_EasyConnection.cs new file mode 100644 index 0000000..c1253fb --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/_EasyConnection.cs @@ -0,0 +1,185 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Concurrent; +using System.IO; + +using Niantic.ARDK.Networking; +using Niantic.ARDK.Utilities.Extensions; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.BinarySerialization; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; +using UnityEngine.Networking.PlayerConnection; + +namespace Niantic.ARDK.VirtualStudio.Remote +{ + /// + /// Helper class to use RemoteConnection without having to worry about Guid IDs for registration + /// or to send messages. + /// Ideally in the future the entire RemoteConnection API will be simplified to be used exactly + /// like this class. + /// + /// + /// An _EasyConnection registration only pairs with an _EasyConnection Send(). + /// So, either use _EasyConnection to register and send a type, or use the RemoteConnection + /// instead. + /// + internal static class _EasyConnection + { + // To avoid using a slow DynamicInvoke on an Action, we use this interface + helper class. + private interface _IMessageExecutor + { + void Execute(object message); + } + + private sealed class _MessageExecutor: + _IMessageExecutor + { + private readonly Action _action; + + internal _MessageExecutor(Action action) + { + _action = action; + } + + public void Execute(object message) + { + T typedMessage = (T)message; + _action(typedMessage); + } + } + + private sealed class _Disposer: + IDisposable + { + private readonly Type _type; + private readonly _IMessageExecutor _executor; + + internal _Disposer(Type type, _IMessageExecutor executor) + { + _type = type; + _executor = executor; + } + + // In .NET 5 there is a TryRemove that gets both key and value. + // For now, we are actually using TryGetValue and then TryRemove with a lock. + private static readonly object _executorsRemoveLock = new object(); + + // Only removes the existing registration if it is the same that was registered. + public void Dispose() + { + // In .NET5 we would just do: + // _executors.TryRemove(KeyValuePair.Create(_type, _executor), out _); + + lock (_executorsRemoveLock) + { + _IMessageExecutor existingExecutor; + _executors.TryGetValue(_type, out existingExecutor); + + if (_executor == existingExecutor) + _executors.TryRemove(_type, out _); + } + } + } + + private static readonly Guid _easyConnectionMessageId = + new Guid("93343898-fcc6-4f77-b5c3-74361c672e77"); + + private static readonly ConcurrentDictionary _executors = + new ConcurrentDictionary(_ReferenceComparer.Instance); + + // As this class depends on RemoteConnection, we must call Initialize() after RemoteConnection + // initialization was done. + public static void Initialize() + { + _RemoteConnection.Register(_easyConnectionMessageId, _MessageReceived); + } + + private static void _MessageReceived(MessageEventArgs args) + { + if (args == null) + throw new ArgumentNullException(nameof(args)); + + var data = args.data; + if (data == null) + throw new ArgumentException("args.data is null.", nameof(args)); + + object message = data.DeserializeFromArray(); + if (message == null) + throw new ArgumentException("args had a null message. That shouldn't happen.", nameof(args)); + + _InvokeExecutor(message); + } + + private static void _InvokeExecutor(object message) + { + var type = message.GetType(); + + _IMessageExecutor executor; + _executors.TryGetValue(type, out executor); + + if (executor != null) + executor.Execute(message); + else + ARLog._Warn("No executor found for message of type: " + type.FullName + "."); + } + + // Returns an object that, when disposed, unregisters the actual registration. + public static IDisposable Register(Action messageExecutor) + { + if (!typeof(T).IsSealed) + throw new InvalidOperationException(typeof(T).FullName + " must be a sealed type."); + + if (messageExecutor == null) + throw new ArgumentNullException(nameof(messageExecutor)); + + var messageExecutorHelper = new _MessageExecutor(messageExecutor); + if (_executors.TryAdd(typeof(T), messageExecutorHelper)) + return new _Disposer(typeof(T), messageExecutorHelper); + + string message = + "There's another message executor already registered for:" + typeof(T).FullName; + + throw new ArgumentException(message, nameof(messageExecutor)); + } + + // Unregisters any handler for type T. Usually it is preferred to store the IDisposable + // object returned from Register and invoke it instead (in that case you only unregister + // the handler if it is your handler). + // Returns whether there was a registration for type T (which was unregistered) or not. + public static bool Unregister() + { + return _executors.TryRemove(typeof(T), out _); + } + + public static void Send(object message, TransportType transportType = TransportType.ReliableUnordered) + { + if (message == null) + throw new ArgumentNullException(nameof(message)); + + var type = message.GetType(); + if (!type.IsSealed) + { + string errorMessage = + "message must be from a sealed type, but type " + type.FullName + " is not sealed."; + + throw new ArgumentException(errorMessage, nameof(message)); + } + + var bytes = message.SerializeToArray(); + _RemoteConnection.Send(_easyConnectionMessageId, bytes, transportType); + } + + internal static class _TestingShim + { +#pragma warning disable 0162 + internal static void _InvokeMessageReceived(MessageEventArgs eventArgs) + { + _MessageReceived(eventArgs); + } +#pragma warning restore 0162 + } + } +} diff --git a/Assets/ARDK/VirtualStudio/Remote/_EasyConnection.cs.meta b/Assets/ARDK/VirtualStudio/Remote/_EasyConnection.cs.meta new file mode 100644 index 0000000..a20872a --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/_EasyConnection.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 45a9f42753f804547aea802cd25bd7ef +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VirtualStudio/Remote/_IRemoteConnectionCompat.cs b/Assets/ARDK/VirtualStudio/Remote/_IRemoteConnectionCompat.cs new file mode 100644 index 0000000..62604d0 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/_IRemoteConnectionCompat.cs @@ -0,0 +1,66 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.Networking; +using Niantic.ARDK.Utilities.Extensions; + +using UnityEngine.Networking.PlayerConnection; + +namespace Niantic.ARDK.VirtualStudio.Remote +{ + /// + /// An interface that defines a compatibility layer between all instances of remote connection. + /// + internal interface _IRemoteConnectionCompat: + IDisposable + { + /// + /// True if the remote connection is connected to another device. + /// + bool IsConnected { get; } + + /// + /// True if the remote connection is ready to connect with another device. + /// + bool IsReady { get; } + + /// + /// The name of the device group the connection is connected to. + /// + string DeviceGroupIdentifier { get; } + + /// + /// The identifier of the local device. + /// + string LocalDeviceIdentifier { get; } + + /// + /// Connects to a device group. + /// + /// The device group name. + void Connect(string groupName); + + /// + /// Registers a message tag with a callback to invoke when a message of that tag is received. + /// + void Register(Guid tag, Action e); + + /// + /// Unregisters a callback with a tag. + /// + void Unregister(Guid tag, Action e); + + /// + /// Sends a message to the remote device. + /// + /// The tag to send the message with. + /// The data to send with the message. + void Send(Guid tag, byte[] data, TransportType transportType); + + /// + /// Disconnects from the remote session. + /// + void Disconnect(); + } +} diff --git a/Assets/ARDK/VirtualStudio/Remote/_IRemoteConnectionCompat.cs.meta b/Assets/ARDK/VirtualStudio/Remote/_IRemoteConnectionCompat.cs.meta new file mode 100644 index 0000000..d275789 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/_IRemoteConnectionCompat.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 572db8bb529745b991b576c4aa58683b +timeCreated: 1554436050 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/Remote/_InternetRemoteConnection.cs b/Assets/ARDK/VirtualStudio/Remote/_InternetRemoteConnection.cs new file mode 100644 index 0000000..509282c --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/_InternetRemoteConnection.cs @@ -0,0 +1,449 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Security; +using System.Text; + +using AOT; + +using Niantic.ARDK.Internals; +using Niantic.ARDK.Networking; +using Niantic.ARDK.Utilities; + +namespace Niantic.ARDK.VirtualStudio.Remote +{ + /// The internet version of RemoteConnection handles remoting by creating a network stack to ARBE. + /// All work is done on the native side and provides a synchronized device role API. + internal sealed unsafe class _InternetRemoteConnection: + IDisposable + { + private void* _nativePtr; + private SafeGCHandle<_InternetRemoteConnection> _ourHandle; + + private HashSet<_DeviceHandle> _deviceHandles = new HashSet<_DeviceHandle>(); + private _LocalDeviceInfo _localDeviceInfo; + private _RemoteConnectionStatus _status; + + public delegate void MessageReceivedCallback(_DeviceHandle sender, Guid tag, byte[] data); + + /// + /// Invoked when a message comes from another device. + /// + public event MessageReceivedCallback ReceivedMessage = (sender, tag, data) => {}; + + /// + /// The set of devices currently in the device group. + /// + /// + /// This is a copy of the internal set. + /// TODO(bpeake): Change this to a IReadOnlyCollection once Unity can upgrade. + /// + public HashSet<_DeviceHandle> Devices + { + get + { + return new HashSet<_DeviceHandle>(_deviceHandles); + } + } + + /// + /// The local device info. + /// + public _LocalDeviceInfo LocalDeviceInfo + { + get + { + return _localDeviceInfo; + } + } + + /// + /// The device group pin currently connected to. Null if not connected. + /// + public string DeviceGroupPin + { + get + { + var pinLength = _NAR_RemoteConnection_GetDeviceGroupPinLength(_nativePtr); + + if (pinLength <= 0) + return null; + + var pinBuffer = new byte[(int)pinLength]; + + fixed (byte* pinBufferPtr = pinBuffer) + _NAR_RemoteConnection_GetDeviceGroupPin(_nativePtr, pinBufferPtr, pinLength); + + return Encoding.UTF8.GetString(pinBuffer); + } + } + + /// + /// The status of the remote connection. + /// + public _RemoteConnectionStatus Status + { + get + { + return _status; + } + } + + /// + /// Creates a new V2 remote connection. + /// + public _InternetRemoteConnection() + { + var stageIdentifier = Guid.NewGuid(); + var localDevice = new _DeviceHandle { Identifier = Guid.NewGuid() }; + + _nativePtr = + _NAR_RemoteConnection_Init + ( + &stageIdentifier, + ServerConfiguration.ARBE.Endpoint, + &localDevice + ); + + // TODO(bpeake) make a version of this that does not get pinned in memory from a callback. + _UpdateLoop.Tick += Update; + } + + ~_InternetRemoteConnection() + { + ReleaseUnmanagedResources(true); + } + + private bool _isDisposed; + public void Dispose() + { + if (_isDisposed) + return; + + _isDisposed = true; + GC.SuppressFinalize(this); + + _CallbackQueue.QueueCallback + ( + () => + { + Disconnect(); + ReleaseUnmanagedResources(false); + } + ); + } + + /// + /// Connects to a device group. + /// + /// The pin of the group to join. + public void Connect(string pin) + { + var bytes = Encoding.UTF8.GetBytes(pin); + + // Store a native reference to this object, but do not have that reference pin it to memory. + _ourHandle = SafeGCHandle.Alloc(this); + + _NAR_RemoteConnection_SetDidReceiveMessageCallback + ( + _nativePtr, + _ourHandle.ToIntPtr(), + InternalMessageReceived + ); + + fixed (byte* bytesPtr = bytes) + _NAR_RemoteConnection_Connect(_nativePtr, bytesPtr, (ulong)bytes.LongLength); + + // TODO(awang): Because of different message handling flows, this will be called in different + // places for different implementations. Unify them somehow? + _EasyConnection.Initialize(); + } + + /// + /// Checks if the device handle is a connected device. + /// + public bool HasDevice(_DeviceHandle deviceHandle) + { + return _NAR_RemoteConnection_DoesDeviceExist(_nativePtr, &deviceHandle); + } + + /// + /// Disconnects from the device group. + /// + public void Disconnect() + { + _NAR_RemoteConnection_SetDidReceiveMessageCallback(_nativePtr, IntPtr.Zero, null); + + _ourHandle.Free(); + _ourHandle = default(SafeGCHandle<_InternetRemoteConnection>); + + _NAR_RemoteConnection_Disconnect(_nativePtr); + } + + /// + /// Gets a device by a role. + /// + /// Role to find the corresponding device for. + /// The device handle that is that role, or none if no device has that role. + public _DeviceHandle? GetDeviceWithRole(_RemoteDeviceRole role) + { + _DeviceHandle foundDevice; + _NAR_RemoteConnection_GetDeviceFromRole(_nativePtr, role, &foundDevice); + + if (foundDevice.Identifier == default(Guid)) + return null; + + return foundDevice; + } + + /// + /// Gets the role of a particular device. + /// + public _RemoteDeviceRole GetRoleOfDevice(_DeviceHandle deviceHandle) + { + return _NAR_RemoteConnection_GetRoleFromDevice(_nativePtr, &deviceHandle); + } + + /// + /// Registers a message tag as being valid with the system. + /// + public void RegisterMessage(Guid tag) + { + _NAR_RemoteConnection_RegisterMessage(_nativePtr, &tag); + } + + /// + /// Sends a message to a particular device. + /// + /// The tag to send it with. + /// The message to send. + /// The target device to send to. + public void SendMessage + ( + Guid tag, + TransportType transportType, + byte[] message, + _DeviceHandle destination + ) + { + fixed (byte* buffer = message) + { + _NAR_RemoteConnection_SendMessage + ( + _nativePtr, + &tag, + buffer, + (UInt64)message.LongLength, + &destination, + (UInt32)transportType + ); + } + } + + [MonoPInvokeCallback(typeof(_NAR_RemoteConnection_MessageReceiveCallback))] + private static void InternalMessageReceived + ( + IntPtr handle, + void* sender, + void* tag, + void* buffer, + ulong size + ) + { + var remoteConnection = SafeGCHandle.TryGetInstance<_InternetRemoteConnection>(handle); + + if (remoteConnection == null) + throw new InvalidOperationException("Native gave back a bad application handle."); + + _DeviceHandle senderHandle = *(_DeviceHandle*)sender; + Guid tagPtr = *(Guid*)tag; + + var data = new byte[size]; + Marshal.Copy((IntPtr)buffer, data, 0, checked((int)size)); + + _CallbackQueue.QueueCallback(() => remoteConnection.ReceivedMessage(senderHandle, tagPtr, data)); + + } + + private void Update() + { + if (_nativePtr == null) + return; + + _NAR_RemoteConnection_SyncMSValues(_nativePtr); + + _deviceHandles.Clear(); + var deviceCount = _NAR_RemoteConnection_DeviceCount(_nativePtr); + _DeviceHandle* devices = stackalloc _DeviceHandle[deviceCount]; + deviceCount = _NAR_RemoteConnection_DeviceBuffer(_nativePtr, devices, deviceCount); + + for (var i = 0; i < deviceCount; i++) + _deviceHandles.Add(devices[i]); + + fixed (_LocalDeviceInfo* localDeviceInfoPtr = &_localDeviceInfo) + _NAR_RemoteConnection_GetLocalDevice(_nativePtr, localDeviceInfoPtr); + + fixed (_RemoteConnectionStatus* statusPtr = &_status) + _NAR_RemoteConnection_GetStatus(_nativePtr, statusPtr); + + _NAR_RemoteConnection_ProcessNetworkMessages(_nativePtr); + } + + private void ReleaseUnmanagedResources(bool isFromGC) + { + if (_nativePtr != null) + { + // Forces a copy of the ptr value, rather than a reference to this, which would prevent GC. + var nativePtrCpy = _nativePtr; + + // Actually dtor on the main thread. + _CallbackQueue.QueueCallback(() => _NAR_RemoteConnection_Release(nativePtrCpy)); + + // When getting called from GC, we know that there cannot be an update callback still. + if (!isFromGC) + _CallbackQueue.QueueCallback(() => _UpdateLoop.Tick -= Update); + + _nativePtr = null; + } + } + + [DllImport(_ARDKLibrary.libraryName)] + [SuppressUnmanagedCodeSecurity] + private static extern void* _NAR_RemoteConnection_Init + ( + Guid* stageIdentifier, + string tcpAddress, + _DeviceHandle* localDeviceHandle + ); + + [DllImport(_ARDKLibrary.libraryName)] + [SuppressUnmanagedCodeSecurity] + private static extern void _NAR_RemoteConnection_Release(void* nativePtr); + + [DllImport(_ARDKLibrary.libraryName)] + [SuppressUnmanagedCodeSecurity] + private static extern void _NAR_RemoteConnection_Connect + ( + void* nativePtr, + byte* deviceGroupPin, + UInt64 deviceGroupPinLength + ); + + [DllImport(_ARDKLibrary.libraryName)] + [SuppressUnmanagedCodeSecurity] + private static extern Int32 _NAR_RemoteConnection_DeviceBuffer + ( + void* nativePtr, + _DeviceHandle* outBuffer, + Int32 sizeOfOutBuffer + ); + + [DllImport(_ARDKLibrary.libraryName)] + [SuppressUnmanagedCodeSecurity] + private static extern Int32 _NAR_RemoteConnection_DeviceCount(void* nativePtr); + + [DllImport(_ARDKLibrary.libraryName)] + [SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool _NAR_RemoteConnection_DoesDeviceExist + ( + void* nativePtr, + _DeviceHandle* deviceHandle + ); + + [DllImport(_ARDKLibrary.libraryName)] + [SuppressUnmanagedCodeSecurity] + private static extern void _NAR_RemoteConnection_Disconnect(void* nativePtr); + + [DllImport(_ARDKLibrary.libraryName)] + [SuppressUnmanagedCodeSecurity] + private static extern void _NAR_RemoteConnection_GetDeviceFromRole + ( + void* nativePtr, + _RemoteDeviceRole role, + _DeviceHandle* outDeviceHandle + ); + + [DllImport(_ARDKLibrary.libraryName)] + [SuppressUnmanagedCodeSecurity] + private static extern _RemoteDeviceRole _NAR_RemoteConnection_GetRoleFromDevice + ( + void* nativePtr, + _DeviceHandle* deviceHandle + ); + + [DllImport(_ARDKLibrary.libraryName)] + [SuppressUnmanagedCodeSecurity] + private static extern void _NAR_RemoteConnection_GetLocalDevice + ( + void* nativePtr, + _LocalDeviceInfo* outLocalDeviceInfo + ); + + [DllImport(_ARDKLibrary.libraryName)] + [SuppressUnmanagedCodeSecurity] + private static extern void _NAR_RemoteConnection_SyncMSValues(void* nativePtr); + + [DllImport(_ARDKLibrary.libraryName)] + [SuppressUnmanagedCodeSecurity] + private static extern void _NAR_RemoteConnection_ProcessNetworkMessages(void* nativePtr); + + [DllImport(_ARDKLibrary.libraryName)] + [SuppressUnmanagedCodeSecurity] + private static extern void _NAR_RemoteConnection_RegisterMessage(void* nativePtr, Guid* tag); + + [DllImport(_ARDKLibrary.libraryName)] + [SuppressUnmanagedCodeSecurity] + private static extern void _NAR_RemoteConnection_SendMessage + ( + void* nativePtr, + Guid* tag, + void* data, + UInt64 size, + _DeviceHandle* destination, + UInt32 connectionType + ); + + // This has to use void* because of a bug with IL2CPP. + delegate void _NAR_RemoteConnection_MessageReceiveCallback + ( + IntPtr applicationHandle, + void* sender, // Device handle + void* tag, // UUID + void* buffer, + UInt64 size + ); + + [DllImport(_ARDKLibrary.libraryName)] + [SuppressUnmanagedCodeSecurity] + private static extern void _NAR_RemoteConnection_SetDidReceiveMessageCallback + ( + void* nativePtr, + IntPtr applicationHandle, + _NAR_RemoteConnection_MessageReceiveCallback callback + ); + + [DllImport(_ARDKLibrary.libraryName)] + [SuppressUnmanagedCodeSecurity] + private static extern UInt64 _NAR_RemoteConnection_GetDeviceGroupPinLength(void* nativePtr); + + [DllImport(_ARDKLibrary.libraryName)] + [SuppressUnmanagedCodeSecurity] + private static extern void _NAR_RemoteConnection_GetDeviceGroupPin + ( + void* nativePtr, + void* outPin, + UInt64 outBufferSize + ); + + [DllImport(_ARDKLibrary.libraryName)] + [SuppressUnmanagedCodeSecurity] + private static extern void _NAR_RemoteConnection_GetStatus + ( + void* nativePtr, + _RemoteConnectionStatus* outRemoteConnectionStatus + ); + } +} diff --git a/Assets/ARDK/VirtualStudio/Remote/_InternetRemoteConnection.cs.meta b/Assets/ARDK/VirtualStudio/Remote/_InternetRemoteConnection.cs.meta new file mode 100644 index 0000000..240e7d9 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/_InternetRemoteConnection.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1a3ad0c76cdde4fd3959a45380aef949 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VirtualStudio/Remote/_InternetRemoteConnectionCompat.cs b/Assets/ARDK/VirtualStudio/Remote/_InternetRemoteConnectionCompat.cs new file mode 100644 index 0000000..032f24d --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/_InternetRemoteConnectionCompat.cs @@ -0,0 +1,175 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; + +using Niantic.ARDK.Networking; +using Niantic.ARDK.Utilities.Extensions; + +using UnityEngine.Networking.PlayerConnection; + +namespace Niantic.ARDK.VirtualStudio.Remote +{ + /// Compat layer for . + internal sealed class _InternetRemoteConnectionCompat: _IRemoteConnectionCompat + { + private readonly Dictionary> _callbackLookup = + new Dictionary>(); + + private readonly _InternetRemoteConnection _internetRemoteConnection; + + /// + public bool IsReady + { + get + { + if (_internetRemoteConnection.Status.State != _RemoteConnectionState.Connected) + { + return false; + } + + var localHandle = _internetRemoteConnection.LocalDeviceInfo.localHandle; + return (_internetRemoteConnection.GetRoleOfDevice(localHandle) != _RemoteDeviceRole.None); + } + } + + /// + public bool IsConnected + { + get + { + if (!IsReady) + { + return false; + } + + var ourRole = + _internetRemoteConnection.GetRoleOfDevice + (_internetRemoteConnection.LocalDeviceInfo.localHandle); + + _RemoteDeviceRole destinationRole; + switch (ourRole) + { + case _RemoteDeviceRole.Application: + destinationRole = _RemoteDeviceRole.Remote; + break; + + case _RemoteDeviceRole.Remote: + destinationRole = _RemoteDeviceRole.Application; + break; + + default: + return false; + } + + var destination = _internetRemoteConnection.GetDeviceWithRole(destinationRole); + return destination != null; + } + } + + /// + public string DeviceGroupIdentifier + { + get + { + return _internetRemoteConnection.DeviceGroupPin; + } + } + + /// + public string LocalDeviceIdentifier + { + get + { + return _internetRemoteConnection.LocalDeviceInfo.localHandle.Identifier.ToString(); + } + } + + public _InternetRemoteConnectionCompat() + { + _internetRemoteConnection = new _InternetRemoteConnection(); + _internetRemoteConnection.ReceivedMessage += (sender, tag, data) => + { + var callbackList = _callbackLookup.GetOrInsert(tag, () => args => {}); + callbackList + ( + new MessageEventArgs() + { + data = data, playerId = tag.GetHashCode(), + } + ); + }; + } + + /// + public void Connect(string groupName) + { + _internetRemoteConnection.Connect(groupName); + } + + /// + public void Register(Guid tag, Action e) + { + var callbackList = _callbackLookup.GetOrInsert(tag, () => args => {}); + + var newCallbackList = callbackList + e; + _callbackLookup[tag] = newCallbackList; + + _internetRemoteConnection.RegisterMessage(tag); + } + + /// + public void Unregister(Guid tag, Action e) + { + var callbackList = _callbackLookup.GetOrInsert(tag, () => args => {}); + + var newCallbackList = callbackList - e; + _callbackLookup[tag] = newCallbackList; + } + + /// + public void Send(Guid tag, byte[] data, TransportType transportType) + { + var ourRole = + _internetRemoteConnection.GetRoleOfDevice + (_internetRemoteConnection.LocalDeviceInfo.localHandle); + + _RemoteDeviceRole destinationRole; + switch (ourRole) + { + case _RemoteDeviceRole.Application: + destinationRole = _RemoteDeviceRole.Remote; + break; + + case _RemoteDeviceRole.Remote: + destinationRole = _RemoteDeviceRole.Application; + break; + + default: + throw new ArgumentOutOfRangeException(); + } + + var destination = _internetRemoteConnection.GetDeviceWithRole(destinationRole); + + if (destination == null) + { + throw new InvalidOperationException("Unknown destination, remote connection not ready."); + } + + _internetRemoteConnection.SendMessage(tag, transportType, data, destination.Value); + } + + /// + public void Disconnect() + { + _internetRemoteConnection.Disconnect(); + } + + /// + public void Dispose() + { + if (_internetRemoteConnection != null) + _internetRemoteConnection.Dispose(); + } + } +} diff --git a/Assets/ARDK/VirtualStudio/Remote/_InternetRemoteConnectionCompat.cs.meta b/Assets/ARDK/VirtualStudio/Remote/_InternetRemoteConnectionCompat.cs.meta new file mode 100644 index 0000000..718f15f --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/_InternetRemoteConnectionCompat.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 27acd4ee6e854ca79f9d6f7d4eaa7be4 +timeCreated: 1554437931 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/Remote/_LocalDeviceInfo.cs b/Assets/ARDK/VirtualStudio/Remote/_LocalDeviceInfo.cs new file mode 100644 index 0000000..4550082 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/_LocalDeviceInfo.cs @@ -0,0 +1,22 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.Runtime.InteropServices; + +namespace Niantic.ARDK.VirtualStudio.Remote +{ + /// + /// Info about the local device. + /// + /// + /// This structure matches its native counter part. + /// + [StructLayout(LayoutKind.Explicit)] + internal struct _LocalDeviceInfo + { + /// + /// The handle of the local device. + /// + [FieldOffset(0)] + public _DeviceHandle localHandle; + } +} diff --git a/Assets/ARDK/VirtualStudio/Remote/_LocalDeviceInfo.cs.meta b/Assets/ARDK/VirtualStudio/Remote/_LocalDeviceInfo.cs.meta new file mode 100644 index 0000000..0e79ebc --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/_LocalDeviceInfo.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e325602690db40b2802fa530dbbea32a +timeCreated: 1554418401 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/Remote/_RemoteConnection.cs b/Assets/ARDK/VirtualStudio/Remote/_RemoteConnection.cs new file mode 100644 index 0000000..39cf3ab --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/_RemoteConnection.cs @@ -0,0 +1,333 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using Niantic.ARDK.Networking; +using Niantic.ARDK.Utilities.Extensions; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Logging; +using Niantic.ARDK.VirtualStudio.Remote; +using Niantic.ARDK.VirtualStudio.Remote.Data; +#if UNITY_EDITOR +using UnityEditor.Networking.PlayerConnection; +using UnityEditor; +#endif + +using UnityEngine; +using UnityEngine.Networking.PlayerConnection; +using UnityEngine.Serialization; + +using Object = UnityEngine.Object; + +namespace Niantic.ARDK.VirtualStudio.Remote +{ + /// TODO(bpeake): Make instantiatable type for testing. + /// Helper class for handling the remote connection with the player/editor. + internal static class _RemoteConnection + { + public enum ConnectionMethod + { + USB, + Internet, + } + + private struct BufferedMessage + { + public Guid Tag; + public TransportType TransportType; + public byte[] Data; + } + + // Messages that were sent while disconnected still. + private static readonly List _bufferedMessages = new List(); + + private static _IRemoteConnectionCompat _remoteConnectionImpl; + + /// True if the remote connection is connected to another device. + public static bool IsConnected + { + get + { + return _remoteConnectionImpl != null && _remoteConnectionImpl.IsConnected; + } + } + + /// True if the remote connection is ready to connect to another device. + public static bool IsReady + { + get + { + return _remoteConnectionImpl != null && _remoteConnectionImpl.IsReady; + } + } + + public static bool IsEnabled + { + get + { +#if UNITY_EDITOR + var use = PlayerPrefs.GetInt(ARDKUseRemoteProperty, 0); + return use == 1; +#else + return true; +#endif + } +#if UNITY_EDITOR + set + { + if (!Application.isPlaying) + PlayerPrefs.SetInt(ARDKUseRemoteProperty, value ? 1 : 0); + } +#endif + } + + private const string ARDKUseRemoteProperty = "ARDK_Use_Remote"; + + /// The secret that was used to connect devices together. + public static string Secret + { + get + { + if (_remoteConnectionImpl != null) + return _remoteConnectionImpl.DeviceGroupIdentifier; + + return ""; + } + } + + /// The ID associated with the connection. + public static string ConnectionID + { + get + { + if (_remoteConnectionImpl != null) + return _remoteConnectionImpl.LocalDeviceIdentifier; + + return ""; + } + } + + /// The version that is being used. + public static ConnectionMethod CurrentConnectionMethod + { + get + { + return _connectionMethod; + } + } + + private static ConnectionMethod _connectionMethod; + + /// + /// Initializes the remote connection using the version of remote connection that corresponds + /// with the given connection method. + /// + /// The connection method to use. + /// If an unknown connection method is given. + public static void InitIfNone(ConnectionMethod connectionMethod) + { + if (_remoteConnectionImpl != null) + { + ARLog._Debug("RemoteConnection was already initialized."); + return; + } + + Init(connectionMethod); + } + + private static void Init(ConnectionMethod connectionMethod) + { + Screen.orientation = ScreenOrientation.Portrait; + Screen.autorotateToPortrait = false; + Screen.autorotateToLandscapeLeft = false; + Screen.autorotateToLandscapeRight = false; + Screen.autorotateToPortraitUpsideDown = false; + Screen.sleepTimeout = SleepTimeout.NeverSleep; + + Application.runInBackground = true; + + Platform.Init(); + + if (_remoteConnectionImpl != null) + _remoteConnectionImpl.Dispose(); + + _connectionMethod = connectionMethod; + + switch (connectionMethod) + { + case ConnectionMethod.USB: + _remoteConnectionImpl = new _UsbRemoteConnection(); + + // TODO(awang): Because of different message handling flows, this will be called in + // different places for different implementations. Unify them somehow? + _EasyConnection.Initialize(); + break; + + case ConnectionMethod.Internet: + _remoteConnectionImpl = new _InternetRemoteConnectionCompat(); + break; + + default: + throw new ArgumentOutOfRangeException(); + } + + _CallbackQueue.ApplicationWillQuit += OnApplicationWillQuit; + + _EasyConnection.Register(Deinitialize); + +#if !UNITY_EDITOR + _RemoteDeviceARSessionConstructor.RegisterForInitMessage(); + _RemoteDeviceMultipeerNetworkingConstructor.RegisterForInitMessage(); + _RemoteDeviceARNetworkingConstructor.RegisterForInitMessage(); +#endif + } + + public static void Deinitialize() + { + _EasyConnection.Send(new RemoteConnectionDestroyMessage()); + Dispose(); + } + + private static void Deinitialize(RemoteConnectionDestroyMessage message) + { + // Dispose before raising error, in case Unity Editor is set to pause on errors + Dispose(); + +#if UNITY_EDITOR + ARLog._Error("Lost connection with the ARDK Remote Feed App."); +#endif + } + + private static void Dispose() + { + var connection = _remoteConnectionImpl; + if (connection == null) + return; + + var handler = Deinitialized; + if (handler != null) + handler(); + + _EasyConnection.Unregister(); + + _remoteConnectionImpl = null; + connection.Dispose(); + + _RemoteDeviceARSessionConstructor._Deinitialize(); + _RemoteDeviceMultipeerNetworkingConstructor._Deinitialize(); + _RemoteDeviceARNetworkingConstructor._Deinitialize(); + } + + private static void OnApplicationWillQuit() + { + _CallbackQueue.ApplicationWillQuit -= OnApplicationWillQuit; + Deinitialize(); + } + + /// + /// Connects the remote connection to a specific pin. + /// + public static void Connect(string pin) + { + if (_remoteConnectionImpl != null) + _remoteConnectionImpl.Connect(pin); + } + + /// + /// Registers a callback to be called whenever data is sent over the specific id. + /// + /// The id of the data. + /// The event to fire when data of the specific id comes. + public static void Register(Guid id, Action e) + { + if (_remoteConnectionImpl != null) + _remoteConnectionImpl.Register(id, e); + } + + /// + /// Unregisters a callback. + /// + /// The id to unregister from. + /// The callback to unregister. + public static void Unregister(Guid id, Action e) + { + if (_remoteConnectionImpl != null) + _remoteConnectionImpl.Unregister(id, e); + } + + /// + /// Sends data over the remote connection. + /// + /// The id to send with the data. + /// The data to send. + /// The protocol to send the data with. + public static void Send(Guid id, byte[] data, TransportType transportType = TransportType.ReliableUnordered) + { + bool readyAndConnected = + _remoteConnectionImpl != null && + _remoteConnectionImpl.IsReady && + _remoteConnectionImpl.IsConnected; + + if (readyAndConnected) + { + if (_bufferedMessages.Count != 0) + TryClearBuffer(); + + _remoteConnectionImpl.Send(id, data, transportType); + } + else + { + var message = + new BufferedMessage() + { + Tag = id, + TransportType = transportType, + Data = data, + }; + + _bufferedMessages.Add(message); + + if (_bufferedMessages.Count == 1) + _CallbackQueue.QueueCallback(_tryClearBufferAction); + } + } + + /// + /// Sends a message over remote connection. + /// + /// The id of the message. + /// The value to send. + /// The protocol to send the data with. + public static void Send(Guid id, TValue value, TransportType transportType = TransportType.ReliableUnordered) + { + Send(id, value.SerializeToArray(), transportType); + } + + // Store the delegate once so we don't keep allocating new Action objects per call. + private static readonly Action _tryClearBufferAction = TryClearBuffer; + private static void TryClearBuffer() + { + bool readyAndConnected = + _remoteConnectionImpl != null && + _remoteConnectionImpl.IsReady && + _remoteConnectionImpl.IsConnected; + + if (!readyAndConnected) + { + _CallbackQueue.QueueCallback(TryClearBuffer); + return; + } + + var messages = _bufferedMessages.ToArray(); + _bufferedMessages.Clear(); + + foreach (var bufferedMessage in messages) + Send(bufferedMessage.Tag, bufferedMessage.Data, bufferedMessage.TransportType); + } + + public static Action Deinitialized; + } +} diff --git a/Assets/ARDK/VirtualStudio/Remote/_RemoteConnection.cs.meta b/Assets/ARDK/VirtualStudio/Remote/_RemoteConnection.cs.meta new file mode 100644 index 0000000..76627a6 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/_RemoteConnection.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9f8b6fd4cde14e75b495c82fef7e34cb +timeCreated: 1544649705 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/Remote/_RemoteConnectionStatus.cs b/Assets/ARDK/VirtualStudio/Remote/_RemoteConnectionStatus.cs new file mode 100644 index 0000000..62078a7 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/_RemoteConnectionStatus.cs @@ -0,0 +1,62 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.Runtime.InteropServices; + +namespace Niantic.ARDK.VirtualStudio.Remote +{ + /// + /// The state of the remote connection. + /// + internal enum _RemoteConnectionState: byte + { + /// + /// No remote connection stack has been made. + /// + None, + + /// + /// The remote connection stack has been made. + /// + Initialized, + + /// + /// Remote connection is in the process of connecting.q + /// + Connecting, + + /// + /// The remote connection is connected. + /// + Connected, + } + + internal enum _RemoteConnectionError: byte + { + /// + /// No error. + /// + None, + + /// + /// Remote connection failed to connect. + /// + ConnectionError, + } + + /// + /// The status of the remote connection. + /// + [StructLayout(LayoutKind.Sequential)] + internal struct _RemoteConnectionStatus + { + /// + /// What state the remote connection is in. + /// + public _RemoteConnectionState State; + + /// + /// The error assosiated with the state. + /// + public _RemoteConnectionError Error; + } +} diff --git a/Assets/ARDK/VirtualStudio/Remote/_RemoteConnectionStatus.cs.meta b/Assets/ARDK/VirtualStudio/Remote/_RemoteConnectionStatus.cs.meta new file mode 100644 index 0000000..30893c9 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/_RemoteConnectionStatus.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3febd9e303ac4a9c888ece3b71f3773d +timeCreated: 1554434953 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/Remote/_RemoteDeviceRole.cs b/Assets/ARDK/VirtualStudio/Remote/_RemoteDeviceRole.cs new file mode 100644 index 0000000..1c1d40e --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/_RemoteDeviceRole.cs @@ -0,0 +1,26 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.VirtualStudio.Remote +{ + /// + /// The roles that remote device can be in. + /// + internal enum _RemoteDeviceRole: + byte + { + /// + /// No role. + /// + None, + + /// + /// The device is running the application. + /// + Application, + + /// + /// The device is running the remote sessions. + /// + Remote, + } +} diff --git a/Assets/ARDK/VirtualStudio/Remote/_RemoteDeviceRole.cs.meta b/Assets/ARDK/VirtualStudio/Remote/_RemoteDeviceRole.cs.meta new file mode 100644 index 0000000..e743dd8 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/_RemoteDeviceRole.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d97c71daebbb4de896325a077aed3b0a +timeCreated: 1554418521 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/Remote/_UsbRemoteConnection.cs b/Assets/ARDK/VirtualStudio/Remote/_UsbRemoteConnection.cs new file mode 100644 index 0000000..14933f2 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/_UsbRemoteConnection.cs @@ -0,0 +1,202 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Linq; + +using Niantic.ARDK.Networking; +using Niantic.ARDK.Utilities.Extensions; +using Niantic.ARDK.Utilities.Logging; + +using UnityEngine; +using UnityEngine.Networking.PlayerConnection; + +#if UNITY_EDITOR +using UnityEditor.Networking.PlayerConnection; +using UnityEditor; +#endif + +namespace Niantic.ARDK.VirtualStudio.Remote +{ + /// + /// Remote connection implementation that goes over USB using the unity profiler utils. + /// + internal sealed class _UsbRemoteConnection: _IRemoteConnectionCompat + { + private RemoteMessageHandler _handler; + + /// + public bool IsConnected + { + get + { +#if UNITY_EDITOR + return EditorConnection.instance.ConnectedPlayers.Count > 0; +#else + return PlayerConnection.instance.isConnected; +#endif + } + } + + /// + public bool IsReady + { + get + { + return true; + } + } + + /// + public string DeviceGroupIdentifier + { + get + { + return "Unity Player Connection"; + } + } + + /// + public string LocalDeviceIdentifier + { + get + { + return SystemInfo.deviceUniqueIdentifier; + } + } + + public _UsbRemoteConnection() + { + EnsureCreation(); + } + + /// + public void Connect(string groupName) + { +#if UNITY_EDITOR + EditorConnection.instance.Initialize(); +#endif + } + + /// + public void Register(Guid tag, Action e) + { + _handler.Register(tag, e); + } + + /// + public void Unregister(Guid tag, Action e) + { + _handler.Unregister(tag, e); + } + + /// + public void Send(Guid tag, byte[] data, TransportType transportType) + { + _handler.Send(tag, data); + } + + /// + public void Disconnect() + { +#if UNITY_EDITOR + EditorConnection.instance.DisconnectAll(); +#else + PlayerConnection.instance.DisconnectAll(); +#endif + } + + private void EnsureCreation() + { + if (_handler != null) + return; + + var go = new GameObject(); + _handler = go.AddComponent(); + } + + public void Dispose() + { + Disconnect(); + } + } + + /// + /// Helper monobehaviour to ensure registeration happens on a unity object. + /// + internal class RemoteMessageHandler: MonoBehaviour + { + private static readonly Guid GlobalMessageGuid = + new Guid("235da759-52e0-4542-adb5-226e1b994328"); + + private readonly Dictionary>> _commandLookup = + new Dictionary>>(); + + private void Awake() + { +#if UNITY_EDITOR + EditorConnection.instance.Register(GlobalMessageGuid, Callback); +#else + PlayerConnection.instance.Register(GlobalMessageGuid, Callback); +#endif + + hideFlags = HideFlags.HideInHierarchy; + DontDestroyOnLoad(gameObject); + } + + public void Register(Guid messageGuid, Action callback) + { + _commandLookup.GetOrInsertNew(messageGuid).Add(callback); + } + + public void Unregister(Guid messageGuid, Action callback) + { + _commandLookup.GetOrInsertNew(messageGuid).Remove(callback); + } + + public void Send(Guid id, byte[] data) + { + var dataStruct = new Data() + { + ID = id.ToByteArray(), Contents = data, + }; +#if UNITY_EDITOR + EditorConnection.instance.Send(GlobalMessageGuid, dataStruct.SerializeToArray()); +#else + PlayerConnection.instance.Send(GlobalMessageGuid, dataStruct.SerializeToArray()); +#endif + } + + private void Callback(MessageEventArgs e) + { + var data = e.data.DeserializeFromArray(); + var guid = new Guid(data.ID); + var eventArgs = new MessageEventArgs() + { + data = data.Contents, playerId = e.playerId, + }; + + var commands = _commandLookup.GetOrDefault(guid); + + if (commands != null) + { + foreach (var command in commands.ToArray()) + command(eventArgs); + } + else + { + ARLog._WarnFormat("Message {0} has no handlers.", false, guid); + } + } + + /// + /// Structure to allow forwarding the message under a global id. + /// + [Serializable] + public class Data + { + public byte[] ID; + public byte[] Contents; + } + } +} diff --git a/Assets/ARDK/VirtualStudio/Remote/_UsbRemoteConnection.cs.meta b/Assets/ARDK/VirtualStudio/Remote/_UsbRemoteConnection.cs.meta new file mode 100644 index 0000000..2411991 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/Remote/_UsbRemoteConnection.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 313c77a460c84b7d8cbfb39c15977694 +timeCreated: 1554436343 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/VpsCoverage.meta b/Assets/ARDK/VirtualStudio/VpsCoverage.meta new file mode 100644 index 0000000..8b87059 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/VpsCoverage.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3206cecb865249fdaafcbd0707f2986c +timeCreated: 1647360662 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/VpsCoverage/VPSCoverageResponses.asset b/Assets/ARDK/VirtualStudio/VpsCoverage/VPSCoverageResponses.asset new file mode 100644 index 0000000..c12afcd --- /dev/null +++ b/Assets/ARDK/VirtualStudio/VpsCoverage/VPSCoverageResponses.asset @@ -0,0 +1,65 @@ +%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: f974ac2009694edcb34a89b241a0d9ee, type: 3} + m_Name: VPSCoverageResponses + m_EditorClassIdentifier: + Coverage: + Areas: + - _localizationTargetIdentifiers: + - target1 + _shape: + - lat_degrees: 37.796263 + lng_degrees: -122.39396 + - lat_degrees: 37.79595 + lng_degrees: -122.39396 + - lat_degrees: 37.79595 + lng_degrees: -122.394408 + - lat_degrees: 37.796263 + lng_degrees: -122.394408 + _localizabilityQuality: 1 + - _localizationTargetIdentifiers: + - target2 + - target3 + _shape: + - lat_degrees: 37.795523 + lng_degrees: -122.393855 + - lat_degrees: 37.795523 + lng_degrees: -122.393333 + - lat_degrees: 37.79526 + lng_degrees: -122.393333 + - lat_degrees: 37.79526 + lng_degrees: -122.393855 + _localizabilityQuality: 2 + ResponseStatus: 1 + ErrorMessage: + LocalizationTargets: + Targets: + - _identifier: target1 + _name: acme bread + _center: + lat_degrees: 37.7961 + lng_degrees: -122.39425 + _imageURL: https://lh3.googleusercontent.com/sZl-o9TGNYXucrPNHesxaMLXajhcPYqw43zojzHJ-y1yYYeQaNtJMrPUQImKgak3paKOMbEm0Av0e5bKG8_z31m1xVGN8J3x-EIAfgeETIhrLxwsw7xWEGstIuwyKYuHjOLFPCcvqIBY944PWFHBhgSEsVERXJljVEwPTD1xpJHhi5gHieiZcjl-rJ734bFiDxG1GzTxkX5nRc9lkRhtNHMdHDOSswMU-dgp8itMF8lTdEztOYz_bE_8H2FxN5NtCBmeOvxTi7f31wM2zrAE7oOzzeVy1_hYLFAWuXJ0CNqDfc-J-Ui9HY1RILj9Z1nYvEKGGDSTiT3tzysWHO9Vn6rXDFKE9TUGNE1_Z9_EaQ7B_HIU_z7oq2Hmmikl1Ap5t7N_pEI44ZhUGbIVirHKJyvc2LgtJgczCeNEgH7SnvvYBCM-OMWX5MnB949rXYn678iZyz7Q16wjPMevr1IQU4zfdOE2xoJQi8x3FhpD2-3moUoilZRBR5OQi-KII4hRYrEaRFnAiGqYeFz3Rqwx_Yw97kROwh2AnfhT03700AHkFqmYobTXjq0Q3IQpjcYQZ3vbtw + - _identifier: target2 + _name: ferry building entrance + _center: + lat_degrees: 37.795413 + lng_degrees: -122.393614 + _imageURL: https://lh3.googleusercontent.com/sZl-o9TGNYXucrPNHesxaMLXajhcPYqw43zojzHJ-y1yYYeQaNtJMrPUQImKgak3paKOMbEm0Av0e5bKG8_z31m1xVGN8J3x-EIAfgeETIhrLxwsw7xWEGstIuwyKYuHjOLFPCcvqIBY944PWFHBhgSEsVERXJljVEwPTD1xpJHhi5gHieiZcjl-rJ734bFiDxG1GzTxkX5nRc9lkRhtNHMdHDOSswMU-dgp8itMF8lTdEztOYz_bE_8H2FxN5NtCBmeOvxTi7f31wM2zrAE7oOzzeVy1_hYLFAWuXJ0CNqDfc-J-Ui9HY1RILj9Z1nYvEKGGDSTiT3tzysWHO9Vn6rXDFKE9TUGNE1_Z9_EaQ7B_HIU_z7oq2Hmmikl1Ap5t7N_pEI44ZhUGbIVirHKJyvc2LgtJgczCeNEgH7SnvvYBCM-OMWX5MnB949rXYn678iZyz7Q16wjPMevr1IQU4zfdOE2xoJQi8x3FhpD2-3moUoilZRBR5OQi-KII4hRYrEaRFnAiGqYeFz3Rqwx_Yw97kROwh2AnfhT03700AHkFqmYobTXjq0Q3IQpjcYQZ3vbtw + - _identifier: target3 + _name: ferry plaza farmer\u0027s market + _center: + lat_degrees: 37.795362 + lng_degrees: -122.393607 + _imageURL: https://lh3.googleusercontent.com/sZl-o9TGNYXucrPNHesxaMLXajhcPYqw43zojzHJ-y1yYYeQaNtJMrPUQImKgak3paKOMbEm0Av0e5bKG8_z31m1xVGN8J3x-EIAfgeETIhrLxwsw7xWEGstIuwyKYuHjOLFPCcvqIBY944PWFHBhgSEsVERXJljVEwPTD1xpJHhi5gHieiZcjl-rJ734bFiDxG1GzTxkX5nRc9lkRhtNHMdHDOSswMU-dgp8itMF8lTdEztOYz_bE_8H2FxN5NtCBmeOvxTi7f31wM2zrAE7oOzzeVy1_hYLFAWuXJ0CNqDfc-J-Ui9HY1RILj9Z1nYvEKGGDSTiT3tzysWHO9Vn6rXDFKE9TUGNE1_Z9_EaQ7B_HIU_z7oq2Hmmikl1Ap5t7N_pEI44ZhUGbIVirHKJyvc2LgtJgczCeNEgH7SnvvYBCM-OMWX5MnB949rXYn678iZyz7Q16wjPMevr1IQU4zfdOE2xoJQi8x3FhpD2-3moUoilZRBR5OQi-KII4hRYrEaRFnAiGqYeFz3Rqwx_Yw97kROwh2AnfhT03700AHkFqmYobTXjq0Q3IQpjcYQZ3vbtw + ResponseStatus: 1 + ErrorMessage: diff --git a/Assets/ARDK/VirtualStudio/VpsCoverage/VPSCoverageResponses.asset.meta b/Assets/ARDK/VirtualStudio/VpsCoverage/VPSCoverageResponses.asset.meta new file mode 100644 index 0000000..237732b --- /dev/null +++ b/Assets/ARDK/VirtualStudio/VpsCoverage/VPSCoverageResponses.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 107c27603c8c349f18af4098a4f99ff7 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VirtualStudio/VpsCoverage/VpsCoverageResponses.cs b/Assets/ARDK/VirtualStudio/VpsCoverage/VpsCoverageResponses.cs new file mode 100644 index 0000000..20e188d --- /dev/null +++ b/Assets/ARDK/VirtualStudio/VpsCoverage/VpsCoverageResponses.cs @@ -0,0 +1,81 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; +using System.Collections.Generic; +using System.Linq; + +using Niantic.ARDK.VPSCoverage; +using Niantic.ARDK.VPSCoverage.GeoserviceMessages; + +using UnityEngine; + +namespace Niantic.ARDK.VirtualStudio.VpsCoverage +{ + // Ensure object is a singleton by hiding UI to create another instance. Not foolproof because an + // instance could be created by script, but good enough? + //[CreateAssetMenu(fileName = "VPS Coverage Responses", menuName = "ARDK/VPS Coverage Responses", order = 0)] + public class VpsCoverageResponses: ScriptableObject + { + public CoverageData Coverage; + public LocalizationTargetsData LocalizationTargets; + + [Serializable] + public struct CoverageData + { + public CoverageArea[] Areas; + public ResponseStatus ResponseStatus; + public string ErrorMessage; + + internal _CoverageAreasResponse ToResponse() + { + var areas = Areas.Select + ( + a => new _CoverageAreasResponse.VpsCoverageArea + ( + new _CoverageAreasResponse.Shape(a.Shape), + a.LocalizationTargetIdentifiers, + a.LocalizabilityQuality.ToString() + ) + ); + + return new _CoverageAreasResponse + ( + areas.ToArray(), + ResponseStatus.ToString(), + ErrorMessage + ); + } + } + + [Serializable] + public struct LocalizationTargetsData + { + public LocalizationTarget[] Targets; + public ResponseStatus ResponseStatus; + public string ErrorMessage; + + + internal _LocalizationTargetsResponse ToResponse(string[] targetIdentifiers) + { + var filteredTargets = Targets.Where(t => targetIdentifiers.Contains(t.Identifier)); + + var details = filteredTargets.Select + ( + t => new _LocalizationTargetsResponse.VpsLocalizationTarget + ( + new _LocalizationTargetsResponse.Shape(t.Center), + t.Identifier, + t.Name, + t.ImageURL + ) + ); + + return new _LocalizationTargetsResponse + ( + details.ToArray(), + ResponseStatus.ToString(), + ErrorMessage + ); + } + } + } +} diff --git a/Assets/ARDK/VirtualStudio/VpsCoverage/VpsCoverageResponses.cs.meta b/Assets/ARDK/VirtualStudio/VpsCoverage/VpsCoverageResponses.cs.meta new file mode 100644 index 0000000..c13ddf7 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/VpsCoverage/VpsCoverageResponses.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f974ac2009694edcb34a89b241a0d9ee +timeCreated: 1647360678 \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/_VirtualStudioManager.cs b/Assets/ARDK/VirtualStudio/_VirtualStudioManager.cs new file mode 100644 index 0000000..6a335e8 --- /dev/null +++ b/Assets/ARDK/VirtualStudio/_VirtualStudioManager.cs @@ -0,0 +1,383 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.Anchors; +using Niantic.ARDK.AR.ARSessionEventArgs; +using Niantic.ARDK.AR.Networking; +using Niantic.ARDK.AR.Networking.ARNetworkingEventArgs; +using Niantic.ARDK.Networking; +using Niantic.ARDK.Networking.MultipeerNetworkingEventArgs; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Logging; +using Niantic.ARDK.VirtualStudio.AR; +using Niantic.ARDK.VirtualStudio.AR.Networking; +using Niantic.ARDK.VirtualStudio.AR.Networking.Mock; +using Niantic.ARDK.VirtualStudio.Networking; +using Niantic.ARDK.VirtualStudio.Networking.Mock; + +using UnityEngine; + +namespace Niantic.ARDK.VirtualStudio +{ + internal sealed class _VirtualStudioManager: + _IVirtualStudioManager + { + public const string LOCAL_PLAYER_NAME = "LocalPlayer"; + + public static _IVirtualStudioManager Instance + { + get + { + _StaticMemberValidator._FieldIsNullWhenScopeEnds(() => _instance); + + lock (_instanceLock) + { + if (_instance == null) + _instance = new _VirtualStudioManager(); + + return _instance; + } + } + } + + internal static void _ResetInstance() + { + _VirtualStudioManager instance; + + lock (_instanceLock) + instance = _instance; + + if (instance != null) + instance.Dispose(); // The Dispose actually resets the instance. + } + + public _IEditorARSessionMediator ArSessionMediator + { + get { return _arSessionMediator; } + } + + public _IEditorMultipeerSessionMediator MultipeerMediator + { + get { return _multipeerMediator; } + } + + public _IEditorARNetworkingSessionMediator ArNetworkingMediator + { + get { return _arNetworkingMediator; } + } + + public MockPlayer LocalPlayer + { + get { return _localPlayer; } + } + + public MockPlayConfiguration PlayConfiguration { get; private set; } + + private static _VirtualStudioManager _instance; + private static object _instanceLock = new object(); + + private readonly _IEditorARSessionMediator _arSessionMediator; + private readonly _IEditorMultipeerSessionMediator _multipeerMediator; + private readonly _IEditorARNetworkingSessionMediator _arNetworkingMediator; + + private readonly Dictionary _arSessionIdentifierToPlayerName = + new Dictionary(); + + private readonly Dictionary _networkingIdentifierToPlayerName = + new Dictionary(); + + private readonly Dictionary _mockPlayers = + new Dictionary(); + + private MockPlayer _localPlayer; + private IMultipeerNetworking _networking; + private IARNetworking _arNetworking; + private IARSession _arSession; + + private _VirtualStudioManager() + { + _arSessionMediator = new _MockARSessionMediator(this); + _multipeerMediator = new _MockNetworkingSessionsMediator(this); + _arNetworkingMediator = new _MockARNetworkingSessionsMediator(this); + + _CallbackQueue.ApplicationWillQuit += Dispose; + + ARSessionFactory.SessionInitialized += SetLocalStage; + MultipeerNetworkingFactory.NetworkingInitialized += SetLocalStage; + ARNetworkingFactory.ARNetworkingInitialized += SetLocalStage; + + ARLog._Debug("VirtualStudioMaster Initialized."); + } + + ~_VirtualStudioManager() + { + ARLog._Error("_VirtualStudioManager was not correctly disposed."); + } + + public void Dispose() + { + GC.SuppressFinalize(this); + + _instance = null; + + ARSessionFactory.SessionInitialized -= SetLocalStage; + + var oldSession = _arSession; + if (oldSession != null) + oldSession.Deinitialized -= RemoveLocalStage; + + MultipeerNetworkingFactory.NetworkingInitialized -= SetLocalStage; + + var oldNetworking = _networking; + if (oldNetworking != null) + oldNetworking.Deinitialized -= _RemoveLocalStageFromMultipeerNetworking; + + ARNetworkingFactory.ARNetworkingInitialized -= SetLocalStage; + + var arNetworking = _arNetworking; + if (arNetworking != null) + { + _arNetworking = null; + arNetworking.Deinitialized -= RemoveLocalStage; + } + + // ARNetworking objects must be disposed before ARSession and MultipeerNetworking, + // because methods subscribed to ARNetworking.WillDeinitialize often use that + // ARNetworking's Networking reference + _arNetworkingMediator.Dispose(); + + _arSessionMediator.Dispose(); + _multipeerMediator.Dispose(); + + ARLog._Debug("VirtualStudioMaster Disposed."); + } + + private void SetLocalStage(AnyARSessionInitializedArgs args) + { + // Camera controller must be initialized for both remote and mock players, + // so don't check for mock implementation here. + + var player = SetLocalPlayerIfNeeded(); + if (player == null) + return; + + var oldSession = _arSession; + if (oldSession != null) + oldSession.Deinitialized -= RemoveLocalStage; + + var arSession = args.Session; + _arSession = arSession; + _arSessionIdentifierToPlayerName.Add(arSession.StageIdentifier, player.Name); + player.SetARSession(arSession); + arSession.Deinitialized += RemoveLocalStage; + } + + private void SetLocalStage(AnyMultipeerNetworkingInitializedArgs args) + { + var mockNetworking = args.Networking as _MockMultipeerNetworking; + if (mockNetworking == null) + return; + + var player = SetLocalPlayerIfNeeded(); + if (player == null) + return; + + var oldNetworking = _networking; + if (oldNetworking != null) + oldNetworking.Deinitialized -= _RemoveLocalStageFromMultipeerNetworking; + + _networking = mockNetworking; + _networkingIdentifierToPlayerName.Add(_networking.StageIdentifier, player.Name); + player.SetMultipeerNetworking(mockNetworking); + _networking.Deinitialized += _RemoveLocalStageFromMultipeerNetworking; + } + + private void SetLocalStage(AnyARNetworkingInitializedArgs args) + { + var mockARNetworking = args.ARNetworking as _MockARNetworking; + if (mockARNetworking == null) + return; + + var player = SetLocalPlayerIfNeeded(); + if (player == null) + return; + + var oldARNetworking = _arNetworking; + if (oldARNetworking != null) + oldARNetworking.Deinitialized -= RemoveLocalStage; + + _arNetworking = mockARNetworking; + mockARNetworking.Deinitialized += RemoveLocalStage; + player.SetARNetworking(mockARNetworking); + } + + private MockPlayer SetLocalPlayerIfNeeded() + { + if (_localPlayer == null) + _localPlayer = CreatePlayer(null); + + return _localPlayer; + } + + private void RemoveLocalStage(ARSessionDeinitializedArgs args) + { + if (_arSession == null) + return; + + LocalPlayer.SetARSession(null); + + _arSessionIdentifierToPlayerName.Remove(_arSession.StageIdentifier); + _arSession = null; + } + + private void _RemoveLocalStageFromMultipeerNetworking(DeinitializedArgs args) + { + if (_networking == null) + return; + + LocalPlayer.SetMultipeerNetworking(null); + + _networkingIdentifierToPlayerName.Remove(_networking.StageIdentifier); + _networking = null; + } + + private void RemoveLocalStage(ARNetworkingDeinitializedArgs args) + { + if (_arNetworking == null) + return; + + LocalPlayer.SetARNetworking(null); + _arNetworking = null; + } + + public void InitializeForConfiguration(MockPlayConfiguration playConfiguration) + { + if (PlayConfiguration != null) + { + ARLog._Error("Virtual Studio was already initialized with a play configuration."); + return; + } + + PlayConfiguration = playConfiguration; + foreach (var profile in playConfiguration.ActiveProfiles) + { + if (!InitializeProfile(profile)) + { + ARLog._ErrorFormat + ( + "Failed trying to start session for profile {0}.", + profile.PlayerName + ); + } + } + } + + // Constructs the MockPlayer and its required of ARSession, MultipeerNetworking, + // and ARNetworking sessions for, as defined by the input MockArdkPlayerProfile. + private bool InitializeProfile(MockArdkPlayerProfile playerProfile) + { + if (GetPlayer(playerProfile.PlayerName) != null) + { + ARLog._ErrorFormat + ( + "A player with the name {0} has already been initialized.", + playerProfile.PlayerName + ); + return false; + } + + var stageIdentifier = Guid.NewGuid(); + var player = CreatePlayer(playerProfile); + + if (playerProfile.UsingNetwork) + { + // Only mock networkings are compatible with mock players + var networking = + _multipeerMediator.CreateNonLocalSession(stageIdentifier, playerProfile.RuntimeEnvironment); + + player.SetMultipeerNetworking(networking); + _networkingIdentifierToPlayerName.Add(stageIdentifier, player.Name); + } + + if (playerProfile.UsingAR) + { + var arSession = + _arSessionMediator.CreateNonLocalSession(stageIdentifier, playerProfile.RuntimeEnvironment); + + player.SetARSession(arSession); + _arSessionIdentifierToPlayerName.Add(stageIdentifier, player.Name); + } + + if (playerProfile.UsingARNetworking) + { + var arNetworking = _arNetworkingMediator.CreateNonLocalSession(stageIdentifier); + + player.SetARNetworking(arNetworking); + } + + return true; + } + + private MockPlayer CreatePlayer(MockArdkPlayerProfile playerProfile) + { + // Create player and add to map + var mockPlayer = new MockPlayer(this, playerProfile); + + var playerName = mockPlayer.Name; + _mockPlayers.Add(playerName, mockPlayer); + + return mockPlayer; + } + + public MockPlayer GetPlayer(string playerName) + { + MockPlayer player; + + if (_mockPlayers.TryGetValue(playerName, out player)) + return player; + + return null; + } + + public MockPlayer GetPlayer(Guid stageIdentifier) + { + string playerName; + MockPlayer player = null; + + var foundPlayerName = + _arSessionIdentifierToPlayerName.TryGetValue(stageIdentifier, out playerName) || + _networkingIdentifierToPlayerName.TryGetValue(stageIdentifier, out playerName); + + if (foundPlayerName) + _mockPlayers.TryGetValue(playerName, out player); + + return player; + } + + public MockPlayer GetPlayerWithPeer(IPeer peer) + { + var mockPeer = peer as _MockPeer; + if (mockPeer == null) + { + ARLog._Error("This method is only valid while running MultipeerNetworking in Mock mode."); + return null; + } + else + { + var peerStageIdentifier = mockPeer.StageIdentifier; + var networking = MultipeerMediator.GetSession(peerStageIdentifier); + + if (networking != null) + { + var playerName = _arSessionIdentifierToPlayerName[networking.StageIdentifier]; + return _mockPlayers[playerName]; + } + + return null; + } + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/VirtualStudio/_VirtualStudioManager.cs.meta b/Assets/ARDK/VirtualStudio/_VirtualStudioManager.cs.meta new file mode 100644 index 0000000..a71dadf --- /dev/null +++ b/Assets/ARDK/VirtualStudio/_VirtualStudioManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 61f3569e2604c4499be360acc1cf96da +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VpsCoverage.meta b/Assets/ARDK/VpsCoverage.meta new file mode 100644 index 0000000..a282b5d --- /dev/null +++ b/Assets/ARDK/VpsCoverage.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1528b9a29e5a04e1ab8c83ea85d01c9a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VpsCoverage/CoverageArea.cs b/Assets/ARDK/VpsCoverage/CoverageArea.cs new file mode 100644 index 0000000..303d73c --- /dev/null +++ b/Assets/ARDK/VpsCoverage/CoverageArea.cs @@ -0,0 +1,138 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Linq; + +using Niantic.ARDK.LocationService; +using Niantic.ARDK.VPSCoverage.GeoserviceMessages; + +using UnityEngine; + +namespace Niantic.ARDK.VPSCoverage +{ + /// An area where localization with VPS is possible. + [Serializable] + public struct CoverageArea + { + [SerializeField] + private string[] _localizationTargetIdentifiers; + /// Identifiers of all LocalizationTargets within the CoverageArea. + public string[] LocalizationTargetIdentifiers { get { return _localizationTargetIdentifiers; } } + + [SerializeField] + private LatLng[] _shape; + /// Polygon outlining the CoverageArea. + public LatLng[] Shape { get { return _shape; } } + + /// Centroid of the Shape polygon. + public LatLng Centroid { get; private set; } + + [SerializeField] + private Localizability _localizabilityQuality; + + /// The localizability quality gives information about the chances of a successful localization + /// in this CoverageArea. + public Localizability LocalizabilityQuality { get {return _localizabilityQuality;} } + + /// The localizability quality is split into CoverageAreas above a quality threshold marked as + /// PRODUCTION, and CoverageAreas that have a lower localizability quality marked as EXPERIMENTAL. + public enum Localizability + { + UNSET, + PRODUCTION, + EXPERIMENTAL + } + + internal CoverageArea(_CoverageAreasResponse.VpsCoverageArea location) + : this(location.vps_localization_target_id, location.shape.polygon.loop[0].vertex, location.localizability) + { + } + + internal CoverageArea(string[] localizationTargetIdentifiers, LatLng[] shape, string localizability) + { + _localizationTargetIdentifiers = localizationTargetIdentifiers; + _shape = shape; + Centroid = CalculateCentroid(_shape); + + Enum.TryParse(localizability, out _localizabilityQuality); + } + + // taken from https://stackoverflow.com/questions/6671183/calculate-the-center-point-of-multiple-latitude-longitude-coordinate-pairs + private static LatLng CalculateCentroid(params LatLng[] points) + { + if (points.Length == 1) + { + return points.Single(); + } + + double x = 0; + double y = 0; + double z = 0; + + foreach (LatLng point in points) + { + var latitude = point.Latitude * Math.PI / 180; + var longitude = point.Longitude * Math.PI / 180; + + x += Math.Cos(latitude) * Math.Cos(longitude); + y += Math.Cos(latitude) * Math.Sin(longitude); + z += Math.Sin(latitude); + } + + int total = points.Length; + + x = x / total; + y = y / total; + z = z / total; + + var centralLongitude = Math.Atan2(y, x); + var centralSquareRoot = Math.Sqrt(x * x + y * y); + var centralLatitude = Math.Atan2(z, centralSquareRoot); + + return new LatLng(centralLatitude * 180 / Math.PI, centralLongitude * 180 / Math.PI); + } + + // JSONUtility can not handle the nested array format of GeoJson and Newtonsoft will add an + // additional dependency. Manual built string works for now. + + /// Convert the CoverageArea information into a GeoJson string. + /// @returns GeoJson as string + public string ToGeoJson() + { + string geoJson = + "{" + + "\"type\": \"FeatureCollection\", \"features\": " + + "[{" + + "\"type\": \"Feature\",\"geometry\": " + + "{" + + "\"type\": \"Polygon\"," + "\"properties\": " + + "{" + + "\"location_type\": \"coverage_area\", " + + "\"localizability_quality\": \"" + _localizabilityQuality + "\", " + + "\"location_target_identifiers\": " + + "["; + for (int i = 0; i < _localizationTargetIdentifiers.Length; i++) + { + if (i != 0) + geoJson += ","; + geoJson += "\"" + _localizationTargetIdentifiers[i] + "\""; + } + geoJson += "]}," + + "\"coordinates\": " + + "[["; + for (int i = 0; i < Shape.Length; i++) + { + geoJson += "[" + Shape[i].Longitude + "," + Shape[i].Latitude + "],"; + } + geoJson += + "[" + Shape[0].Longitude + "," + Shape[0].Latitude + "]"; + geoJson += + "]]" + + "}" + + "}]" + + "}"; + + return geoJson; + } + } +} diff --git a/Assets/ARDK/VpsCoverage/CoverageArea.cs.meta b/Assets/ARDK/VpsCoverage/CoverageArea.cs.meta new file mode 100644 index 0000000..fe0dd8f --- /dev/null +++ b/Assets/ARDK/VpsCoverage/CoverageArea.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2cd4455d07b6e433ebfa859ddb14243a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VpsCoverage/CoverageClient.meta b/Assets/ARDK/VpsCoverage/CoverageClient.meta new file mode 100644 index 0000000..581f1f0 --- /dev/null +++ b/Assets/ARDK/VpsCoverage/CoverageClient.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9a58e8ca5263547a5ae6051f82f42862 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VpsCoverage/CoverageClient/CoverageClientFactory.cs b/Assets/ARDK/VpsCoverage/CoverageClient/CoverageClientFactory.cs new file mode 100644 index 0000000..2bff638 --- /dev/null +++ b/Assets/ARDK/VpsCoverage/CoverageClient/CoverageClientFactory.cs @@ -0,0 +1,101 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.ComponentModel; + +using Niantic.ARDK.VirtualStudio.VpsCoverage; + +namespace Niantic.ARDK.VPSCoverage +{ + /// Factory to create CoverageClient instances. + public static class CoverageClientFactory + { + /// Create an ICoverageLoader implementation appropriate for the current device. + /// + /// On a mobile device, the attempted order will be LiveDevice, Remote, and finally Mock. + /// In the Unity Editor, the attempted order will be Remote, then Mock. + /// + /// @returns The created loader, or throws if it was not possible to create a loader. + public static ICoverageClient Create() + { + return _Create(null); + } + + /// Create an ICoverageLoader with the specified RuntimeEnvironment. + /// + /// @param env + /// The env used to create the loader for. + /// @param mockResponses + /// A ScriptableObject containing the data that a Mock implementation of the ICoverageClient + /// will return. This is a required argument for using the mock client on a mobile + /// device. It is optional in the Unity Editor; the mock client will simply use the data + /// provided in the ARDK/VirtualStudio/VpsCoverage/VPS Coverage Responses.asset file. + /// + /// @returns The created loader, or null if it was not possible to create a loader. + public static ICoverageClient Create(RuntimeEnvironment env, VpsCoverageResponses mockResponses = null) + { + ICoverageClient result; + switch (env) + { + case RuntimeEnvironment.Default: + return Create(); + + case RuntimeEnvironment.LiveDevice: + result = new _NativeCoverageClient(); + break; + + case RuntimeEnvironment.Remote: + throw new NotSupportedException(); + + case RuntimeEnvironment.Mock: + result = new _MockCoverageClient(mockResponses); + break; + + default: + throw new InvalidEnumArgumentException(nameof(env), (int)env, env.GetType()); + } + + return result; + } + + private static readonly RuntimeEnvironment[] _defaultBestMatches = +#if (UNITY_IOS || UNITY_ANDROID) && !UNITY_EDITOR + new RuntimeEnvironment[] { RuntimeEnvironment.LiveDevice }; +#else + new RuntimeEnvironment[] { RuntimeEnvironment.Mock }; +#endif + + /// Tries to create an ICoverageLoader implementation of any of the given envs. + /// + /// @param envs + /// A collection of runtime environments used to create the session for. As not all platforms + /// support all environments, the code will try to create the session for the first + /// environment, then for the second and so on. If envs is null or empty, then the order used + /// is LiveDevice, Remote and finally Mock. + /// + /// @returns The created loader, or null if it was not possible to create a loader. + internal static ICoverageClient _Create(IEnumerable envs = null) + { + bool triedAtLeast1 = false; + + if (envs != null) + { + foreach (var env in envs) + { + var possibleResult = Create(env); + if (possibleResult != null) + return possibleResult; + + triedAtLeast1 = true; + } + } + + if (!triedAtLeast1) + return _Create(_defaultBestMatches); + + throw new NotSupportedException("None of the provided envs are supported by this build."); + } + + } +} diff --git a/Assets/ARDK/VpsCoverage/CoverageClient/CoverageClientFactory.cs.meta b/Assets/ARDK/VpsCoverage/CoverageClient/CoverageClientFactory.cs.meta new file mode 100644 index 0000000..ce3e12c --- /dev/null +++ b/Assets/ARDK/VpsCoverage/CoverageClient/CoverageClientFactory.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 90187e938bc394645a8b2b7870a6fc11 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VpsCoverage/CoverageClient/ICoverageClient.cs b/Assets/ARDK/VpsCoverage/CoverageClient/ICoverageClient.cs new file mode 100644 index 0000000..a7045c4 --- /dev/null +++ b/Assets/ARDK/VpsCoverage/CoverageClient/ICoverageClient.cs @@ -0,0 +1,47 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Threading.Tasks; + +using Niantic.ARDK.LocationService; + +namespace Niantic.ARDK.VPSCoverage +{ + /// Client to request CoverageAreas and LocalizationTargets. + public interface ICoverageClient + { + /// Request CoverageAreas at device location within a radius using the async await pattern. + /// @param queryLocation Center of query from device location. + /// @param queryRadius Radius for query between 0m and 500m. Negative radius will default to the maximum radius of 500m. + /// @returns Task with the received CoverageAreasResult as result. + Task RequestCoverageAreasAsync(LocationInfo queryLocation, int queryRadius); + + /// Request CoverageAreas at any location within a radius using the async await pattern. + /// @param queryLocation Center of query. + /// @param queryRadius Radius for query between 0m and 500m. Negative radius will default to the maximum radius of 500m. + /// @returns Task with the received CoverageAreasResult as result. + Task RequestCoverageAreasAsync(LatLng queryLocation, int queryRadius); + + /// Request LocalizationTargets for a set of identifiers using the async await pattern. + /// @param targetIdentifiers Set of unique identifiers of the requested targets. + /// @returns Task with the received LocalizationTargetsResult as result. + Task RequestLocalizationTargetsAsync(string[] targetIdentifiers); + + /// Request CoverageAreas at device location within a radius using the callback pattern. + /// @param queryLocation Center of query from device location. + /// @param queryRadius Radius for query between 0m and 500m. Negative radius will default to the maximum radius of 500m. + /// @param onAreasReceived Callback function to process the received CoverageAreasResult. + void RequestCoverageAreas(LocationInfo queryLocation, int queryRadius, Action onAreasReceived); + + /// Request CoverageAreas at device location within a radius using the callback pattern. + /// @param queryLocation Center of query. + /// @param queryRadius Radius for query between 0m and 500m. Negative radius will default to the maximum radius of 500m. + /// @param onAreasReceived Callback function to process the received CoverageAreasResult. + void RequestCoverageAreas(LatLng queryLocation, int queryRadius, Action onAreasReceived); + + /// Request LocalizationTargets for a set of identifiers using the callback pattern. + /// @param targetIdentifiers Set of unique identifiers of the requested targets. + /// @param onTargetsReceived Callback function to process the received LocalizationTargetsResult. + void RequestLocalizationTargets(string[] targetIdentifiers, Action onTargetsReceived); + } +} diff --git a/Assets/ARDK/VpsCoverage/CoverageClient/ICoverageClient.cs.meta b/Assets/ARDK/VpsCoverage/CoverageClient/ICoverageClient.cs.meta new file mode 100644 index 0000000..370ccc6 --- /dev/null +++ b/Assets/ARDK/VpsCoverage/CoverageClient/ICoverageClient.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cda31cedc9a0f43eea78ccd1f7cf8f09 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VpsCoverage/CoverageClient/ResponseStatus.cs b/Assets/ARDK/VpsCoverage/CoverageClient/ResponseStatus.cs new file mode 100644 index 0000000..bbabf2e --- /dev/null +++ b/Assets/ARDK/VpsCoverage/CoverageClient/ResponseStatus.cs @@ -0,0 +1,25 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +namespace Niantic.ARDK.VPSCoverage +{ + /// Status of a response from the VPS Coverage server. + public enum ResponseStatus + { + // From API + Unset, + Success, + InvalidRequest, + InternalError, + TooManyEntitiesRequested, + + // From UnityWebRequest.Result + ConnectionError, + ProtocolError, // all 4xx and 5xx => see Gateway + + // From Gateway + Forbidden = 403, + TooManyRequests = 429, + InternalGatewayError = 500 + + } +} diff --git a/Assets/ARDK/VpsCoverage/CoverageClient/ResponseStatus.cs.meta b/Assets/ARDK/VpsCoverage/CoverageClient/ResponseStatus.cs.meta new file mode 100644 index 0000000..4169545 --- /dev/null +++ b/Assets/ARDK/VpsCoverage/CoverageClient/ResponseStatus.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9d2c06cabb69b470a9330b453f5c7b8a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VpsCoverage/CoverageClient/_MockCoverageClient.cs b/Assets/ARDK/VpsCoverage/CoverageClient/_MockCoverageClient.cs new file mode 100644 index 0000000..f6ebcaa --- /dev/null +++ b/Assets/ARDK/VpsCoverage/CoverageClient/_MockCoverageClient.cs @@ -0,0 +1,81 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Threading.Tasks; + +using Niantic.ARDK.Utilities.Extensions; +using Niantic.ARDK.VirtualStudio.VpsCoverage; +using Niantic.ARDK.LocationService; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.Utilities.Logging; + +namespace Niantic.ARDK.VPSCoverage +{ + internal class _MockCoverageClient: ICoverageClient + { + private VpsCoverageResponses _responses; + + internal _MockCoverageClient(VpsCoverageResponses responses) + { + _FriendTypeAsserter.AssertCallerIs(typeof(CoverageClientFactory)); + + if (responses != null) + _responses = responses; + else + { +#if UNITY_EDITOR + var foundResponses = _AssetDatabaseExtension.FindAssets(); + if (foundResponses.Length == 0) + { + ARLog._Error("No instance of VpsCoverageResponses found in project to use for mock ICoverageClient."); + } + else + { + _responses = foundResponses[0]; + }; +#else + throw new ArgumentNullException(nameof(responses), "On a mobile device, a VpsCoverageResponses object must be provided when using a mock ICoverageClient."); +#endif + } + } + + public async Task RequestCoverageAreasAsync(LocationInfo queryLocation, int queryRadius) + { + return await RequestCoverageAreasAsync(new LatLng(queryLocation), queryRadius); + } + +#pragma warning disable 1998 + public async Task RequestCoverageAreasAsync(LatLng queryLocation, int queryRadius) +#pragma warning restore 1998 + { + var mockResponse = _responses.Coverage.ToResponse(); + return new CoverageAreasResult(mockResponse); + } + +#pragma warning disable 1998 + public async Task RequestLocalizationTargetsAsync(string[] targetIdentifiers) +#pragma warning restore 1998 + { + var mockResponse = _responses.LocalizationTargets.ToResponse(targetIdentifiers); + return new LocalizationTargetsResult(mockResponse); + } + + public async void RequestCoverageAreas(LocationInfo queryLocation, int queryRadius, Action onAreasReceived) + { + CoverageAreasResult result = await RequestCoverageAreasAsync(queryLocation, queryRadius); + onAreasReceived?.Invoke(result); + } + + public async void RequestCoverageAreas(LatLng queryLocation, int queryRadius, Action onAreasReceived) + { + CoverageAreasResult result = await RequestCoverageAreasAsync(queryLocation, queryRadius); + onAreasReceived?.Invoke(result); + } + + public async void RequestLocalizationTargets(string[] targetIdentifiers, Action onTargetsReceived) + { + LocalizationTargetsResult result = await RequestLocalizationTargetsAsync(targetIdentifiers); + onTargetsReceived?.Invoke(result); + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/VpsCoverage/CoverageClient/_MockCoverageClient.cs.meta b/Assets/ARDK/VpsCoverage/CoverageClient/_MockCoverageClient.cs.meta new file mode 100644 index 0000000..f2fdb9c --- /dev/null +++ b/Assets/ARDK/VpsCoverage/CoverageClient/_MockCoverageClient.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6c398877f276a47e8b70a949a9598e26 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VpsCoverage/CoverageClient/_NativeCoverageClient.cs b/Assets/ARDK/VpsCoverage/CoverageClient/_NativeCoverageClient.cs new file mode 100644 index 0000000..666fa71 --- /dev/null +++ b/Assets/ARDK/VpsCoverage/CoverageClient/_NativeCoverageClient.cs @@ -0,0 +1,123 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +using Niantic.ARDK.Configuration; +using Niantic.ARDK.Configuration.Internal; +using Niantic.ARDK.LocationService; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.VPSCoverage.GeoserviceMessages; + +using UnityEditor; + +using UnityEngine; + +using LocationInfo = Niantic.ARDK.LocationService.LocationInfo; +using LocationServiceStatus = UnityEngine.LocationServiceStatus; + + +namespace Niantic.ARDK.VPSCoverage +{ + internal class _NativeCoverageClient: ICoverageClient + { + private const string VpsCoverageEndpoint = "https://vps-coverage-api.nianticlabs.com/api/json/v1/"; + private const string CoverageAreasEndpoint = VpsCoverageEndpoint + "GET_VPS_COVERAGE"; + private const string LocalizationTargetsEndpoint = VpsCoverageEndpoint + "GET_VPS_LOCALIZATION_TARGETS"; + + internal _NativeCoverageClient() + { + _FriendTypeAsserter.AssertCallerIs(typeof(CoverageClientFactory)); + } + + public async Task RequestCoverageAreasAsync(LatLng queryLocation, int queryRadius) + { + _CoverageAreasRequest request; + + // Server side we use radius == 0 then use max radius, radius < 0 then set radius to 0. + // Client side we want a to use radius == 0 then radius = 0, radius < 0 then use max radius. + if (queryRadius == 0) + queryRadius = -1; + else if (queryRadius < 0) + queryRadius = 0; + + var metadata = ArdkGlobalConfig._Internal.GetCommonDataEnvelopeWithRequestIdAsStruct(); + var header = ArdkGlobalConfig._Internal.GetApiGatewayHeader(); + + if (Input.location.status == LocationServiceStatus.Running) + { + int distanceToQuery = (int)queryLocation.Distance(new LatLng(Input.location.lastData)); + request = new _CoverageAreasRequest(queryLocation, queryRadius, distanceToQuery, metadata); + } + else + { + request = new _CoverageAreasRequest(queryLocation, queryRadius, metadata); + } + + _HttpResponse<_CoverageAreasResponse> response = + await _HttpClient.SendPostAsync<_CoverageAreasRequest, _CoverageAreasResponse> + ( + CoverageAreasEndpoint, + request, + header + ); + + if (response.Status == ResponseStatus.Success) + response.Status = _ResponseStatusTranslator.FromString(response.Data.status); + + CoverageAreasResult result = new CoverageAreasResult(response); + + return result; + } + + public async Task RequestCoverageAreasAsync(LocationInfo queryLocation, int queryRadius) + { + return await RequestCoverageAreasAsync(new LatLng(queryLocation), queryRadius); + } + + public async Task RequestLocalizationTargetsAsync + ( + string[] targetIdentifiers + ) + { + var metadata = ArdkGlobalConfig._Internal.GetCommonDataEnvelopeWithRequestIdAsStruct(); + var header = ArdkGlobalConfig._Internal.GetApiGatewayHeader(); + + _LocalizationTargetsRequest request = new _LocalizationTargetsRequest(targetIdentifiers, metadata); + + _HttpResponse<_LocalizationTargetsResponse> response = + await _HttpClient.SendPostAsync<_LocalizationTargetsRequest, _LocalizationTargetsResponse> + ( + LocalizationTargetsEndpoint, + request, + header + ); + + if (response.Status == ResponseStatus.Success) + response.Status = _ResponseStatusTranslator.FromString(response.Data.status); + + LocalizationTargetsResult result = new LocalizationTargetsResult(response); + + return result; + } + + public async void RequestCoverageAreas(LocationInfo queryLocation, int queryRadius, Action onAreasReceived) + { + CoverageAreasResult result = await RequestCoverageAreasAsync(queryLocation, queryRadius); + onAreasReceived?.Invoke(result); + } + + public async void RequestCoverageAreas(LatLng queryLocation, int queryRadius, Action onAreasReceived) + { + CoverageAreasResult result = await RequestCoverageAreasAsync(queryLocation, queryRadius); + onAreasReceived?.Invoke(result); + } + + public async void RequestLocalizationTargets(string[] targetIdentifiers, Action onTargetsReceived) + { + LocalizationTargetsResult result = await RequestLocalizationTargetsAsync(targetIdentifiers); + onTargetsReceived?.Invoke(result); + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/VpsCoverage/CoverageClient/_NativeCoverageClient.cs.meta b/Assets/ARDK/VpsCoverage/CoverageClient/_NativeCoverageClient.cs.meta new file mode 100644 index 0000000..ed241e1 --- /dev/null +++ b/Assets/ARDK/VpsCoverage/CoverageClient/_NativeCoverageClient.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 29dc754f7489f485088ca396cdacfca9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VpsCoverage/GeoserviceMessages.meta b/Assets/ARDK/VpsCoverage/GeoserviceMessages.meta new file mode 100644 index 0000000..bd02078 --- /dev/null +++ b/Assets/ARDK/VpsCoverage/GeoserviceMessages.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 2c6d3aea12184cbb913f8b496769bb14 +timeCreated: 1646404589 \ No newline at end of file diff --git a/Assets/ARDK/VpsCoverage/GeoserviceMessages/_CoverageAreasRequest.cs b/Assets/ARDK/VpsCoverage/GeoserviceMessages/_CoverageAreasRequest.cs new file mode 100644 index 0000000..949889b --- /dev/null +++ b/Assets/ARDK/VpsCoverage/GeoserviceMessages/_CoverageAreasRequest.cs @@ -0,0 +1,40 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.Configuration.Internal; +using Niantic.ARDK.LocationService; + +using UnityEngine; + +namespace Niantic.ARDK.VPSCoverage.GeoserviceMessages +{ + [Serializable] + internal class _CoverageAreasRequest + { + [SerializeField] + private LatLng query_location; + + [SerializeField] + private int query_radius_in_meters; + + [SerializeField] + private int user_distance_to_query_location_in_meters; + + [SerializeField] + private ARCommonMetadataStruct ar_common_metadata; + + public _CoverageAreasRequest(LatLng queryLocation, int queryRadiusInMeters, int userDistanceToQueryLocationInMeters, ARCommonMetadataStruct arCommonMetadata): + this(queryLocation, queryRadiusInMeters, arCommonMetadata) + { + user_distance_to_query_location_in_meters = userDistanceToQueryLocationInMeters; + } + + public _CoverageAreasRequest(LatLng queryLocation, int queryRadiusInMeters, ARCommonMetadataStruct arCommonMetadata) + { + query_location = queryLocation; + query_radius_in_meters = queryRadiusInMeters; + ar_common_metadata = arCommonMetadata; + } + } +} diff --git a/Assets/ARDK/VpsCoverage/GeoserviceMessages/_CoverageAreasRequest.cs.meta b/Assets/ARDK/VpsCoverage/GeoserviceMessages/_CoverageAreasRequest.cs.meta new file mode 100644 index 0000000..9b60607 --- /dev/null +++ b/Assets/ARDK/VpsCoverage/GeoserviceMessages/_CoverageAreasRequest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4238bc8b782464abd8660de0689f5338 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VpsCoverage/GeoserviceMessages/_CoverageAreasResponse.cs b/Assets/ARDK/VpsCoverage/GeoserviceMessages/_CoverageAreasResponse.cs new file mode 100644 index 0000000..d12bc56 --- /dev/null +++ b/Assets/ARDK/VpsCoverage/GeoserviceMessages/_CoverageAreasResponse.cs @@ -0,0 +1,77 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; + +using Niantic.ARDK.LocationService; + +namespace Niantic.ARDK.VPSCoverage.GeoserviceMessages +{ + [Serializable] + internal class _CoverageAreasResponse + { + public VpsCoverageArea[] vps_coverage_area; + public string status; + public string error_message; + + public _CoverageAreasResponse(VpsCoverageArea[] vpsCoverageArea, string status, string errorMessage) + { + vps_coverage_area = vpsCoverageArea; + this.status = status; + error_message = errorMessage; + } + + [Serializable] + public struct VpsCoverageArea + { + public Shape shape; + public string[] vps_localization_target_id; + public string localizability; + + public VpsCoverageArea(Shape shape, string[] vpsLocalizationTargetId, string localizability) + { + vps_localization_target_id = vpsLocalizationTargetId; + this.shape = shape; + this.localizability = localizability; + } + } + + [Serializable] + public struct Shape + { + public Polygon polygon; + + public Shape(Polygon polygon) + { + this.polygon = polygon; + } + + public Shape(LatLng[] points) + { + var loop = new Loop(points); + polygon = new Polygon(new [] { loop }); + } + } + + [Serializable] + public struct Polygon + { + public Loop[] loop; + + public Polygon(Loop[] loop) + { + this.loop = loop; + } + } + + [Serializable] + public struct Loop + { + public LatLng[] vertex; + + public Loop(LatLng[] vertex) + { + this.vertex = vertex; + } + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/VpsCoverage/GeoserviceMessages/_CoverageAreasResponse.cs.meta b/Assets/ARDK/VpsCoverage/GeoserviceMessages/_CoverageAreasResponse.cs.meta new file mode 100644 index 0000000..dd23d0a --- /dev/null +++ b/Assets/ARDK/VpsCoverage/GeoserviceMessages/_CoverageAreasResponse.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ae30fa5ddc6734a0c94f832b602b7c38 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VpsCoverage/GeoserviceMessages/_LocalizationTargetsRequest.cs b/Assets/ARDK/VpsCoverage/GeoserviceMessages/_LocalizationTargetsRequest.cs new file mode 100644 index 0000000..e5c40ed --- /dev/null +++ b/Assets/ARDK/VpsCoverage/GeoserviceMessages/_LocalizationTargetsRequest.cs @@ -0,0 +1,36 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.IO; + +using Niantic.ARDK.Configuration.Internal; + +using UnityEngine; + +namespace Niantic.ARDK.VPSCoverage.GeoserviceMessages +{ + [Serializable] + internal class _LocalizationTargetsRequest + { + [SerializeField] + private string[] query_id; + + [SerializeField] + private ARCommonMetadataStruct ar_common_metadata; + + public _LocalizationTargetsRequest(string[] queryId, ARCommonMetadataStruct arCommonMetadata) + { + query_id = queryId; + ar_common_metadata = arCommonMetadata; + } + + public static string ReadFromFile() + { + string path = Path.Combine(Application.dataPath, "../../ARDK/Assets/ARDK/VpsCoverage/MockData/VpsCoverageTargets/VpsCoverageTargetsRequest.json"); + string json = File.ReadAllText(path); + + return json; + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/VpsCoverage/GeoserviceMessages/_LocalizationTargetsRequest.cs.meta b/Assets/ARDK/VpsCoverage/GeoserviceMessages/_LocalizationTargetsRequest.cs.meta new file mode 100644 index 0000000..02780cd --- /dev/null +++ b/Assets/ARDK/VpsCoverage/GeoserviceMessages/_LocalizationTargetsRequest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e9d41209fe2d148188217d0d64fbdda0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VpsCoverage/GeoserviceMessages/_LocalizationTargetsResponse.cs b/Assets/ARDK/VpsCoverage/GeoserviceMessages/_LocalizationTargetsResponse.cs new file mode 100644 index 0000000..ac46597 --- /dev/null +++ b/Assets/ARDK/VpsCoverage/GeoserviceMessages/_LocalizationTargetsResponse.cs @@ -0,0 +1,55 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; + +using Niantic.ARDK.LocationService; + +namespace Niantic.ARDK.VPSCoverage.GeoserviceMessages +{ + [Serializable] + internal class _LocalizationTargetsResponse + { + public VpsLocalizationTarget[] vps_localization_target; + public string status; + public string error_message; + + public _LocalizationTargetsResponse + ( + VpsLocalizationTarget[] vpsLocalizationTarget, + string status, + string errorMessage + ) + { + vps_localization_target = vpsLocalizationTarget; + this.status = status; + error_message = errorMessage; + } + + [Serializable] + public struct VpsLocalizationTarget + { + public Shape shape; + public string id; + public string name; + public string image_url; + + public VpsLocalizationTarget(Shape shape, string id, string name, string imageURL) + { + this.shape = shape; + this.id = id; + this.name = name; + image_url = imageURL; + } + } + + [Serializable] + public struct Shape + { + public LatLng point; + + public Shape(LatLng point) + { + this.point = point; + } + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/VpsCoverage/GeoserviceMessages/_LocalizationTargetsResponse.cs.meta b/Assets/ARDK/VpsCoverage/GeoserviceMessages/_LocalizationTargetsResponse.cs.meta new file mode 100644 index 0000000..28ce4a1 --- /dev/null +++ b/Assets/ARDK/VpsCoverage/GeoserviceMessages/_LocalizationTargetsResponse.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f6f2dbb150eee4b79b2df08fe88d5bab +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VpsCoverage/GeoserviceMessages/_ResponseStatusTranslator.cs b/Assets/ARDK/VpsCoverage/GeoserviceMessages/_ResponseStatusTranslator.cs new file mode 100644 index 0000000..ae7c6ca --- /dev/null +++ b/Assets/ARDK/VpsCoverage/GeoserviceMessages/_ResponseStatusTranslator.cs @@ -0,0 +1,38 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Globalization; + +using UnityEngine; +using UnityEngine.Networking; + +namespace Niantic.ARDK.VPSCoverage.GeoserviceMessages +{ + internal static class _ResponseStatusTranslator + { + public static ResponseStatus FromString(string status) + { + ResponseStatus result; + if (Enum.TryParse(status, out result)) + return result; + + status = status.ToLower().Replace("_", " "); + TextInfo info = CultureInfo.CurrentCulture.TextInfo; + status = info.ToTitleCase(status).Replace(" ", string.Empty); + Enum.TryParse(status, out result); + return result; + } + + public static ResponseStatus FromHttpStatus(UnityWebRequest.Result httpStatus, long errorCode) + { + Enum.TryParse(httpStatus.ToString(), out ResponseStatus responseStatus); + + if (responseStatus == ResponseStatus.ProtocolError) + { + Enum.TryParse(errorCode.ToString(), out responseStatus); + } + + return responseStatus; + } + } +} \ No newline at end of file diff --git a/Assets/ARDK/VpsCoverage/GeoserviceMessages/_ResponseStatusTranslator.cs.meta b/Assets/ARDK/VpsCoverage/GeoserviceMessages/_ResponseStatusTranslator.cs.meta new file mode 100644 index 0000000..b48dd93 --- /dev/null +++ b/Assets/ARDK/VpsCoverage/GeoserviceMessages/_ResponseStatusTranslator.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 0aac918058494ad6bf7ec7b9726c5772 +timeCreated: 1646407045 \ No newline at end of file diff --git a/Assets/ARDK/VpsCoverage/LocalizationTarget.cs b/Assets/ARDK/VpsCoverage/LocalizationTarget.cs new file mode 100644 index 0000000..33dfd95 --- /dev/null +++ b/Assets/ARDK/VpsCoverage/LocalizationTarget.cs @@ -0,0 +1,126 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Threading.Tasks; + +using Niantic.ARDK.LocationService; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.VPSCoverage.GeoserviceMessages; + +using UnityEngine; +using UnityEngine.UI; + +namespace Niantic.ARDK.VPSCoverage +{ + /// A real world target for localization using VPS. + [Serializable] + public struct LocalizationTarget + { + [SerializeField] + private string _identifier; + /// Unique identifier of the LocalizationTarget. + public string Identifier { get { return _identifier; } } + + [SerializeField] + private string _name; + /// Name of the LocalizationTarget. + public string Name { get { return _name; } } + + [SerializeField] + private LatLng _center; + /// Geolocation of the LocalizationTarget. + public LatLng Center { get { return _center; } } + + [SerializeField] + private string _imageURL; + /// Url where hint image is stored. + public string ImageURL { get { return _imageURL; } } + + internal LocalizationTarget(_LocalizationTargetsResponse.VpsLocalizationTarget vpsLocalizationTarget) + : this(vpsLocalizationTarget.id, vpsLocalizationTarget.name, vpsLocalizationTarget.image_url, vpsLocalizationTarget.shape.point) + { + } + + internal LocalizationTarget(string identifier, string name, string imageUrl, LatLng center) + { + _identifier = identifier; + _name = name; + _imageURL = imageUrl; + _center = center; + } + + /// Downloads the image from the provided url as a texture, using the async await pattern. + /// @param onImageReceived Callback for downloaded image as texture. When download fails, + /// texture is returned as null. + public async Task DownloadImageAsync() + { + Texture image = await _HttpClient.DownloadImageAsync(_imageURL); + return image; + } + + /// Downloads the image from the provided url as a texture, using the callback pattern. + /// @param onImageReceived Callback for downloaded image as texture. When download fails, + /// texture is returned as null. + public async void DownloadImage(Action onImageDownloaded) + { + Texture image = await _HttpClient.DownloadImageAsync(_imageURL); + onImageDownloaded?.Invoke(image); + } + + /// Downloads the image from the provided url as a texture cropped to a fixed size, using the + /// async await pattern. + /// The source image is first resampled so the image is fitting for the limiting dimension, then + /// it gets cropped to the fixed size. + /// @param width Fixed width of cropped image + /// @param height Fixed height of cropped image + /// @param onImageReceived Callback for downloaded image as texture. When download fails, + /// texture is returned as null. + public async Task DownloadImageAsync(int width, int height) + { + Texture image = await _HttpClient.DownloadImageAsync(_imageURL + "=w" + width + "-h" + height + "-c"); + return image; + } + + /// Downloads the image from the provided url as a texture cropped to a fixed size, using the + /// callback pattern. + /// The source image is first resampled so the image is fitting for the limiting dimension, then + /// it gets cropped to the fixed size. + /// @param width Fixed width of cropped image + /// @param height Fixed height of cropped image + /// @param onImageReceived Callback for downloaded image as texture. When download fails, + /// texture is returned as null. + public async void DownloadImage(int width, int height, Action onImageDownloaded) + { + Texture image = await _HttpClient.DownloadImageAsync(_imageURL + "=w" + width + "-h" + height + "-c"); + onImageDownloaded?.Invoke(image); + } + + // JSONUtility can not handle the nested array format of GeoJson and Newtonsoft will add an + // additional dependency. Manual built string works for now. + public string ToGeoJson() + { + string geoJson = + "{" + + "\"type\": \"FeatureCollection\", \"features\": " + + "[{" + + "\"type\": \"Feature\",\"geometry\": " + + "{" + + "\"type\": \"Point\"," + "\"properties\": " + + "{" + + "\"location_type\": \"localization_target\", " + + "\"location_image\": \"" + ImageURL + "\", " + + "\"location_target_identifier\": \"" + Identifier + "\", " + + "\"location_name\": \"" + Name + "\" " + + "}," + + "\"coordinates\": " + + "[" + + Center.Longitude + "," + Center.Latitude + + "]" + + "}" + + "}]" + + "}"; + + return geoJson; + } + } +} diff --git a/Assets/ARDK/VpsCoverage/LocalizationTarget.cs.meta b/Assets/ARDK/VpsCoverage/LocalizationTarget.cs.meta new file mode 100644 index 0000000..28e18bf --- /dev/null +++ b/Assets/ARDK/VpsCoverage/LocalizationTarget.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 51ee9aa06602d4922bb116dc9c7f3274 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VpsCoverage/Results.meta b/Assets/ARDK/VpsCoverage/Results.meta new file mode 100644 index 0000000..b384ff4 --- /dev/null +++ b/Assets/ARDK/VpsCoverage/Results.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f46f2f26ba2e445bd900a4b136f2c991 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VpsCoverage/Results/CoverageAreasResult.cs b/Assets/ARDK/VpsCoverage/Results/CoverageAreasResult.cs new file mode 100644 index 0000000..4655f24 --- /dev/null +++ b/Assets/ARDK/VpsCoverage/Results/CoverageAreasResult.cs @@ -0,0 +1,39 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System; +using System.Linq; + +using Niantic.ARDK.Utilities; +using Niantic.ARDK.VPSCoverage.GeoserviceMessages; + +namespace Niantic.ARDK.VPSCoverage +{ + /// Received result from server request for CoverageAreas. + public class CoverageAreasResult + { + /// Response status of server request. + public ResponseStatus Status { get; } + + /// Found CoverageAreas found for the request. + public CoverageArea[] Areas { get; } + + internal CoverageAreasResult(_CoverageAreasResponse response) + { + Status = _ResponseStatusTranslator.FromString(response.status); + Areas = response.vps_coverage_area.Select(t => new CoverageArea(t)).ToArray(); + } + + internal CoverageAreasResult(_HttpResponse<_CoverageAreasResponse> response) + { + Status = response.Status; + + if (Status == ResponseStatus.Success) + { + if (response.Data.vps_coverage_area != null) + Areas = response.Data.vps_coverage_area.Select(t => new CoverageArea(t)).ToArray(); + else + Areas = Array.Empty(); + } + } + } +} diff --git a/Assets/ARDK/VpsCoverage/Results/CoverageAreasResult.cs.meta b/Assets/ARDK/VpsCoverage/Results/CoverageAreasResult.cs.meta new file mode 100644 index 0000000..50612d0 --- /dev/null +++ b/Assets/ARDK/VpsCoverage/Results/CoverageAreasResult.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d1547353e585c4c0397ed6c4de83e265 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/VpsCoverage/Results/LocalizationTargetsResult.cs b/Assets/ARDK/VpsCoverage/Results/LocalizationTargetsResult.cs new file mode 100644 index 0000000..1888753 --- /dev/null +++ b/Assets/ARDK/VpsCoverage/Results/LocalizationTargetsResult.cs @@ -0,0 +1,50 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. + +using System.Collections.Generic; +using Niantic.ARDK.Utilities; +using Niantic.ARDK.VPSCoverage.GeoserviceMessages; + +namespace Niantic.ARDK.VPSCoverage +{ + /// Received result from server request for LocalizationTargets. + public class LocalizationTargetsResult + { + /// Response status of server request. + public ResponseStatus Status { get; } + + /// Found LocalizationTargets found for the request as a dictionary with their identifier as keys. + public IReadOnlyDictionary ActivationTargets { get; } + + internal LocalizationTargetsResult(_LocalizationTargetsResponse response) + { + Status = _ResponseStatusTranslator.FromString(response.status); + var activationTargets = new Dictionary(); + foreach (var target in response.vps_localization_target) + { + activationTargets.Add(target.id, new LocalizationTarget(target)); + } + + ActivationTargets = activationTargets; + } + + internal LocalizationTargetsResult(_HttpResponse<_LocalizationTargetsResponse> response) + { + Status = response.Status; + + if (Status == ResponseStatus.Success) + { + var activationTargets = new Dictionary(); + if (response.Data.vps_localization_target != null) + { + activationTargets = new Dictionary(); + foreach (var target in response.Data.vps_localization_target) + { + activationTargets.Add(target.id, new LocalizationTarget(target)); + } + } + + ActivationTargets = activationTargets; + } + } + } +} diff --git a/Assets/ARDK/VpsCoverage/Results/LocalizationTargetsResult.cs.meta b/Assets/ARDK/VpsCoverage/Results/LocalizationTargetsResult.cs.meta new file mode 100644 index 0000000..b1f96a7 --- /dev/null +++ b/Assets/ARDK/VpsCoverage/Results/LocalizationTargetsResult.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a33ced939429c4bbaa752c490802ac59 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/csc.rsp.DISABLED b/Assets/ARDK/csc.rsp.DISABLED new file mode 100644 index 0000000..ef30afa --- /dev/null +++ b/Assets/ARDK/csc.rsp.DISABLED @@ -0,0 +1 @@ +-define:IN_ROSETTA \ No newline at end of file diff --git a/Assets/ARDK/csc.rsp.DISABLED.meta b/Assets/ARDK/csc.rsp.DISABLED.meta new file mode 100644 index 0000000..9ecc9ce --- /dev/null +++ b/Assets/ARDK/csc.rsp.DISABLED.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: dd832b13ddc8f42e8ae288ad6a7b05a0 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ARDK/mcs.rsp.DISABLED b/Assets/ARDK/mcs.rsp.DISABLED new file mode 100644 index 0000000..ef30afa --- /dev/null +++ b/Assets/ARDK/mcs.rsp.DISABLED @@ -0,0 +1 @@ +-define:IN_ROSETTA \ No newline at end of file diff --git a/Assets/ARDK/mcs.rsp.DISABLED.meta b/Assets/ARDK/mcs.rsp.DISABLED.meta new file mode 100644 index 0000000..6e2778d --- /dev/null +++ b/Assets/ARDK/mcs.rsp.DISABLED.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 5e7f3fcb906a941809fe0b0706de3f38 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Adaptive Performance.meta b/Assets/Adaptive Performance.meta new file mode 100644 index 0000000..24067a7 --- /dev/null +++ b/Assets/Adaptive Performance.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1f0a44556690697459ec689a2ad7424b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Adaptive Performance/AdaptivePerformanceGeneralSettings.asset b/Assets/Adaptive Performance/AdaptivePerformanceGeneralSettings.asset new file mode 100644 index 0000000..95cc1d1 --- /dev/null +++ b/Assets/Adaptive Performance/AdaptivePerformanceGeneralSettings.asset @@ -0,0 +1,46 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &-1982227178052435319 +MonoBehaviour: + m_ObjectHideFlags: 2 + 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: 179fc3111e144bc4688dca4038b3265d, type: 3} + m_Name: Android Settings + m_EditorClassIdentifier: + m_LoaderManagerInstance: {fileID: 5581875199608903843} + m_InitManagerOnStart: 0 +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 2 + 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: cb0ece14d1f711a4fb9325ca819dee95, type: 3} + m_Name: AdaptivePerformanceGeneralSettings + m_EditorClassIdentifier: + Keys: 07000000 + Values: + - {fileID: -1982227178052435319} +--- !u!114 &5581875199608903843 +MonoBehaviour: + m_ObjectHideFlags: 2 + 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: 536372c49e1ca914d822849d36de938c, type: 3} + m_Name: Android Providers + m_EditorClassIdentifier: + m_AutomaticLoading: 0 + m_AutomaticRunning: 0 + m_Loaders: [] diff --git a/Assets/Adaptive Performance/AdaptivePerformanceGeneralSettings.asset.meta b/Assets/Adaptive Performance/AdaptivePerformanceGeneralSettings.asset.meta new file mode 100644 index 0000000..2d10369 --- /dev/null +++ b/Assets/Adaptive Performance/AdaptivePerformanceGeneralSettings.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6f70b1763ea9d4749a5714274f31dcd2 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Adaptive Performance/Settings.meta b/Assets/Adaptive Performance/Settings.meta new file mode 100644 index 0000000..324ed5a --- /dev/null +++ b/Assets/Adaptive Performance/Settings.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 65f757478287e754e9c3b15dce247e6a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Adaptive Performance/Settings/Simulator Provider Settings.asset b/Assets/Adaptive Performance/Settings/Simulator Provider Settings.asset new file mode 100644 index 0000000..980ae26 --- /dev/null +++ b/Assets/Adaptive Performance/Settings/Simulator Provider Settings.asset @@ -0,0 +1,261 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 2 + 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: b592865877cb54284a5d1d88aec9cfbb, type: 3} + m_Name: Simulator Provider Settings + m_EditorClassIdentifier: + m_Logging: 1 + m_AutomaticPerformanceModeEnabled: 1 + m_EnableBoostOnStartup: 1 + m_StatsLoggingFrequencyInFrames: 50 + m_IndexerSettings: + m_Active: 1 + m_ThermalActionDelay: 10 + m_PerformanceActionDelay: 4 + m_ScalerSettings: + m_AdaptiveFramerate: + m_Name: Adaptive Framerate + m_Enabled: 0 + m_Scale: 1 + m_VisualImpact: 2 + m_Target: 7 + m_MaxLevel: 45 + m_MinBound: 15 + m_MaxBound: 60 + m_AdaptiveResolution: + m_Name: Adaptive Resolution + m_Enabled: 0 + m_Scale: 1 + m_VisualImpact: 0 + m_Target: 6 + m_MaxLevel: 9 + m_MinBound: 0.5 + m_MaxBound: 1 + m_AdaptiveBatching: + m_Name: Adaptive Batching + m_Enabled: 0 + m_Scale: 1 + m_VisualImpact: 1 + m_Target: 1 + m_MaxLevel: 1 + m_MinBound: 0 + m_MaxBound: 1 + m_AdaptiveLOD: + m_Name: Adaptive LOD + m_Enabled: 0 + m_Scale: 1 + m_VisualImpact: 2 + m_Target: 2 + m_MaxLevel: 3 + m_MinBound: 0.4 + m_MaxBound: 1 + m_AdaptiveLut: + m_Name: Adaptive Lut + m_Enabled: 0 + m_Scale: 1 + m_VisualImpact: 1 + m_Target: 3 + m_MaxLevel: 1 + m_MinBound: 0 + m_MaxBound: 1 + m_AdaptiveMSAA: + m_Name: Adaptive MSAA + m_Enabled: 0 + m_Scale: 1 + m_VisualImpact: 1 + m_Target: 6 + m_MaxLevel: 2 + m_MinBound: 0 + m_MaxBound: 1 + m_AdaptiveShadowCascade: + m_Name: Adaptive Shadow Cascade + m_Enabled: 0 + m_Scale: 1 + m_VisualImpact: 1 + m_Target: 3 + m_MaxLevel: 2 + m_MinBound: 0 + m_MaxBound: 1 + m_AdaptiveShadowDistance: + m_Name: Adaptive Shadow Distance + m_Enabled: 0 + m_Scale: 1 + m_VisualImpact: 0 + m_Target: 2 + m_MaxLevel: 3 + m_MinBound: 0.15 + m_MaxBound: 1 + m_AdaptiveShadowmapResolution: + m_Name: Adaptive Shadowmap Resolution + m_Enabled: 0 + m_Scale: 1 + m_VisualImpact: 0 + m_Target: 2 + m_MaxLevel: 3 + m_MinBound: 0.15 + m_MaxBound: 1 + m_AdaptiveShadowQuality: + m_Name: Adaptive Shadow Quality + m_Enabled: 0 + m_Scale: 1 + m_VisualImpact: 2 + m_Target: 3 + m_MaxLevel: 3 + m_MinBound: 0 + m_MaxBound: 1 + m_AdaptiveSorting: + m_Name: Adaptive Sorting + m_Enabled: 0 + m_Scale: 1 + m_VisualImpact: 1 + m_Target: 1 + m_MaxLevel: 1 + m_MinBound: 0 + m_MaxBound: 1 + m_AdaptiveTransparency: + m_Name: Adaptive Transparency + m_Enabled: 0 + m_Scale: 1 + m_VisualImpact: 2 + m_Target: 2 + m_MaxLevel: 1 + m_MinBound: 0 + m_MaxBound: 1 + m_AdaptiveViewDistance: + m_Name: Adaptive View Distance + m_Enabled: 0 + m_Scale: 1 + m_VisualImpact: 2 + m_Target: 2 + m_MaxLevel: 40 + m_MinBound: 50 + m_MaxBound: 1000 + m_scalerProfileList: + - m_AdaptiveFramerate: + m_Name: Adaptive Framerate + m_Enabled: 0 + m_Scale: 1 + m_VisualImpact: 2 + m_Target: 7 + m_MaxLevel: 45 + m_MinBound: 15 + m_MaxBound: 60 + m_AdaptiveResolution: + m_Name: Adaptive Resolution + m_Enabled: 0 + m_Scale: 1 + m_VisualImpact: 0 + m_Target: 6 + m_MaxLevel: 9 + m_MinBound: 0.5 + m_MaxBound: 1 + m_AdaptiveBatching: + m_Name: Adaptive Batching + m_Enabled: 0 + m_Scale: 1 + m_VisualImpact: 1 + m_Target: 1 + m_MaxLevel: 1 + m_MinBound: 0 + m_MaxBound: 1 + m_AdaptiveLOD: + m_Name: Adaptive LOD + m_Enabled: 0 + m_Scale: 1 + m_VisualImpact: 2 + m_Target: 2 + m_MaxLevel: 3 + m_MinBound: 0.4 + m_MaxBound: 1 + m_AdaptiveLut: + m_Name: Adaptive Lut + m_Enabled: 0 + m_Scale: 1 + m_VisualImpact: 1 + m_Target: 3 + m_MaxLevel: 1 + m_MinBound: 0 + m_MaxBound: 1 + m_AdaptiveMSAA: + m_Name: Adaptive MSAA + m_Enabled: 0 + m_Scale: 1 + m_VisualImpact: 1 + m_Target: 6 + m_MaxLevel: 2 + m_MinBound: 0 + m_MaxBound: 1 + m_AdaptiveShadowCascade: + m_Name: Adaptive Shadow Cascade + m_Enabled: 0 + m_Scale: 1 + m_VisualImpact: 1 + m_Target: 3 + m_MaxLevel: 2 + m_MinBound: 0 + m_MaxBound: 1 + m_AdaptiveShadowDistance: + m_Name: Adaptive Shadow Distance + m_Enabled: 0 + m_Scale: 1 + m_VisualImpact: 0 + m_Target: 2 + m_MaxLevel: 3 + m_MinBound: 0.15 + m_MaxBound: 1 + m_AdaptiveShadowmapResolution: + m_Name: Adaptive Shadowmap Resolution + m_Enabled: 0 + m_Scale: 1 + m_VisualImpact: 0 + m_Target: 2 + m_MaxLevel: 3 + m_MinBound: 0.15 + m_MaxBound: 1 + m_AdaptiveShadowQuality: + m_Name: Adaptive Shadow Quality + m_Enabled: 0 + m_Scale: 1 + m_VisualImpact: 2 + m_Target: 3 + m_MaxLevel: 3 + m_MinBound: 0 + m_MaxBound: 1 + m_AdaptiveSorting: + m_Name: Adaptive Sorting + m_Enabled: 0 + m_Scale: 1 + m_VisualImpact: 1 + m_Target: 1 + m_MaxLevel: 1 + m_MinBound: 0 + m_MaxBound: 1 + m_AdaptiveTransparency: + m_Name: Adaptive Transparency + m_Enabled: 0 + m_Scale: 1 + m_VisualImpact: 2 + m_Target: 2 + m_MaxLevel: 1 + m_MinBound: 0 + m_MaxBound: 1 + m_AdaptiveViewDistance: + m_Name: Adaptive View Distance + m_Enabled: 0 + m_Scale: 1 + m_VisualImpact: 2 + m_Target: 2 + m_MaxLevel: 40 + m_MinBound: 50 + m_MaxBound: 1000 + m_Name: Default Scaler Profile + m_DefaultScalerProfilerIndex: 0 + k_AssetVersion: 2 diff --git a/Assets/Adaptive Performance/Settings/Simulator Provider Settings.asset.meta b/Assets/Adaptive Performance/Settings/Simulator Provider Settings.asset.meta new file mode 100644 index 0000000..03b9df8 --- /dev/null +++ b/Assets/Adaptive Performance/Settings/Simulator Provider Settings.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9f408d13013cdc6418ca440c6ce0dd7e +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Dynamic_UI.cs b/Assets/Dynamic_UI.cs new file mode 100644 index 0000000..909a02c --- /dev/null +++ b/Assets/Dynamic_UI.cs @@ -0,0 +1,92 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Networking; +using TMPro; + +[System.Serializable] +public class POI +{ + public string name; + public float[] coordinates; +} + + +[System.Serializable] +public class POIS +{ + //employees is case sensitive and must match the string "employees" in the JSON. + public POI[] pois; +} +public class Dynamic_UI : MonoBehaviour +{ + + + [SerializeField] private TextMeshProUGUI text; + [SerializeField] private GameObject obj; + + private POI[] pois; + private bool fechtedpoi = false; + private bool buildodui = false; + void Start() + { + StartCoroutine(GetRequest("https://pastebin.com/raw/fp0dVQnw")); + + } + + void Update() + { + if (fechtedpoi) + { + text.text = ""; + if (fechtedpoi) + { + // just update disctance here reodering possible? + } + else + { + for (int i = 0; i < pois.Length; i++) + { + string name = pois[i].name; + float[] coordinates = pois[i].coordinates; + } + } + } + else + { + text.text = "not fetched yet"; + } + } + + // Update is called once per frame + IEnumerator GetRequest(string uri) + { + using (UnityWebRequest webRequest = UnityWebRequest.Get(uri)) + { + // Request and wait for the desired page. + yield return webRequest.SendWebRequest(); + + string[] pages = uri.Split('/'); + int page = pages.Length - 1; + + switch (webRequest.result) + { + case UnityWebRequest.Result.ConnectionError: + case UnityWebRequest.Result.DataProcessingError: + Debug.LogError(pages[page] + ": Error: " + webRequest.error); + break; + case UnityWebRequest.Result.ProtocolError: + Debug.LogError(pages[page] + ": HTTP Error: " + webRequest.error); + break; + case UnityWebRequest.Result.Success: + Debug.Log(pages[page] + ":\nReceived: " + webRequest.downloadHandler.text); + if (pages[page] == "fp0dVQnw") + { + this.fechtedpoi = true; + POIS pois = JsonUtility.FromJson(webRequest.downloadHandler.text); + } + break; + } + } + } +} diff --git a/Assets/Dynamic_UI.cs.meta b/Assets/Dynamic_UI.cs.meta new file mode 100644 index 0000000..45e4887 --- /dev/null +++ b/Assets/Dynamic_UI.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 64c358cc15978d84abdb7788721e67d6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor.meta b/Assets/Editor.meta new file mode 100644 index 0000000..0afa8e4 --- /dev/null +++ b/Assets/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9a2df797eb7ea8e44843144af9429b99 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/com.unity.mobile.notifications.meta b/Assets/Editor/com.unity.mobile.notifications.meta new file mode 100644 index 0000000..a665f3c --- /dev/null +++ b/Assets/Editor/com.unity.mobile.notifications.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6d8e2e3178665be488e481c57be9527e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/com.unity.mobile.notifications/NotificationSettings.asset b/Assets/Editor/com.unity.mobile.notifications/NotificationSettings.asset new file mode 100644 index 0000000..655d006 --- /dev/null +++ b/Assets/Editor/com.unity.mobile.notifications/NotificationSettings.asset @@ -0,0 +1,42 @@ +%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: 0863bf92b4fcc45b0b9267325249bf0f, type: 3} + m_Name: NotificationSettings + m_EditorClassIdentifier: + toolbarInt: 0 + iOSNotificationEditorSettingsValues: + keys: + - UnityNotificationRequestAuthorizationOnAppLaunch + - UnityNotificationDefaultAuthorizationOptions + - UnityAddRemoteNotificationCapability + - UnityNotificationRequestAuthorizationForRemoteNotificationsOnAppLaunch + - UnityRemoteNotificationForegroundPresentationOptions + - UnityUseAPSReleaseEnvironment + - UnityUseLocationNotificationTrigger + values: + - True + - 7 + - False + - False + - -1 + - False + - False + AndroidNotificationEditorSettingsValues: + keys: + - UnityNotificationAndroidRescheduleOnDeviceRestart + - UnityNotificationAndroidUseCustomActivity + - UnityNotificationAndroidCustomActivityString + values: + - False + - False + - com.unity3d.player.UnityPlayerActivity + TrackedResourceAssets: [] diff --git a/Assets/Editor/com.unity.mobile.notifications/NotificationSettings.asset.meta b/Assets/Editor/com.unity.mobile.notifications/NotificationSettings.asset.meta new file mode 100644 index 0000000..60a3cc6 --- /dev/null +++ b/Assets/Editor/com.unity.mobile.notifications/NotificationSettings.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 45a04f37e0f48c744acc0874c4a8918a +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GPS.cs b/Assets/GPS.cs new file mode 100644 index 0000000..2cc0aea --- /dev/null +++ b/Assets/GPS.cs @@ -0,0 +1,53 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class GPS : MonoBehaviour +{ + // Start is called before the first frame update + void Start() + { + StartCoroutine(GPSLoc()); + } + + IEnumerator GPSLoc() + { + // Check if the user has location service enabled. + if (!Input.location.isEnabledByUser) + yield break; + + // Starts the location service. + Input.location.Start(0.5f, 0.5f); + Input.compass.enabled = true; + + // Waits until the location service initializes + int maxWait = 20; + while (Input.location.status == LocationServiceStatus.Initializing && maxWait > 0) + { + yield return new WaitForSeconds(1); + maxWait--; + } + + // If the service didn't initialize in 20 seconds this cancels location service use. + if (maxWait < 1) + { + print("Timed out"); + yield break; + } + + // If the connection failed this cancels location service use. + if (Input.location.status == LocationServiceStatus.Failed) + { + print("Unable to determine device location"); + yield break; + } + else + { + // If the connection succeeded, this retrieves the device's current location and displays it in the Console window. + print("Location: " + Input.location.lastData.latitude + " " + Input.location.lastData.longitude + " " + Input.location.lastData.altitude + " " + Input.location.lastData.horizontalAccuracy + " " + Input.location.lastData.timestamp); + } + + // Stops the location service if there is no need to query location updates continuously. + + } +} diff --git a/Assets/GPS.cs.meta b/Assets/GPS.cs.meta new file mode 100644 index 0000000..e458516 --- /dev/null +++ b/Assets/GPS.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f56abc74667c31f48989800bf172f589 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GPScontroller.cs b/Assets/GPScontroller.cs new file mode 100644 index 0000000..009e0a3 --- /dev/null +++ b/Assets/GPScontroller.cs @@ -0,0 +1,94 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using TMPro; +using UnityEngine.UI; +using GeoCoordinatePortable; + +public class GPScontroller : MonoBehaviour +{ + [SerializeField] private TextMeshProUGUI Cords; + [SerializeField] private TextMeshProUGUI Distance; + [SerializeField] private TextMeshProUGUI rotat; + [SerializeField] private RawImage compass_img; + [SerializeField] private Button found_btn; + + [SerializeField] private int Radius; + + + private bool inradius; + private double distance = 20; + private RectTransform compass_rect; + private int angle; + // Start is called before the first frame update + void Start() + { + compass_rect = compass_img.GetComponent(); + inradius = false; + found_btn.interactable = false; + Screen.sleepTimeout = SleepTimeout.NeverSleep; + } + + void FixedUpdate() + { + if (distance <= Radius) + { + inradius = true; + found_btn.interactable = true; + } + else + { + inradius = false; + found_btn.interactable = false; + } + } + + void Update() + { + + if (Input.location.status == LocationServiceStatus.Failed) + { + Cords.text = "Unable to determine device location"; + } + else + { + Cords.text = "Latitude: " + Input.location.lastData.latitude + " Longitude: " + Input.location.lastData.longitude; + + GeoCoordinate curr_pos = new GeoCoordinate(Input.location.lastData.latitude, Input.location.lastData.longitude); + GeoCoordinate wanna_be = new GeoCoordinate(49.86086629274778f, 8.566904834576274f); + distance = curr_pos.GetDistanceTo(wanna_be); + Quaternion compass = Quaternion.Euler(0, -Input.compass.magneticHeading, 0); + + angle = (int)(getBearing(curr_pos, wanna_be) - compass.eulerAngles.y); + compass_rect.SetPositionAndRotation(compass_rect.transform.position, Quaternion.Euler(0, 0, angle - 90)); + + rotat.text = compass.eulerAngles.y.ToString() + " : " + getBearing(curr_pos, wanna_be).ToString() + " : " + angle.ToString() + " : " + Input.compass.headingAccuracy.ToString(); ; + } + Distance.text = "Distance: " + ((int)distance).ToString() + "m"; + found_btn.interactable = inradius; + } + + + private static double ToRadians(double val) + { + return (Mathf.PI / 180) * val; + } + private static double ToDegrees(double radians) + { + return (180 / Mathf.PI) * radians; + } + + private double getBearing(GeoCoordinate curr, GeoCoordinate wanna_be) + { + // https://stackoverflow.com/questions/64791543/finding-a-heading-towards-a-coordinate + float deltaL = (float)(ToRadians(wanna_be.Longitude) - ToRadians(curr.Longitude)); + float thataB = (float)ToRadians(wanna_be.Latitude); + float thataA = (float)ToRadians(curr.Latitude); + float x = (float)(Mathf.Cos(thataB) * Mathf.Sin(deltaL)); + float y = (float)(Mathf.Cos(thataA) * Mathf.Sin(thataB) - Mathf.Sin(thataA) * Mathf.Cos(thataB) * Mathf.Cos(deltaL)); + float bearing = (float)Mathf.Atan2(x, y); + return ToDegrees(bearing); + } + + +} \ No newline at end of file diff --git a/Assets/GPScontroller.cs.meta b/Assets/GPScontroller.cs.meta new file mode 100644 index 0000000..8d1d1a2 --- /dev/null +++ b/Assets/GPScontroller.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7ee9507c8b4c5aa4fa87336b7626ab45 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GeoCoordinate.cs b/Assets/GeoCoordinate.cs new file mode 100644 index 0000000..ab5aadf --- /dev/null +++ b/Assets/GeoCoordinate.cs @@ -0,0 +1,341 @@ +using System; +using System.Globalization; + +namespace GeoCoordinatePortable +{ + /// + /// Represents a geographical location that is determined by latitude and longitude + /// coordinates. May also include altitude, accuracy, speed, and course information. + /// + public class GeoCoordinate : IEquatable + { + /// + /// Represents a object that has unknown latitude and longitude fields. + /// + public static readonly GeoCoordinate Unknown = new GeoCoordinate(); + private double _course; + private double _horizontalAccuracy; + private double _latitude; + private double _longitude; + private double _speed; + private double _verticalAccuracy; + + /// + /// Initializes a new instance of GeoCoordinate that has no data fields set. + /// + public GeoCoordinate() + : this(double.NaN, double.NaN) + { + } + + /// + /// Initializes a new instance of the GeoCoordinate class from latitude and longitude data. + /// + /// The latitude of the location. May range from -90.0 to 90.0. + /// The longitude of the location. May range from -180.0 to 180.0. + /// Latitude or longitude is out of range. + public GeoCoordinate(double latitude, double longitude) + : this(latitude, longitude, double.NaN) + { + } + + /// + /// Initializes a new instance of the GeoCoordinate class from latitude, longitude, and altitude data. + /// + /// Latitude. May range from -90.0 to 90.0. + /// Longitude. May range from -180.0 to 180.0 + /// The altitude in meters. May be negative, 0, positive, or Double.NaN, if unknown. + /// + /// latitude, longitude or altitude is out of range. + /// + public GeoCoordinate(double latitude, double longitude, double altitude) + : this(latitude, longitude, altitude, double.NaN, double.NaN, double.NaN, double.NaN) + { + } + + /// + /// Initializes a new instance of the GeoCoordinate class from latitude, longitude, altitude, horizontal accuracy, + /// vertical accuracy, speed, and course. + /// + /// The latitude of the location. May range from -90.0 to 90.0. + /// The longitude of the location. May range from -180.0 to 180.0. + /// The altitude in meters. May be negative, 0, positive, or Double.NaN, if unknown. + /// + /// The accuracy of the latitude and longitude coordinates, in meters. Must be greater + /// than or equal to 0. If a value of 0 is supplied to this constructor, the HorizontalAccuracy property will be set to + /// Double.NaN. + /// + /// + /// The accuracy of the altitude, in meters. Must be greater than or equal to 0. If a value + /// of 0 is supplied to this constructor, the VerticalAccuracy property will be set to Double.NaN. + /// + /// + /// The speed measured in meters per second. May be negative, 0, positive, or Double.NaN, if unknown. + /// A negative speed can indicate moving in reverse. + /// + /// + /// The direction of travel, rather than orientation. This parameter is measured in degrees relative + /// to true north. Must range from 0 to 360.0, or be Double.NaN. + /// + /// + /// If latitude, longitude, horizontalAccuracy, verticalAccuracy, course is out of range. + /// + public GeoCoordinate(double latitude, double longitude, double altitude, double horizontalAccuracy, + double verticalAccuracy, double speed, double course) + { + Latitude = latitude; + Longitude = longitude; + Altitude = altitude; + HorizontalAccuracy = horizontalAccuracy; + VerticalAccuracy = verticalAccuracy; + Speed = speed; + Course = course; + } + + /// + /// Gets or sets the latitude of the GeoCoordinate. + /// + /// + /// Latitude of the location. + /// + /// Latitude is set outside the valid range. + public double Latitude + { + get { return _latitude; } + set + { + if (value > 90.0 || value < -90.0) + { + throw new ArgumentOutOfRangeException("Latitude", "Argument must be in range of -90 to 90"); + } + _latitude = value; + } + } + + /// + /// Gets or sets the longitude of the GeoCoordinate. + /// + /// + /// The longitude. + /// + /// Longitude is set outside the valid range. + public double Longitude + { + get { return _longitude; } + set + { + if (value > 180.0 || value < -180.0) + { + throw new ArgumentOutOfRangeException("Longitude", "Argument must be in range of -180 to 180"); + } + _longitude = value; + } + } + + /// + /// Gets or sets the accuracy of the latitude and longitude that is given by the GeoCoordinate, in meters. + /// + /// + /// The accuracy of the latitude and longitude, in meters. + /// + /// HorizontalAccuracy is set outside the valid range. + public double HorizontalAccuracy + { + get { return _horizontalAccuracy; } + set + { + if (value < 0.0) + throw new ArgumentOutOfRangeException("HorizontalAccuracy", "Argument must be non negative"); + _horizontalAccuracy = value == 0.0 ? double.NaN : value; + } + } + + /// + /// Gets or sets the accuracy of the altitude given by the GeoCoordinate, in meters. + /// + /// + /// The accuracy of the altitude, in meters. + /// + /// VerticalAccuracy is set outside the valid range. + public double VerticalAccuracy + { + get { return _verticalAccuracy; } + set + { + if (value < 0.0) + throw new ArgumentOutOfRangeException("VerticalAccuracy", "Argument must be non negative"); + _verticalAccuracy = value == 0.0 ? double.NaN : value; + } + } + + /// + /// Gets or sets the speed in meters per second. + /// + /// + /// The speed in meters per second. The speed must be greater than or equal to zero, or Double.NaN. + /// + /// Speed is set outside the valid range. + public double Speed + { + get { return _speed; } + set + { + if (value < 0.0) + throw new ArgumentOutOfRangeException("speed", "Argument must be non negative"); + _speed = value; + } + } + + /// + /// Gets or sets the heading in degrees, relative to true north. + /// + /// + /// The heading in degrees, relative to true north. + /// + /// Course is set outside the valid range. + public double Course + { + get { return _course; } + set + { + if (value < 0.0 || value > 360.0) + throw new ArgumentOutOfRangeException("course", "Argument must be in range 0 to 360"); + _course = value; + } + } + + /// + /// Gets a value that indicates whether the GeoCoordinate does not contain latitude or longitude data. + /// + /// + /// true if the GeoCoordinate does not contain latitude or longitude data; otherwise, false. + /// + public bool IsUnknown => Equals(Unknown); + + /// + /// Gets the altitude of the GeoCoordinate, in meters. + /// + /// + /// The altitude, in meters. + /// + public double Altitude { get; set; } + + /// + /// Determines if the GeoCoordinate object is equivalent to the parameter, based solely on latitude and longitude. + /// + /// + /// true if the GeoCoordinate objects are equal; otherwise, false. + /// + /// The GeoCoordinate object to compare to the calling object. + public bool Equals(GeoCoordinate other) + { + if (ReferenceEquals(other, null)) + return false; + + var num = Latitude; + + if (!num.Equals(other.Latitude)) + return false; + + num = Longitude; + + return num.Equals(other.Longitude); + } + + /// + /// Determines whether two GeoCoordinate objects refer to the same location. + /// + /// + /// true, if the GeoCoordinate objects are determined to be equivalent; otherwise, false. + /// + /// The first GeoCoordinate to compare. + /// The second GeoCoordinate to compare. + public static bool operator ==(GeoCoordinate left, GeoCoordinate right) + { + if (ReferenceEquals(left, null)) + return ReferenceEquals(right, null); + + return left.Equals(right); + } + + /// + /// Determines whether two GeoCoordinate objects correspond to different locations. + /// + /// + /// true, if the GeoCoordinate objects are determined to be different; otherwise, false. + /// + /// The first GeoCoordinate to compare. + /// The second GeoCoordinate to compare. + public static bool operator !=(GeoCoordinate left, GeoCoordinate right) + { + return !(left == right); + } + + /// + /// Returns the distance between the latitude and longitude coordinates that are specified by this GeoCoordinate and + /// another specified GeoCoordinate. + /// + /// + /// The distance between the two coordinates, in meters. + /// + /// The GeoCoordinate for the location to calculate the distance to. + public double GetDistanceTo(GeoCoordinate other) + { + if (double.IsNaN(Latitude) || double.IsNaN(Longitude) || double.IsNaN(other.Latitude) || + double.IsNaN(other.Longitude)) + { + throw new ArgumentException("Argument latitude or longitude is not a number"); + } + + var d1 = Latitude * (Math.PI / 180.0); + var num1 = Longitude * (Math.PI / 180.0); + var d2 = other.Latitude * (Math.PI / 180.0); + var num2 = other.Longitude * (Math.PI / 180.0) - num1; + var d3 = Math.Pow(Math.Sin((d2 - d1) / 2.0), 2.0) + + Math.Cos(d1) * Math.Cos(d2) * Math.Pow(Math.Sin(num2 / 2.0), 2.0); + + return 6376500.0 * (2.0 * Math.Atan2(Math.Sqrt(d3), Math.Sqrt(1.0 - d3))); + } + + /// + /// Serves as a hash function for the GeoCoordinate. + /// + /// + /// A hash code for the current GeoCoordinate. + /// + public override int GetHashCode() + { + return Latitude.GetHashCode() ^ Longitude.GetHashCode(); + } + + /// + /// Determines if a specified GeoCoordinate is equal to the current GeoCoordinate, based solely on latitude and + /// longitude. + /// + /// + /// true, if the GeoCoordinate objects are equal; otherwise, false. + /// + /// The object to compare the GeoCoordinate to. + public override bool Equals(object obj) + { + return Equals(obj as GeoCoordinate); + } + + /// + /// Returns a string that contains the latitude and longitude. + /// + /// + /// A string that contains the latitude and longitude, separated by a comma. + /// + public override string ToString() + { + if (this == Unknown) + { + return "Unknown"; + } + + return + $"{Latitude.ToString("G", CultureInfo.InvariantCulture)}, {Longitude.ToString("G", CultureInfo.InvariantCulture)}"; + } + } +} \ No newline at end of file diff --git a/Assets/GeoCoordinate.cs.meta b/Assets/GeoCoordinate.cs.meta new file mode 100644 index 0000000..2d33f40 --- /dev/null +++ b/Assets/GeoCoordinate.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 850e83dbc88a4554da0946a5f60ff047 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GeoPosition.cs b/Assets/GeoPosition.cs new file mode 100644 index 0000000..f77d682 --- /dev/null +++ b/Assets/GeoPosition.cs @@ -0,0 +1,46 @@ +using System; + +namespace GeoCoordinatePortable +{ + /// + /// Contains location data of a type specified by the type parameter of the class + /// + /// The type of the location data. + public class GeoPosition + { + /// + /// Initializes a new instance of the class. + /// + public GeoPosition() + { + } + + /// + /// Initializes a new instance of the class + /// with a timestamp and position. + /// + /// The time the location data was obtained. + /// The location data to use to initialize the object. + public GeoPosition(DateTimeOffset timestamp, T location) + { + Timestamp = timestamp; + Location = location; + } + + /// + /// Gets or sets the location data for the object. + /// + /// + /// An object of type T that contains the location data for the object. + /// + public T Location { get; set; } + + /// + /// Gets or sets the time when the location data was obtained. + /// + /// + /// A that contains the time the location data was created. + /// + public DateTimeOffset Timestamp { get; set; } + } +} \ No newline at end of file diff --git a/Assets/GeoPosition.cs.meta b/Assets/GeoPosition.cs.meta new file mode 100644 index 0000000..753632f --- /dev/null +++ b/Assets/GeoPosition.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bcd327ab2c41c1b42afa0263a9e84924 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/POI.json b/Assets/POI.json new file mode 100644 index 0000000..c735226 --- /dev/null +++ b/Assets/POI.json @@ -0,0 +1,19 @@ +{ + "version": "0.1", + "pois": [ + { + "name": "Sitzsack", + "position": [ + 49.857982, + 8.5583 + ] + }, + { + "name": "Terrasse", + "position": [ + 49.857936, + 8.558297 + ] + } + ] +} \ No newline at end of file diff --git a/Assets/POI.json.meta b/Assets/POI.json.meta new file mode 100644 index 0000000..775287b --- /dev/null +++ b/Assets/POI.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 00ee1010a3cb44042b05d3afc06adfe9 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Prefabs.meta b/Assets/Prefabs.meta new file mode 100644 index 0000000..abd1fb9 --- /dev/null +++ b/Assets/Prefabs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8143a0c8a3e0d1042ad58fc9c0596c9f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Prefabs/Anchor.prefab b/Assets/Prefabs/Anchor.prefab new file mode 100644 index 0000000..68e6db9 --- /dev/null +++ b/Assets/Prefabs/Anchor.prefab @@ -0,0 +1,85 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &3033127319783910676 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2530976781631077688} + - component: {fileID: 8289528555328162453} + - component: {fileID: 6594983877314590435} + m_Layer: 0 + m_Name: Anchor + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2530976781631077688 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3033127319783910676} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0.1, y: 0.1, z: 0.1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &8289528555328162453 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3033127319783910676} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &6594983877314590435 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3033127319783910676} + 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: 22262639920f43d6be32430e4e58350d, 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} diff --git a/Assets/Prefabs/Anchor.prefab.meta b/Assets/Prefabs/Anchor.prefab.meta new file mode 100644 index 0000000..ee17090 --- /dev/null +++ b/Assets/Prefabs/Anchor.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: fb71847722300c943b4e2833b7d420b7 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Prefabs/Button.prefab b/Assets/Prefabs/Button.prefab new file mode 100644 index 0000000..7ea533a --- /dev/null +++ b/Assets/Prefabs/Button.prefab @@ -0,0 +1,284 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &7249320401528742714 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7249320401528742713} + - component: {fileID: 7249320401528742718} + - component: {fileID: 7249320401528742719} + - component: {fileID: 7249320401528742712} + - component: {fileID: 1273516815054558568} + m_Layer: 5 + m_Name: Button + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &7249320401528742713 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7249320401528742714} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0.57574, y: 0.57574, z: 0.57574} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 7249320402513519708} + m_Father: {fileID: 0} + 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: 75, y: -4.317871} + m_SizeDelta: {x: 150, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &7249320401528742718 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7249320401528742714} + m_CullTransparentMesh: 1 +--- !u!114 &7249320401528742719 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7249320401528742714} + 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.6179246, b: 0.6179246, 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: 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 + m_PixelsPerUnitMultiplier: 1 +--- !u!114 &7249320401528742712 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7249320401528742714} + 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: 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: 7249320401528742719} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1273516815054558568} + m_TargetAssemblyTypeName: SceneSwitcher, Assembly-CSharp + m_MethodName: SwitchLevel + 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!114 &1273516815054558568 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7249320401528742714} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 8badf486ffbd12a4db418e7514263dc3, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1 &7249320402513519709 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7249320402513519708} + - component: {fileID: 7249320402513519698} + - component: {fileID: 7249320402513519699} + m_Layer: 5 + m_Name: Text (TMP) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &7249320402513519708 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7249320402513519709} + m_LocalRotation: {x: 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: 7249320401528742713} + 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: 150, y: 15} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &7249320402513519698 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7249320402513519709} + m_CullTransparentMesh: 1 +--- !u!114 &7249320402513519699 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7249320402513519709} + 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: Button + 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: 4281874639 + m_fontColor: {r: 0.8113208, g: 0.21813813, b: 0.21813813, 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: 24.8 + m_fontSizeBase: 24.8 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 0 + m_fontSizeMax: 0 + 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: 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} diff --git a/Assets/Prefabs/Button.prefab.meta b/Assets/Prefabs/Button.prefab.meta new file mode 100644 index 0000000..a5ac870 --- /dev/null +++ b/Assets/Prefabs/Button.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 496910a86c8eb204294fee466dc70657 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources.meta b/Assets/Resources.meta new file mode 100644 index 0000000..a9f7c44 --- /dev/null +++ b/Assets/Resources.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6437dc96b0f3ccb4ba87d7b88595974c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/ARDK.meta b/Assets/Resources/ARDK.meta new file mode 100644 index 0000000..e129d2a --- /dev/null +++ b/Assets/Resources/ARDK.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9749eec1c53ee4e42a017b9b7a3d5dc8 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/ARDK/ArdkAuthConfig.asset b/Assets/Resources/ARDK/ArdkAuthConfig.asset new file mode 100644 index 0000000..6004a79 --- /dev/null +++ b/Assets/Resources/ARDK/ArdkAuthConfig.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: 3e818d7086440451e889be0511048aa6, type: 3} + m_Name: ArdkAuthConfig + m_EditorClassIdentifier: + _apiKey: 2dudnWEgKZHuQl4vrYtn diff --git a/Assets/Resources/ARDK/ArdkAuthConfig.asset.meta b/Assets/Resources/ARDK/ArdkAuthConfig.asset.meta new file mode 100644 index 0000000..35bf338 --- /dev/null +++ b/Assets/Resources/ARDK/ArdkAuthConfig.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b463f25a79fd1d1479b946f21bef8000 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SceneSwitcher.cs b/Assets/SceneSwitcher.cs new file mode 100644 index 0000000..005c28c --- /dev/null +++ b/Assets/SceneSwitcher.cs @@ -0,0 +1,15 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.SceneManagement; +using UnityEngine.UI; +using TMPro; + +public class SceneSwitcher : MonoBehaviour +{ + public void SwitchLevel(string Level) + { + Debug.Log("fuzck ui"); + SceneManager.LoadScene(Level); + } +} diff --git a/Assets/SceneSwitcher.cs.meta b/Assets/SceneSwitcher.cs.meta new file mode 100644 index 0000000..417e448 --- /dev/null +++ b/Assets/SceneSwitcher.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8badf486ffbd12a4db418e7514263dc3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes.meta b/Assets/Scenes.meta new file mode 100644 index 0000000..c317c08 --- /dev/null +++ b/Assets/Scenes.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 30340b97d11d06a45ab35a95bc963c9a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/Main.unity b/Assets/Scenes/Main.unity new file mode 100644 index 0000000..1ee59cd --- /dev/null +++ b/Assets/Scenes/Main.unity @@ -0,0 +1,997 @@ +%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: 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 &332670402 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 332670405} + - component: {fileID: 332670404} + - component: {fileID: 332670403} + - component: {fileID: 332670406} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &332670403 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 332670402} + 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 &332670404 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 332670402} + 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 &332670405 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 332670402} + m_LocalRotation: {x: 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_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &332670406 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 332670402} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f56abc74667c31f48989800bf172f589, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1 &350063900 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 350063902} + - component: {fileID: 350063901} + 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 &350063901 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 350063900} + m_Enabled: 1 + serializedVersion: 10 + m_Type: 1 + m_Shape: 0 + m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} + m_Intensity: 1 + 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: 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 &350063902 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 350063900} + 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_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} +--- !u!1 &438558543 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 438558544} + - component: {fileID: 438558546} + - component: {fileID: 438558545} + m_Layer: 5 + m_Name: Text (TMP) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &438558544 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 438558543} + m_LocalRotation: {x: 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: 1772418000} + 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 &438558545 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 438558543} + 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: Button + 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: 24 + m_fontSizeBase: 24 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 2 + m_VerticalAlignment: 512 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 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 &438558546 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 438558543} + m_CullTransparentMesh: 1 +--- !u!1 &743292302 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 743292306} + - component: {fileID: 743292305} + - component: {fileID: 743292304} + - component: {fileID: 743292303} + - component: {fileID: 743292307} + m_Layer: 5 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &743292303 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 743292302} + 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: 2147483647 +--- !u!114 &743292304 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 743292302} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, 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 + m_PresetInfoIsWorld: 0 +--- !u!223 &743292305 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 743292302} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 1 + m_Camera: {fileID: 1075206274} + m_PlaneDistance: 50 + 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 &743292306 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 743292302} + 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: 798590233} + - {fileID: 1772418000} + m_Father: {fileID: 0} + 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, y: 0} +--- !u!114 &743292307 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 743292302} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 64c358cc15978d84abdb7788721e67d6, type: 3} + m_Name: + m_EditorClassIdentifier: + text: {fileID: 798590231} + obj: {fileID: 0} +--- !u!1 &798590230 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 798590233} + - component: {fileID: 798590232} + - component: {fileID: 798590231} + m_Layer: 5 + m_Name: Text (TMP) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &798590231 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 798590230} + 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: New 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: 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: 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 &798590232 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 798590230} + m_CullTransparentMesh: 1 +--- !u!224 &798590233 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 798590230} + m_LocalRotation: {x: 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: 743292306} + 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: 50} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &942985773 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 942985775} + - component: {fileID: 942985774} + m_Layer: 5 + m_Name: UIDocument + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &942985774 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 942985773} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 19102, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_PanelSettings: {fileID: 11400000, guid: 7085e9cd0c737af4aad102900c61ffee, type: 2} + m_ParentUI: {fileID: 0} + sourceAsset: {fileID: 9197481963319205126, guid: 924d62a5906e4954bbd573ee19cbe4c4, + type: 3} + m_SortingOrder: 0 +--- !u!4 &942985775 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 942985773} + m_LocalRotation: {x: 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_RootOrder: 5 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1075206272 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1075206275} + - component: {fileID: 1075206274} + - component: {fileID: 1075206273} + 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 &1075206273 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1075206272} + m_Enabled: 1 +--- !u!20 &1075206274 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1075206272} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 2 + m_BackGroundColor: {r: 0, g: 0, b: 0, a: 1} + 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: 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 &1075206275 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1075206272} + 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_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1422852436 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1422852438} + - component: {fileID: 1422852437} + m_Layer: 0 + m_Name: kaka + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1422852437 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1422852436} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 8badf486ffbd12a4db418e7514263dc3, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!4 &1422852438 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1422852436} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 4.788891, y: 4.2324896, z: 39.818146} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1772417999 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1772418000} + - component: {fileID: 1772418003} + - component: {fileID: 1772418002} + - component: {fileID: 1772418001} + m_Layer: 5 + m_Name: Button + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1772418000 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1772417999} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 6.55, y: 6.55, z: 6.55} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 438558544} + m_Father: {fileID: 743292306} + 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: 755} + m_SizeDelta: {x: 160, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1772418001 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1772417999} + 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: 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: 1772418002} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1422852437} + m_TargetAssemblyTypeName: SceneSwitcher, Assembly-CSharp + m_MethodName: SwitchLevel + m_Mode: 5 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: SearchGPS + m_BoolArgument: 0 + m_CallState: 2 +--- !u!114 &1772418002 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1772417999} + 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: 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 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1772418003 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1772417999} + m_CullTransparentMesh: 1 diff --git a/Assets/Scenes/Main.unity.meta b/Assets/Scenes/Main.unity.meta new file mode 100644 index 0000000..b5d6767 --- /dev/null +++ b/Assets/Scenes/Main.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: b6474ea881770b3409e04772a882bc0a +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/NewUXMLTemplate.uxml b/Assets/Scenes/NewUXMLTemplate.uxml new file mode 100644 index 0000000..21ee883 --- /dev/null +++ b/Assets/Scenes/NewUXMLTemplate.uxml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/Assets/Scenes/NewUXMLTemplate.uxml.meta b/Assets/Scenes/NewUXMLTemplate.uxml.meta new file mode 100644 index 0000000..c1b76a6 --- /dev/null +++ b/Assets/Scenes/NewUXMLTemplate.uxml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 924d62a5906e4954bbd573ee19cbe4c4 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0} diff --git a/Assets/Scenes/SearchGPS.unity b/Assets/Scenes/SearchGPS.unity new file mode 100644 index 0000000..8adc081 --- /dev/null +++ b/Assets/Scenes/SearchGPS.unity @@ -0,0 +1,1379 @@ +%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: 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 &497923708 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 497923709} + - component: {fileID: 497923711} + - component: {fileID: 497923710} + m_Layer: 5 + m_Name: Comp_needle + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &497923709 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 497923708} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0.2487, y: 0.2487, z: 0.2487} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 2006140274} + 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: 34.3} + m_SizeDelta: {x: 100, y: 100} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &497923710 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 497923708} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 1344c3c82d62a2a41a3576d8abb8e3ea, 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_Texture: {fileID: 2800000, guid: 1df24786ab9ee03439ed6f5eb8d0b370, type: 3} + m_UVRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 +--- !u!222 &497923711 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 497923708} + m_CullTransparentMesh: 1 +--- !u!1 &498509445 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 498509449} + - component: {fileID: 498509448} + - component: {fileID: 498509447} + - component: {fileID: 498509450} + - component: {fileID: 498509446} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &498509446 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 498509445} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 7ee9507c8b4c5aa4fa87336b7626ab45, type: 3} + m_Name: + m_EditorClassIdentifier: + Cords: {fileID: 889699546} + Distance: {fileID: 1357806463} + rotat: {fileID: 1519385038} + compass_img: {fileID: 497923710} + found_btn: {fileID: 1827718301} + Radius: 500000 +--- !u!114 &498509447 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 498509445} + 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 &498509448 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 498509445} + 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 &498509449 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 498509445} + m_LocalRotation: {x: 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_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &498509450 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 498509445} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f56abc74667c31f48989800bf172f589, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1 &889699543 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 889699544} + - component: {fileID: 889699545} + - component: {fileID: 889699546} + m_Layer: 5 + m_Name: 'Cords:' + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &889699544 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 889699543} + m_LocalRotation: {x: -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: 2006140274} + 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: 50, y: -35.56125} + m_SizeDelta: {x: 100, y: 18.05} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &889699545 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 889699543} + m_CullTransparentMesh: 1 +--- !u!114 &889699546 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 889699543} + 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: 'Long: + + Lat: + +' + 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: 10 + m_fontSizeBase: 10 + 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: 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: -10.573683} + 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 &1211913184 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1211913186} + - component: {fileID: 1211913185} + m_Layer: 0 + m_Name: Kaka + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1211913185 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1211913184} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 8badf486ffbd12a4db418e7514263dc3, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!4 &1211913186 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1211913184} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 4.788891, y: 4.2324896, z: 39.818146} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1357806460 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1357806461} + - component: {fileID: 1357806462} + - component: {fileID: 1357806463} + m_Layer: 5 + m_Name: Distance + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1357806461 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1357806460} + m_LocalRotation: {x: -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: 2006140274} + 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: 50, y: -60} + m_SizeDelta: {x: 100, y: 18.05} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &1357806462 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1357806460} + m_CullTransparentMesh: 1 +--- !u!114 &1357806463 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1357806460} + 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: 'Distance:' + 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: 12 + m_fontSizeBase: 12 + 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: 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: -5.760024} + 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 &1409676644 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1409676645} + - component: {fileID: 1409676647} + - component: {fileID: 1409676646} + m_Layer: 5 + m_Name: Text (TMP) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1409676645 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1409676644} + m_LocalRotation: {x: 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: 1827718304} + 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 &1409676646 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1409676644} + 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: Found - Start AR + 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: 18.1 + m_fontSizeBase: 18.1 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 2 + m_VerticalAlignment: 512 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 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 &1409676647 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1409676644} + m_CullTransparentMesh: 1 +--- !u!1 &1519385035 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1519385036} + - component: {fileID: 1519385037} + - component: {fileID: 1519385038} + m_Layer: 5 + m_Name: Rotat + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1519385036 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1519385035} + m_LocalRotation: {x: -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: 2006140274} + 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: 50, y: -74.1} + m_SizeDelta: {x: 100, y: 18.05} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &1519385037 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1519385035} + m_CullTransparentMesh: 1 +--- !u!114 &1519385038 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1519385035} + 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: Rotat + 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: 12 + m_fontSizeBase: 12 + 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: 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: -5.760024} + 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 &1558977079 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1558977080} + - component: {fileID: 1558977083} + - component: {fileID: 1558977082} + - component: {fileID: 1558977081} + m_Layer: 5 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1558977080 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1558977079} + 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: 2006140274} + 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 &1558977081 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1558977079} + 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 &1558977082 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1558977079} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, 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 + m_PresetInfoIsWorld: 0 +--- !u!223 &1558977083 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1558977079} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 1 + m_Camera: {fileID: 2122225927} + 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 &1827718300 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1827718304} + - component: {fileID: 1827718303} + - component: {fileID: 1827718302} + - component: {fileID: 1827718301} + m_Layer: 5 + m_Name: Button + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1827718301 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1827718300} + 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: 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: 1827718302} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1211913185} + m_TargetAssemblyTypeName: SceneSwitcher, Assembly-CSharp + m_MethodName: SwitchLevel + m_Mode: 5 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: VPSCreate + m_BoolArgument: 0 + m_CallState: 2 +--- !u!114 &1827718302 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1827718300} + 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: 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 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1827718303 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1827718300} + m_CullTransparentMesh: 1 +--- !u!224 &1827718304 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1827718300} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0.55806, y: 0.55806, z: 0.55806} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1409676645} + m_Father: {fileID: 2006140274} + 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: -38.8} + m_SizeDelta: {x: 160, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &1861654293 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1861654295} + - component: {fileID: 1861654294} + 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 &1861654294 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1861654293} + m_Enabled: 1 + serializedVersion: 10 + m_Type: 1 + m_Shape: 0 + m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} + m_Intensity: 1 + 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: 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 &1861654295 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1861654293} + 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_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} +--- !u!1 &2006140273 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2006140274} + - component: {fileID: 2006140276} + - component: {fileID: 2006140275} + m_Layer: 5 + m_Name: BG + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2006140274 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2006140273} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 7.4789, y: 7.4789, z: 7.4789} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 497923709} + - {fileID: 889699544} + - {fileID: 1357806461} + - {fileID: 1519385036} + - {fileID: 1827718304} + m_Father: {fileID: 1558977080} + 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: 100, y: 100} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &2006140275 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2006140273} + 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.2830189, g: 0.2830189, b: 0.2830189, 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 &2006140276 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2006140273} + m_CullTransparentMesh: 1 +--- !u!1 &2122225925 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2122225928} + - component: {fileID: 2122225927} + - component: {fileID: 2122225926} + 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 &2122225926 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2122225925} + m_Enabled: 1 +--- !u!20 &2122225927 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2122225925} + 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_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: 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 &2122225928 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2122225925} + 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_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} diff --git a/Assets/Scenes/SearchGPS.unity.meta b/Assets/Scenes/SearchGPS.unity.meta new file mode 100644 index 0000000..83804a8 --- /dev/null +++ b/Assets/Scenes/SearchGPS.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: a95637ff7c61c6b42bd0c563a86e921a +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/VPSCreate.unity b/Assets/Scenes/VPSCreate.unity new file mode 100644 index 0000000..e6ffa96 --- /dev/null +++ b/Assets/Scenes/VPSCreate.unity @@ -0,0 +1,1901 @@ +%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: 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!1001 &27369971 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 1861203857} + m_Modifications: + - target: {fileID: 7249320401528742712, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_Target + value: + objectReference: {fileID: 1199484539} + - target: {fileID: 7249320401528742712, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_MethodName + value: SaveWayspotAnchors + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742712, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_TargetAssemblyTypeName + value: WayspotAnchors.WayspotAnchorManager, Assembly-CSharp + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_Pivot.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_Pivot.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_RootOrder + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_AnchorMax.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_AnchorMax.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_AnchorMin.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_AnchorMin.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_SizeDelta.x + value: 150 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_SizeDelta.y + value: 30 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalScale.x + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalScale.y + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalScale.z + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 943 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_AnchoredPosition.y + value: -828 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742714, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_Name + value: Save Anchors + objectReference: {fileID: 0} + - target: {fileID: 7249320402513519699, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_text + value: Save + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 496910a86c8eb204294fee466dc70657, type: 3} +--- !u!224 &27369972 stripped +RectTransform: + m_CorrespondingSourceObject: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + m_PrefabInstance: {fileID: 27369971} + m_PrefabAsset: {fileID: 0} +--- !u!1 &98020394 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 98020397} + - component: {fileID: 98020396} + - component: {fileID: 98020395} + m_Layer: 0 + m_Name: ARHelpers + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &98020395 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 98020394} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 544755552afaf4436af235f6de9be0b1, type: 3} + m_Name: + m_EditorClassIdentifier: + _permissions: 0000000002000000 +--- !u!114 &98020396 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 98020394} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b019f0c4dd824101a0a664f35dcb7ace, type: 3} + m_Name: + m_EditorClassIdentifier: + _manageUsingUnityLifecycle: 1 + _planePrefab: {fileID: 1092543363889104, guid: 98e455e2ba6ba413287f8cd497d4b08e, + type: 3} + _detectedPlaneTypes: 3 +--- !u!4 &98020397 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 98020394} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 4.763476, y: -36.931152, z: 11.37677} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1001 &219042238 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 1861203857} + m_Modifications: + - target: {fileID: 7249320401528742712, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_Target + value: + objectReference: {fileID: 1199484539} + - target: {fileID: 7249320401528742712, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_MethodName + value: ClearAnchorGameObjects + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742712, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_TargetAssemblyTypeName + value: WayspotAnchors.WayspotAnchorManager, Assembly-CSharp + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_Pivot.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_Pivot.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_RootOrder + value: 4 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_AnchorMax.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_AnchorMax.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_AnchorMin.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_AnchorMin.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_SizeDelta.x + value: 150 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_SizeDelta.y + value: 30 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalScale.x + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalScale.y + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalScale.z + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 944 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_AnchoredPosition.y + value: -973 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742714, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_Name + value: Clear Anchors + objectReference: {fileID: 0} + - target: {fileID: 7249320402513519699, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_text + value: Clear + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 496910a86c8eb204294fee466dc70657, type: 3} +--- !u!224 &219042239 stripped +RectTransform: + m_CorrespondingSourceObject: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + m_PrefabInstance: {fileID: 219042238} + m_PrefabAsset: {fileID: 0} +--- !u!1001 &765630017 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 1861203857} + m_Modifications: + - target: {fileID: 7249320401528742712, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_Target + value: + objectReference: {fileID: 1199484539} + - target: {fileID: 7249320401528742712, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_MethodName + value: RestartWayspotAnchorService + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742712, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_TargetAssemblyTypeName + value: WayspotAnchors.WayspotAnchorManager, Assembly-CSharp + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_Pivot.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_Pivot.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_RootOrder + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_AnchorMax.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_AnchorMax.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_AnchorMin.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_AnchorMin.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_SizeDelta.x + value: 150 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_SizeDelta.y + value: 30 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalScale.x + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalScale.y + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalScale.z + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalRotation.x + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalRotation.y + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalRotation.z + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 938 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_AnchoredPosition.y + value: -1461 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742714, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_Name + value: Restart Service + objectReference: {fileID: 0} + - target: {fileID: 7249320402513519699, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_text + value: 'Restart + +' + objectReference: {fileID: 0} + - target: {fileID: 7249320402513519699, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_fontSize + value: 28.2 + objectReference: {fileID: 0} + - target: {fileID: 7249320402513519699, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_fontSizeBase + value: 28.2 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 496910a86c8eb204294fee466dc70657, type: 3} +--- !u!224 &765630018 stripped +RectTransform: + m_CorrespondingSourceObject: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + m_PrefabInstance: {fileID: 765630017} + m_PrefabAsset: {fileID: 0} +--- !u!1001 &788970385 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 1861203857} + m_Modifications: + - target: {fileID: 7249320401528742712, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_Target + value: + objectReference: {fileID: 1199484539} + - target: {fileID: 7249320401528742712, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_MethodName + value: LoadWayspotAnchors + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742712, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_TargetAssemblyTypeName + value: WayspotAnchors.WayspotAnchorManager, Assembly-CSharp + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_Pivot.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_Pivot.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_RootOrder + value: 5 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_AnchorMax.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_AnchorMax.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_AnchorMin.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_AnchorMin.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_SizeDelta.x + value: 150 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_SizeDelta.y + value: 30 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalScale.x + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalScale.y + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalScale.z + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 942 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_AnchoredPosition.y + value: -1095 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742714, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_Name + value: Load Anchors + objectReference: {fileID: 0} + - target: {fileID: 7249320402513519699, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_text + value: Load + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 496910a86c8eb204294fee466dc70657, type: 3} +--- !u!224 &788970386 stripped +RectTransform: + m_CorrespondingSourceObject: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + m_PrefabInstance: {fileID: 788970385} + m_PrefabAsset: {fileID: 0} +--- !u!1 &840871075 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 840871076} + - component: {fileID: 840871078} + - component: {fileID: 840871077} + m_Layer: 0 + m_Name: ARSceneManager + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &840871076 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 840871075} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 4.763476, y: -36.931152, z: 11.37677} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1739816012} + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &840871077 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 840871075} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 043ecbfe80cd44fca08dc8e0ee10100e, type: 3} + m_Name: + m_EditorClassIdentifier: + _manageUsingUnityLifecycle: 1 + Success: + m_PersistentCalls: + m_Calls: [] + Failure: + m_PersistentCalls: + m_Calls: [] +--- !u!114 &840871078 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 840871075} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 00203f13141804260a205f7c8a71dc60, type: 3} + m_Name: + m_EditorClassIdentifier: + _manageUsingUnityLifecycle: 1 + RuntimeEnvironment: 0 + _runOptions: 0 + _useWithARNetworkingSession: 0 + _isLightEstimationEnabled: 0 + _isAutoFocusEnabled: 0 + _worldAlignment: 0 +--- !u!1001 &929200399 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 1861203857} + m_Modifications: + - target: {fileID: 7249320401528742712, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_Target + value: + objectReference: {fileID: 1199484539} + - target: {fileID: 7249320401528742712, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_MethodName + value: PauseARSession + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742712, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_TargetAssemblyTypeName + value: WayspotAnchors.WayspotAnchorManager, Assembly-CSharp + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_Pivot.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_Pivot.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_RootOrder + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_AnchorMax.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_AnchorMax.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_AnchorMin.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_AnchorMin.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_SizeDelta.x + value: 150 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_SizeDelta.y + value: 30 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalScale.x + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalScale.y + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalScale.z + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 940 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_AnchoredPosition.y + value: -1215 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742714, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_Name + value: Pause Session + objectReference: {fileID: 0} + - target: {fileID: 7249320402513519699, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_text + value: Pause + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 496910a86c8eb204294fee466dc70657, type: 3} +--- !u!224 &929200400 stripped +RectTransform: + m_CorrespondingSourceObject: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + m_PrefabInstance: {fileID: 929200399} + m_PrefabAsset: {fileID: 0} +--- !u!1001 &994113965 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 1861203857} + m_Modifications: + - target: {fileID: 7249320401528742712, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_Target + value: + objectReference: {fileID: 1199484539} + - target: {fileID: 7249320401528742712, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_MethodName + value: ResumeARSession + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742712, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_TargetAssemblyTypeName + value: WayspotAnchors.WayspotAnchorManager, Assembly-CSharp + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_Pivot.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_Pivot.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_RootOrder + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_AnchorMax.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_AnchorMax.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_AnchorMin.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_AnchorMin.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_SizeDelta.x + value: 150 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_SizeDelta.y + value: 30 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalScale.x + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalScale.y + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalScale.z + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 941 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_AnchoredPosition.y + value: -1330 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7249320401528742714, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_Name + value: Resume Session + objectReference: {fileID: 0} + - target: {fileID: 7249320402513519699, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + propertyPath: m_text + value: Resume + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 496910a86c8eb204294fee466dc70657, type: 3} +--- !u!224 &994113966 stripped +RectTransform: + m_CorrespondingSourceObject: {fileID: 7249320401528742713, guid: 496910a86c8eb204294fee466dc70657, + type: 3} + m_PrefabInstance: {fileID: 994113965} + m_PrefabAsset: {fileID: 0} +--- !u!1 &1199484538 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1199484540} + - component: {fileID: 1199484539} + m_Layer: 0 + m_Name: WayspotAnchors + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1199484539 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1199484538} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 113b9d20890f31f4d864c69586d8bda0, type: 3} + m_Name: + m_EditorClassIdentifier: + _anchorPrefab: {fileID: 3033127319783910676, guid: fb71847722300c943b4e2833b7d420b7, + type: 3} + _camera: {fileID: 1739816011} + _statusLog: {fileID: 1934137038} + _localizationStatus: {fileID: 1247875423} +--- !u!4 &1199484540 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1199484538} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 4.763476, y: -36.931152, z: 11.37677} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1247875422 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1247875425} + - component: {fileID: 1247875424} + - component: {fileID: 1247875423} + m_Layer: 5 + m_Name: Localization Status + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1247875423 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1247875422} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, 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_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 88 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 128 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: New Text +--- !u!222 &1247875424 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1247875422} + m_CullTransparentMesh: 1 +--- !u!224 &1247875425 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1247875422} + m_LocalRotation: {x: 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: 1413359792} + 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: 4, y: -188} + m_SizeDelta: {x: 1043.8, y: 114.9438} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &1390326250 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1390326253} + - component: {fileID: 1390326252} + - component: {fileID: 1390326251} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1390326251 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1390326250} + 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 &1390326252 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1390326250} + 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 &1390326253 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1390326250} + m_LocalRotation: {x: 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_RootOrder: 5 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1413359791 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1413359792} + - component: {fileID: 1413359794} + - component: {fileID: 1413359793} + m_Layer: 5 + m_Name: Panel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1413359792 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1413359791} + m_LocalRotation: {x: 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: 1934137040} + - {fileID: 1247875425} + m_Father: {fileID: 1861203857} + 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: -200} + m_SizeDelta: {x: 0, y: -1600} + m_Pivot: {x: 0.5, y: 1} +--- !u!114 &1413359793 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1413359791} + 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: 0.392} + 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 &1413359794 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1413359791} + m_CullTransparentMesh: 1 +--- !u!1 &1739816009 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1739816012} + - component: {fileID: 1739816011} + - component: {fileID: 1739816010} + - component: {fileID: 1739816014} + - component: {fileID: 1739816013} + 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 &1739816010 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1739816009} + m_Enabled: 1 +--- !u!20 &1739816011 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1739816009} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 2 + m_BackGroundColor: {r: 0, g: 0, b: 0, 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: 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 &1739816012 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1739816009} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -4.763476, y: 37.931152, z: -21.37677} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 840871076} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1739816013 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1739816009} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5d39c0b3c66c44c10b52d0b316fcdea5, type: 3} + m_Name: + m_EditorClassIdentifier: + _manageUsingUnityLifecycle: 1 + _renderTargetId: 0 + _camera: {fileID: 1739816011} + _targetTexture: {fileID: 0} +--- !u!114 &1739816014 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1739816009} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: da5ec3a3669946bf90ad10bf4ffab8a8, type: 3} + m_Name: + m_EditorClassIdentifier: + _camera: {fileID: 1739816011} +--- !u!1 &1861203853 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1861203857} + - component: {fileID: 1861203856} + - component: {fileID: 1861203855} + - component: {fileID: 1861203854} + m_Layer: 5 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1861203854 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1861203853} + 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 &1861203855 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1861203853} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, 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 + m_PresetInfoIsWorld: 0 +--- !u!223 &1861203856 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1861203853} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 1739816011} + 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 &1861203857 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1861203853} + 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: 1413359792} + - {fileID: 765630018} + - {fileID: 929200400} + - {fileID: 994113966} + - {fileID: 219042239} + - {fileID: 788970386} + - {fileID: 27369972} + m_Father: {fileID: 0} + 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, y: 0} +--- !u!1 &1874784640 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1874784642} + - component: {fileID: 1874784641} + 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 &1874784641 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1874784640} + m_Enabled: 1 + serializedVersion: 10 + m_Type: 1 + m_Shape: 0 + m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} + m_Intensity: 1 + 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: 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 &1874784642 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1874784640} + 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_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} +--- !u!1 &1934137037 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1934137040} + - component: {fileID: 1934137039} + - component: {fileID: 1934137038} + m_Layer: 5 + m_Name: Status Log + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1934137038 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1934137037} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, 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_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 85 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 135 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: New Text +--- !u!222 &1934137039 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1934137037} + m_CullTransparentMesh: 1 +--- !u!224 &1934137040 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1934137037} + m_LocalRotation: {x: 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: 1413359792} + 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: -4, y: 184} + m_SizeDelta: {x: 944.07, y: 114.9438} + m_Pivot: {x: 0.5, y: 0.5} diff --git a/Assets/Scenes/VPSCreate.unity.meta b/Assets/Scenes/VPSCreate.unity.meta new file mode 100644 index 0000000..f157bd4 --- /dev/null +++ b/Assets/Scenes/VPSCreate.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 9416b9171502e0e4e87f1802caef1483 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/VPSsearch.unity b/Assets/Scenes/VPSsearch.unity new file mode 100644 index 0000000..af08e52 --- /dev/null +++ b/Assets/Scenes/VPSsearch.unity @@ -0,0 +1,303 @@ +%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, 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: 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: 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 &596915340 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 596915343} + - component: {fileID: 596915342} + - component: {fileID: 596915341} + 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 &596915341 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 596915340} + m_Enabled: 1 +--- !u!20 &596915342 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 596915340} + 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_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: 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 &596915343 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 596915340} + 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_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1865540769 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1865540771} + - component: {fileID: 1865540770} + 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 &1865540770 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1865540769} + m_Enabled: 1 + serializedVersion: 10 + m_Type: 1 + m_Shape: 0 + m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} + m_Intensity: 1 + 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: 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 &1865540771 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1865540769} + 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_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} diff --git a/Assets/Scenes/VPSsearch.unity.meta b/Assets/Scenes/VPSsearch.unity.meta new file mode 100644 index 0000000..ed833d6 --- /dev/null +++ b/Assets/Scenes/VPSsearch.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 7fc50a6b4f982a94085782c09fa13a9f +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Stateholder.cs b/Assets/Stateholder.cs new file mode 100644 index 0000000..f76ab36 --- /dev/null +++ b/Assets/Stateholder.cs @@ -0,0 +1,8 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class Stateholder : MonoBehaviour +{ + public static int curr_poi; +} diff --git a/Assets/Stateholder.cs.meta b/Assets/Stateholder.cs.meta new file mode 100644 index 0000000..bf7b60d --- /dev/null +++ b/Assets/Stateholder.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e56d7afac598fae4b807edfc891f7a7b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 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.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/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/Ground - Logo Scene.mat b/Assets/TextMesh Pro/Examples & Extras/Materials/Ground - Logo Scene.mat new file mode 100644 index 0000000..580abd7 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Materials/Ground - Logo Scene.mat @@ -0,0 +1,105 @@ +%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 - Logo Scene + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ValidKeywords: + - _EMISSION + m_InvalidKeywords: [] + 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: 8b8c8a10edf94ddc8cc4cc4fcd5696a9, type: 3} + m_Scale: {x: 30, y: 50} + 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} + - _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: 1cdc5b506b1a4a33a53c30669ced1f51, type: 3} + m_Scale: {x: 20, y: 20} + 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: + - _Border: 0.021428574 + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DiffusePower: 1 + - _DstBlend: 0 + - _EdgeSoftness: 0 + - _EdgeWidth: 0 + - _EmissionScaleUI: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.344 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _Radius: 0 + - _Shininess: 0.22035475 + - _Size: 0.1 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _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: [] 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/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..de640e3 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Anton SDF.asset @@ -0,0 +1,297 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2140474 +Material: + serializedVersion: 6 + 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_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: 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_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} +--- !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: + hashCode: -1153031989 + material: {fileID: 2140474} + materialHashCode: -1064320757 + m_Version: 1.1.0 + m_SourceFontFileGUID: 997a43b767814dd0a7642ec9b78cba41 + m_SourceFontFile_EditorRef: {fileID: 12800000, guid: 997a43b767814dd0a7642ec9b78cba41, + type: 3} + m_SourceFontFile: {fileID: 12800000, guid: 997a43b767814dd0a7642ec9b78cba41, type: 3} + m_AtlasPopulationMode: 1 + m_FaceInfo: + m_FamilyName: Anton + m_StyleName: Regular + m_PointSize: 90 + m_Scale: 1 + 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_GlyphTable: [] + m_CharacterTable: [] + m_AtlasTextures: + - {fileID: 28933816116536082} + 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: 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 + atlas: {fileID: 0} + m_AtlasWidth: 1024 + m_AtlasHeight: 1024 + m_AtlasPadding: 9 + m_AtlasRenderMode: 4165 + m_glyphInfoList: [] + m_KerningTable: + kerningPairs: [] + m_FontFeatureTable: + m_GlyphPairAdjustmentRecords: [] + fallbackFontAssets: [] + m_FallbackFontAssetTable: [] + m_CreationSettings: + sourceFontFileName: + sourceFontFileGUID: 997a43b767814dd0a7642ec9b78cba41 + pointSizeSamplingMode: 1 + pointSize: 90 + padding: 9 + packingMode: 4 + atlasWidth: 1024 + atlasHeight: 1024 + characterSetSelectionMode: 6 + characterSequence: + referencedFontAssetGUID: 8a89fa14b10d46a99122fd4f73fca9a2 + 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 &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_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/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.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.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..6a5cab3 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Bangers SDF.asset @@ -0,0 +1,297 @@ +%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: + hashCode: 2134875903 + material: {fileID: 2100000} + materialHashCode: -2079879681 + m_Version: 1.1.0 + m_SourceFontFileGUID: 5dd49b3eacc540408c98eee0de38e0f1 + m_SourceFontFile_EditorRef: {fileID: 12800000, guid: 5dd49b3eacc540408c98eee0de38e0f1, + type: 3} + m_SourceFontFile: {fileID: 12800000, guid: 5dd49b3eacc540408c98eee0de38e0f1, type: 3} + m_AtlasPopulationMode: 1 + m_FaceInfo: + m_FamilyName: Bangers + m_StyleName: Regular + m_PointSize: 144 + m_Scale: 1 + 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_GlyphPairAdjustmentRecords: [] + fallbackFontAssets: [] + m_FallbackFontAssetTable: [] + m_CreationSettings: + sourceFontFileName: + sourceFontFileGUID: 5dd49b3eacc540408c98eee0de38e0f1 + pointSizeSamplingMode: 1 + pointSize: 144 + padding: 10 + 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..c8cb8e8 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Electronic Highway Sign SDF.asset @@ -0,0 +1,297 @@ +%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: + hashCode: 1023178945 + material: {fileID: 2140032} + materialHashCode: 225402433 + m_Version: 1.1.0 + m_SourceFontFileGUID: 8a2b9e2a607dd2143b58c44bc32410b4 + m_SourceFontFile_EditorRef: {fileID: 12800000, guid: 8a2b9e2a607dd2143b58c44bc32410b4, + type: 3} + m_SourceFontFile: {fileID: 12800000, guid: 8a2b9e2a607dd2143b58c44bc32410b4, type: 3} + m_AtlasPopulationMode: 1 + m_FaceInfo: + m_FamilyName: Electronic Highway Sign + m_StyleName: Regular + m_PointSize: 144 + m_Scale: 1 + 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_GlyphPairAdjustmentRecords: [] + fallbackFontAssets: [] + m_FallbackFontAssetTable: [] + m_CreationSettings: + sourceFontFileName: + sourceFontFileGUID: 8a2b9e2a607dd2143b58c44bc32410b4 + pointSizeSamplingMode: 1 + pointSize: 144 + padding: 10 + 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..dd07539 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Oswald Bold SDF.asset @@ -0,0 +1,297 @@ +%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.8333333 + - _ScaleRatioB: 0.6770833 + - _ScaleRatioC: 0.6770833 + - _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: + hashCode: 1490843414 + material: {fileID: 2147374} + materialHashCode: 1112331510 + m_Version: 1.1.0 + m_SourceFontFileGUID: c9f6d0e7bc8541498c9a4799ba184ede + m_SourceFontFile_EditorRef: {fileID: 12800000, guid: c9f6d0e7bc8541498c9a4799ba184ede, + type: 3} + m_SourceFontFile: {fileID: 12800000, guid: c9f6d0e7bc8541498c9a4799ba184ede, type: 3} + m_AtlasPopulationMode: 1 + m_FaceInfo: + m_FamilyName: Oswald + m_StyleName: Bold + m_PointSize: 90 + m_Scale: 1 + 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_GlyphPairAdjustmentRecords: [] + fallbackFontAssets: [] + m_FallbackFontAssetTable: [] + m_CreationSettings: + sourceFontFileName: + sourceFontFileGUID: c9f6d0e7bc8541498c9a4799ba184ede + pointSizeSamplingMode: 1 + pointSize: 90 + padding: 9 + 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 - 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.asset b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Roboto-Bold SDF.asset new file mode 100644 index 0000000..aa6869b --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Resources/Fonts & Materials/Roboto-Bold SDF.asset @@ -0,0 +1,297 @@ +%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: + hashCode: -635320526 + material: {fileID: 2164040} + materialHashCode: -1838732846 + m_Version: 1.1.0 + m_SourceFontFileGUID: 4beb055f07aaff244873dec698d0363e + m_SourceFontFile_EditorRef: {fileID: 12800000, guid: 4beb055f07aaff244873dec698d0363e, + type: 3} + m_SourceFontFile: {fileID: 12800000, guid: 4beb055f07aaff244873dec698d0363e, type: 3} + m_AtlasPopulationMode: 1 + m_FaceInfo: + m_FamilyName: Roboto + m_StyleName: Bold + m_PointSize: 90 + m_Scale: 1 + 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_GlyphPairAdjustmentRecords: [] + fallbackFontAssets: [] + m_FallbackFontAssetTable: [] + m_CreationSettings: + sourceFontFileName: + sourceFontFileGUID: 4beb055f07aaff244873dec698d0363e + pointSizeSamplingMode: 1 + pointSize: 90 + padding: 9 + 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/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..3a27355 --- /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: 0 + 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..9b23df2 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scenes/12a - Text Interactions.unity @@ -0,0 +1,887 @@ +%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_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: 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: + - {fileID: 1744362547} + 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 &1744362543 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1744362547} + - component: {fileID: 1744362545} + - component: {fileID: 1744362546} + 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 &1744362545 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1744362543} + m_Mesh: {fileID: 0} +--- !u!23 &1744362546 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1744362543} + 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 &1744362547 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1744362543} + m_LocalRotation: {x: 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: 1647263053} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !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_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: 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.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/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..b48ebbd --- /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.enableWordWrapping = false; + //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..29d75b6 --- /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.enableKerning = false; + + 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..e56714d --- /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.enableWordWrapping = false; + 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..f7e33fe --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/ObjectSpin.cs @@ -0,0 +1,69 @@ +using UnityEngine; +using System.Collections; + + +namespace TMPro.Examples +{ + + public class ObjectSpin : MonoBehaviour + { + +#pragma warning disable 0414 + + 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; + private int frames = 0; + + public enum MotionType { Rotation, BackAndForth, Translation }; + public MotionType Motion; + + 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() + { + if (Motion == MotionType.Rotation) + { + m_transform.Rotate(0, SpinSpeed * Time.deltaTime, 0); + } + else if (Motion == MotionType.BackAndForth) + { + 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); + } + else + { + m_time += SpinSpeed * Time.deltaTime; + + float x = 15 * Mathf.Cos(m_time * .95f); + float y = 10; // *Mathf.Sin(m_time * 1f) * Mathf.Cos(m_time * 1f); + float z = 0f; // *Mathf.Sin(m_time * .9f); + + m_transform.position = m_initial_Position + new Vector3(x, z, y); + + // Drawing light patterns because they can be cool looking. + //if (frames > 2) + // Debug.DrawLine(m_transform.position, m_prevPOS, m_lightColor, 100f); + + m_prevPOS = m_transform.position; + frames += 1; + } + } + } +} \ 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..1c71c48 --- /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.enableWordWrapping = false; + + //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..4a858b5 --- /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.enableWordWrapping = false; + 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..505bf64 --- /dev/null +++ b/Assets/TextMesh Pro/Examples & Extras/Scripts/TMP_TextEventHandler.cs @@ -0,0 +1,254 @@ +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 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..e41fbfa --- /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 + Vector2[] src_uv0s = m_cachedMeshInfoVertexData[materialIndex].uvs0; + Vector2[] 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..586e8be --- /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.enableWordWrapping = false; + 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..0d94197 --- /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.enableWordWrapping = true; + 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..f961113 --- /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.enableKerning = false; + 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..c4973fb --- /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 + Vector2[] sourceUVs0 = cachedMeshInfoVertexData[materialIndex].uvs0; + Vector2[] 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.uv = 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..e907cc7 --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Fallback.asset @@ -0,0 +1,343 @@ +%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: + - _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_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.90909094 + - _ScaleRatioB: 0.73125 + - _ScaleRatioC: 0.7386364 + - _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} +--- !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: + hashCode: -1699145518 + material: {fileID: 2180264} + materialHashCode: 462855346 + m_Version: 1.1.0 + m_SourceFontFileGUID: e3265ab4bf004d28a9537516768c1c75 + m_SourceFontFile_EditorRef: {fileID: 12800000, guid: e3265ab4bf004d28a9537516768c1c75, + type: 3} + m_SourceFontFile: {fileID: 12800000, guid: e3265ab4bf004d28a9537516768c1c75, type: 3} + m_AtlasPopulationMode: 1 + 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_CharacterTable: [] + m_AtlasTextures: + - {fileID: 28268798066460806} + m_AtlasTextureIndex: 0 + m_IsMultiAtlasTexturesEnabled: 0 + m_ClearDynamicDataOnBuild: 1 + m_UsedGlyphRects: [] + m_FreeGlyphRects: + - m_X: 0 + m_Y: 0 + m_Width: 511 + m_Height: 511 + 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: 512 + m_AtlasHeight: 512 + m_AtlasPadding: 9 + m_AtlasRenderMode: 4169 + m_glyphInfoList: [] + m_KerningTable: + kerningPairs: [] + m_FontFeatureTable: + m_GlyphPairAdjustmentRecords: [] + fallbackFontAssets: [] + m_FallbackFontAssetTable: [] + m_CreationSettings: + sourceFontFileName: + sourceFontFileGUID: e3265ab4bf004d28a9537516768c1c75 + pointSizeSamplingMode: 0 + pointSize: 86 + padding: 9 + 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_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 &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_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/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..ceb609b --- /dev/null +++ b/Assets/TextMesh Pro/Resources/Style Sheets/Default Style Sheet.asset @@ -0,0 +1,68 @@ +%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: ab2114bdc8544297b417dfefe9f1e410, type: 3} + m_Name: Default Style Sheet + m_EditorClassIdentifier: + m_StyleList: + - m_Name: H1 + m_HashCode: 2425 + m_OpeningDefinition: <#40ff80>* + m_ClosingDefinition: '*' + m_OpeningTagArray: 3c00000073000000690000007a000000650000003d00000032000000650000006d0000003e0000003c000000620000003e0000003c000000230000003400000030000000660000006600000038000000300000003e0000002a000000 + m_ClosingTagArray: 2a0000003c0000002f00000073000000690000007a000000650000003e0000003c0000002f000000620000003e0000003c0000002f000000630000006f0000006c0000006f000000720000003e000000 + - m_Name: Quote + m_HashCode: 92254330 + m_OpeningDefinition: + m_ClosingDefinition: + m_OpeningTagArray: 3c000000690000003e0000003c00000073000000690000007a000000650000003d0000003700000035000000250000003e0000003c0000006d000000610000007200000067000000690000006e0000003d0000003100000030000000250000003e000000 + m_ClosingTagArray: 3c0000002f000000690000003e0000003c0000002f00000073000000690000007a000000650000003e0000003c0000002f00000077000000690000006400000074000000680000003e0000003c0000002f0000006d000000610000007200000067000000690000006e0000003e000000 + - m_Name: Link + m_HashCode: 2687968 + m_OpeningDefinition: <#40a0ff> + m_ClosingDefinition: + m_OpeningTagArray: 3c000000750000003e0000003c000000230000003400000030000000610000003000000066000000660000003e0000003c0000006c000000690000006e0000006b0000003d0000002200000049000000440000005f0000003000000031000000220000003e000000 + m_ClosingTagArray: 3c0000002f000000750000003e0000003c0000002f000000630000006f0000006c0000006f000000720000003e0000003c0000002f0000006c000000690000006e0000006b0000003e000000 + - m_Name: Title + m_HashCode: 98732960 + 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..c09a92f --- /dev/null +++ b/Assets/TextMesh Pro/Resources/TMP Settings.asset @@ -0,0 +1,46 @@ +%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: + m_enableWordWrapping: 1 + m_enableKerning: 1 + m_enableExtraPadding: 0 + m_enableTintAllSprites: 0 + m_enableParseEscapeCharacters: 1 + m_EnableRaycastTarget: 1 + m_GetFontFeaturesAtRuntime: 1 + m_missingGlyphCharacter: 0 + 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_fallbackFontAssets: [] + m_matchMaterialPreset: 1 + m_defaultSpriteAsset: {fileID: 11400000, guid: c41005c129ba4d66911b75229fd70b45, + type: 2} + m_defaultSpriteAssetPath: Sprite Assets/ + m_enableEmojiSupport: 1 + m_MissingCharacterSpriteUnicode: 0 + 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/TMP_Bitmap-Custom-Atlas.shader b/Assets/TextMesh Pro/Shaders/TMP_Bitmap-Custom-Atlas.shader new file mode 100644 index 0000000..bab2b2c --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_Bitmap-Custom-Atlas.shader @@ -0,0 +1,143 @@ +Shader "TextMeshPro/Bitmap Custom Atlas" { + +Properties { + _MainTex ("Font Atlas", 2D) = "white" {} + _FaceTex ("Font Texture", 2D) = "white" {} + [HDR]_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" + + struct appdata_t { + float4 vertex : POSITION; + fixed4 color : COLOR; + float2 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; + + float2 UnpackUV(float uv) + { + float2 output; + output.x = floor(uv / 4096); + output.y = uv - 4096 * output.x; + + return output * 0.001953125; + } + + 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)); + + fixed4 faceColor = v.color; + faceColor *= _FaceColor; + + v2f OUT; + OUT.vertex = vPosition; + OUT.color = faceColor; + OUT.texcoord0 = v.texcoord0; + OUT.texcoord1 = TRANSFORM_TEX(UnpackUV(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. + float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + OUT.mask = float4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + 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..006a271 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_Bitmap-Mobile.shader @@ -0,0 +1,145 @@ +Shader "TextMeshPro/Mobile/Bitmap" { + +Properties { + _MainTex ("Font Atlas", 2D) = "white" {} + [HDR]_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" + + 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; + + 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; + + 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. + float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + OUT.mask = float4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + 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..8ce4937 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_Bitmap.shader @@ -0,0 +1,143 @@ +Shader "TextMeshPro/Bitmap" { + +Properties { + _MainTex ("Font Atlas", 2D) = "white" {} + _FaceTex ("Font Texture", 2D) = "white" {} + [HDR]_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" + + struct appdata_t { + float4 vertex : POSITION; + fixed4 color : COLOR; + float2 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; + + float2 UnpackUV(float uv) + { + float2 output; + output.x = floor(uv / 4096); + output.y = uv - 4096 * output.x; + + return output * 0.001953125; + } + + 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)); + + fixed4 faceColor = v.color; + faceColor *= _FaceColor; + + v2f OUT; + OUT.vertex = vPosition; + OUT.color = faceColor; + OUT.texcoord0 = v.texcoord0; + OUT.texcoord1 = TRANSFORM_TEX(UnpackUV(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. + float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + OUT.mask = float4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + 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..c50c593 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF Overlay.shader @@ -0,0 +1,317 @@ +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 + [HDR]_FaceColor ("Face Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + [HDR]_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 + [HDR]_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) + + + [HDR]_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 + + [HDR]_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; + float2 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; + + 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.texcoord1.y, 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.texcoord1.y) * _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 = UnpackUV(input.texcoord1.x); + float2 faceUV = TRANSFORM_TEX(textureUV, _FaceTex); + float2 outlineUV = TRANSFORM_TEX(textureUV, _OutlineTex); + + + output.position = vPosition; + output.color = input.color; + output.atlas = input.texcoord0; + output.param = float4(alphaClip, scale, bias, weight); + output.mask = half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + 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..ed48574 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF SSD.shader @@ -0,0 +1,310 @@ +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 + [HDR]_FaceColor ("Face Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + [HDR]_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 + [HDR]_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) + + + [HDR]_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 + + [HDR]_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; + float2 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; + + 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.texcoord1.y, 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 = UnpackUV(input.texcoord1.x); + float2 faceUV = TRANSFORM_TEX(textureUV, _FaceTex); + float2 outlineUV = TRANSFORM_TEX(textureUV, _OutlineTex); + + 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; + + float2 pixelSize = float2(ddx(input.atlas.y), ddy(input.atlas.y)); + pixelSize *= _TextureWidth * .75; + float scale = rsqrt(dot(pixelSize, 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 + float2 maskZW = 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + (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-Mobile Masking.shader b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile Masking.shader new file mode 100644 index 0000000..7019aaf --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile Masking.shader @@ -0,0 +1,247 @@ +// 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 { + [HDR]_FaceColor ("Face Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + [HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineWidth ("Outline Thickness", Range(0,1)) = 0 + _OutlineSoftness ("Outline Softness", Range(0,1)) = 0 + + [HDR]_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; + float2 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; + + pixel_t VertShader(vertex_t input) + { + float bold = step(input.texcoord1.y, 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.texcoord1.y) * _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; + + 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); + + // 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 * half2(_MaskSoftnessX, _MaskSoftnessY) + 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..ce82bed --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile Overlay.shader @@ -0,0 +1,240 @@ +// 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 { + [HDR]_FaceColor ("Face Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + [HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineWidth ("Outline Thickness", Range(0,1)) = 0 + _OutlineSoftness ("Outline Softness", Range(0,1)) = 0 + + [HDR]_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; + float2 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 + }; + + + 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.texcoord1.y, 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.texcoord1.y) * _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; + + 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); + output.mask = half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + 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..df4d5b0 --- /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 { + [HDR]_FaceColor ("Face Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + [HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineWidth ("Outline Thickness", Range(0,1)) = 0 + _OutlineSoftness ("Outline Softness", Range(0,1)) = 0 + + [HDR]_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.shader b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile.shader new file mode 100644 index 0000000..d3f5866 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile.shader @@ -0,0 +1,240 @@ +// 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 { + [HDR]_FaceColor ("Face Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + [HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineWidth ("Outline Thickness", Range(0,1)) = 0 + _OutlineSoftness ("Outline Softness", Range(0,1)) = 0 + + [HDR]_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 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; + float2 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 + }; + + + 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.texcoord1.y, 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.texcoord1.y) * _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; + + 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); + output.mask = half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + 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..be764ae --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-Surface-Mobile.shader @@ -0,0 +1,138 @@ +// 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" {} + [HDR]_FaceColor ("Fill Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + [HDR]_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 + + [HDR]_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..bcb2bb2 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-Surface.shader @@ -0,0 +1,158 @@ +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 + [HDR]_FaceColor ("Fill Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + [HDR]_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) + [HDR]_SpecColor ("Specular Color", Color) = (0,0,0,1) + + _FaceShininess ("Face Shininess", Range(0,1)) = 0 + _OutlineShininess ("Outline Shininess", Range(0,1)) = 0 + + [HDR]_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.shader b/Assets/TextMesh Pro/Shaders/TMP_SDF.shader new file mode 100644 index 0000000..011ee19 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF.shader @@ -0,0 +1,317 @@ +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 + [HDR]_FaceColor ("Face Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + [HDR]_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 + [HDR]_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) + + + [HDR]_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 + + [HDR]_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; + float2 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; + + 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.texcoord1.y, 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.texcoord1.y) * _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 = UnpackUV(input.texcoord1.x); + float2 faceUV = TRANSFORM_TEX(textureUV, _FaceTex); + float2 outlineUV = TRANSFORM_TEX(textureUV, _OutlineTex); + + + output.position = vPosition; + output.color = input.color; + output.atlas = input.texcoord0; + output.param = float4(alphaClip, scale, bias, weight); + output.mask = half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + 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..e8283a7 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_Sprite.shader @@ -0,0 +1,116 @@ +Shader "TextMeshPro/Sprite" +{ + Properties + { + [PerRendererData] _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; + UNITY_VERTEX_OUTPUT_STEREO + }; + + sampler2D _MainTex; + fixed4 _Color; + fixed4 _TextureSampleAdd; + float4 _ClipRect; + float4 _MainTex_ST; + + v2f vert(appdata_t v) + { + v2f OUT; + UNITY_SETUP_INSTANCE_ID(v); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT); + OUT.worldPosition = v.vertex; + OUT.vertex = UnityObjectToClipPos(OUT.worldPosition); + + OUT.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex); + + OUT.color = v.color * _Color; + return OUT; + } + + fixed4 frag(v2f IN) : SV_Target + { + half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color; + + #ifdef UNITY_UI_CLIP_RECT + color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect); + #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..0d6eb56 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMPro.cginc.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 407bc68d299748449bbf7f48ee690f8d +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + 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..5969fec --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMPro_Mobile.cginc @@ -0,0 +1,157 @@ +struct vertex_t { + UNITY_VERTEX_INPUT_INSTANCE_ID + float4 position : POSITION; + float3 normal : NORMAL; + float4 color : COLOR; + float2 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; // weight, scaleRatio + 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); +} + +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.texcoord1.y, 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, 1.3333 * _GradientScale * (_Sharpness + 1) / _TextureWidth, _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; + + float2 UV = input.texcoord0.xy; + float scale = rsqrt(abs(ddx(UV.x) * ddy(UV.y) - ddy(UV.x) * ddx(UV.y))) * input.param.y; + + #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); + + #ifdef 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 + + #ifdef 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 + float2 maskZW = 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + (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..2e96258 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMPro_Properties.cginc @@ -0,0 +1,85 @@ +// 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 _MaskWipeControl; +//uniform float _MaskEdgeSoftness; +//uniform fixed4 _MaskEdgeColor; +//uniform bool _MaskInverse; + +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..622ae87 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMPro_Surface.cginc @@ -0,0 +1,101 @@ +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.texcoord1.y, 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.texcoord1.y) * _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; // + + v.texcoord1.xy = UnpackUV(v.texcoord1.x); + 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/TutorialInfo.meta b/Assets/TutorialInfo.meta new file mode 100644 index 0000000..5118e87 --- /dev/null +++ b/Assets/TutorialInfo.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 034b93559619c664583bc87483b771f6 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TutorialInfo/Icons.meta b/Assets/TutorialInfo/Icons.meta new file mode 100644 index 0000000..1d19fb9 --- /dev/null +++ b/Assets/TutorialInfo/Icons.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 8a0c9218a650547d98138cd835033977 +folderAsset: yes +timeCreated: 1484670163 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TutorialInfo/Icons/Help_Icon.png b/Assets/TutorialInfo/Icons/Help_Icon.png new file mode 100644 index 0000000..91fa215 Binary files /dev/null and b/Assets/TutorialInfo/Icons/Help_Icon.png differ diff --git a/Assets/TutorialInfo/Icons/Help_Icon.png.meta b/Assets/TutorialInfo/Icons/Help_Icon.png.meta new file mode 100644 index 0000000..86cc13a --- /dev/null +++ b/Assets/TutorialInfo/Icons/Help_Icon.png.meta @@ -0,0 +1,128 @@ +fileFormatVersion: 2 +guid: 9266273b8f123004195741f969177dda +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 5 + 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 + 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: 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: 2 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 2 + buildTarget: DefaultTexturePlatform + maxTextureSize: 8192 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Standalone + maxTextureSize: 8192 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: iPhone + maxTextureSize: 8192 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Android + maxTextureSize: 8192 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Windows Store Apps + maxTextureSize: 8192 + 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: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TutorialInfo/Icons/Mobile 3D.png b/Assets/TutorialInfo/Icons/Mobile 3D.png new file mode 100644 index 0000000..6a0a7b0 Binary files /dev/null and b/Assets/TutorialInfo/Icons/Mobile 3D.png differ diff --git a/Assets/TutorialInfo/Icons/Mobile 3D.png.meta b/Assets/TutorialInfo/Icons/Mobile 3D.png.meta new file mode 100644 index 0000000..ce049ce --- /dev/null +++ b/Assets/TutorialInfo/Icons/Mobile 3D.png.meta @@ -0,0 +1,122 @@ +fileFormatVersion: 2 +guid: cbea0258d69fdef4ba73fa582f0e2004 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 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: 1 + aniso: 1 + mipBias: 0 + wrapU: 0 + wrapV: 0 + wrapW: 0 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + 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 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: 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/TutorialInfo/Layout.wlt b/Assets/TutorialInfo/Layout.wlt new file mode 100644 index 0000000..7b50a25 --- /dev/null +++ b/Assets/TutorialInfo/Layout.wlt @@ -0,0 +1,654 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &1 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12004, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_PixelRect: + serializedVersion: 2 + x: 0 + y: 45 + width: 1666 + height: 958 + m_ShowMode: 4 + m_Title: + m_RootView: {fileID: 6} + m_MinSize: {x: 950, y: 542} + m_MaxSize: {x: 10000, y: 10000} +--- !u!114 &2 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_Children: [] + m_Position: + serializedVersion: 2 + x: 0 + y: 466 + width: 290 + height: 442 + m_MinSize: {x: 234, y: 271} + m_MaxSize: {x: 10004, y: 10021} + m_ActualView: {fileID: 14} + m_Panes: + - {fileID: 14} + m_Selected: 0 + m_LastSelected: 0 +--- !u!114 &3 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12010, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_Children: + - {fileID: 4} + - {fileID: 2} + m_Position: + serializedVersion: 2 + x: 973 + y: 0 + width: 290 + height: 908 + m_MinSize: {x: 234, y: 492} + m_MaxSize: {x: 10004, y: 14042} + vertical: 1 + controlID: 226 +--- !u!114 &4 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_Children: [] + m_Position: + serializedVersion: 2 + x: 0 + y: 0 + width: 290 + height: 466 + m_MinSize: {x: 204, y: 221} + m_MaxSize: {x: 4004, y: 4021} + m_ActualView: {fileID: 17} + m_Panes: + - {fileID: 17} + m_Selected: 0 + m_LastSelected: 0 +--- !u!114 &5 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_Children: [] + m_Position: + serializedVersion: 2 + x: 0 + y: 466 + width: 973 + height: 442 + m_MinSize: {x: 202, y: 221} + m_MaxSize: {x: 4002, y: 4021} + m_ActualView: {fileID: 15} + m_Panes: + - {fileID: 15} + m_Selected: 0 + m_LastSelected: 0 +--- !u!114 &6 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12008, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_Children: + - {fileID: 7} + - {fileID: 8} + - {fileID: 9} + m_Position: + serializedVersion: 2 + x: 0 + y: 0 + width: 1666 + height: 958 + m_MinSize: {x: 950, y: 542} + m_MaxSize: {x: 10000, y: 10000} +--- !u!114 &7 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12011, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_Children: [] + m_Position: + serializedVersion: 2 + x: 0 + y: 0 + width: 1666 + height: 30 + m_MinSize: {x: 0, y: 0} + m_MaxSize: {x: 0, y: 0} + m_LastLoadedLayoutName: Tutorial +--- !u!114 &8 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12010, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_Children: + - {fileID: 10} + - {fileID: 3} + - {fileID: 11} + m_Position: + serializedVersion: 2 + x: 0 + y: 30 + width: 1666 + height: 908 + m_MinSize: {x: 713, y: 492} + m_MaxSize: {x: 18008, y: 14042} + vertical: 0 + controlID: 74 +--- !u!114 &9 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12042, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_Children: [] + m_Position: + serializedVersion: 2 + x: 0 + y: 938 + width: 1666 + height: 20 + m_MinSize: {x: 0, y: 0} + m_MaxSize: {x: 0, y: 0} +--- !u!114 &10 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12010, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_Children: + - {fileID: 12} + - {fileID: 5} + m_Position: + serializedVersion: 2 + x: 0 + y: 0 + width: 973 + height: 908 + m_MinSize: {x: 202, y: 442} + m_MaxSize: {x: 4002, y: 8042} + vertical: 1 + controlID: 75 +--- !u!114 &11 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_Children: [] + m_Position: + serializedVersion: 2 + x: 1263 + y: 0 + width: 403 + height: 908 + m_MinSize: {x: 277, y: 71} + m_MaxSize: {x: 4002, y: 4021} + m_ActualView: {fileID: 13} + m_Panes: + - {fileID: 13} + m_Selected: 0 + m_LastSelected: 0 +--- !u!114 &12 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_Children: [] + m_Position: + serializedVersion: 2 + x: 0 + y: 0 + width: 973 + height: 466 + m_MinSize: {x: 202, y: 221} + m_MaxSize: {x: 4002, y: 4021} + m_ActualView: {fileID: 16} + m_Panes: + - {fileID: 16} + m_Selected: 0 + m_LastSelected: 0 +--- !u!114 &13 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12019, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_AutoRepaintOnSceneChange: 0 + m_MinSize: {x: 275, y: 50} + m_MaxSize: {x: 4000, y: 4000} + m_TitleContent: + m_Text: Inspector + m_Image: {fileID: -6905738622615590433, guid: 0000000000000000d000000000000000, + type: 0} + m_Tooltip: + m_DepthBufferBits: 0 + m_Pos: + serializedVersion: 2 + x: 2 + y: 19 + width: 401 + height: 887 + m_ScrollPosition: {x: 0, y: 0} + m_InspectorMode: 0 + m_PreviewResizer: + m_CachedPref: -160 + m_ControlHash: -371814159 + m_PrefName: Preview_InspectorPreview + m_PreviewWindow: {fileID: 0} +--- !u!114 &14 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12014, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_AutoRepaintOnSceneChange: 0 + m_MinSize: {x: 230, y: 250} + m_MaxSize: {x: 10000, y: 10000} + m_TitleContent: + m_Text: Project + m_Image: {fileID: -7501376956915960154, guid: 0000000000000000d000000000000000, + type: 0} + m_Tooltip: + m_DepthBufferBits: 0 + m_Pos: + serializedVersion: 2 + x: 2 + y: 19 + width: 286 + height: 421 + m_SearchFilter: + m_NameFilter: + m_ClassNames: [] + m_AssetLabels: [] + m_AssetBundleNames: [] + m_VersionControlStates: [] + m_ReferencingInstanceIDs: + m_ScenePaths: [] + m_ShowAllHits: 0 + m_SearchArea: 0 + m_Folders: + - Assets + m_ViewMode: 0 + m_StartGridSize: 64 + m_LastFolders: + - Assets + m_LastFoldersGridSize: -1 + m_LastProjectPath: /Users/danielbrauer/Unity Projects/New Unity Project 47 + m_IsLocked: 0 + m_FolderTreeState: + scrollPos: {x: 0, y: 0} + m_SelectedIDs: ee240000 + m_LastClickedID: 9454 + m_ExpandedIDs: ee24000000ca9a3bffffff7f + m_RenameOverlay: + m_UserAcceptedRename: 0 + m_Name: + m_OriginalName: + m_EditFieldRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + m_UserData: 0 + m_IsWaitingForDelay: 0 + m_IsRenaming: 0 + m_OriginalEventType: 11 + m_IsRenamingFilename: 1 + m_ClientGUIView: {fileID: 0} + m_SearchString: + m_CreateAssetUtility: + m_EndAction: {fileID: 0} + m_InstanceID: 0 + m_Path: + m_Icon: {fileID: 0} + m_ResourceFile: + m_AssetTreeState: + scrollPos: {x: 0, y: 0} + m_SelectedIDs: 68fbffff + m_LastClickedID: 0 + m_ExpandedIDs: ee240000 + m_RenameOverlay: + m_UserAcceptedRename: 0 + m_Name: + m_OriginalName: + m_EditFieldRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + m_UserData: 0 + m_IsWaitingForDelay: 0 + m_IsRenaming: 0 + m_OriginalEventType: 11 + m_IsRenamingFilename: 1 + m_ClientGUIView: {fileID: 0} + m_SearchString: + m_CreateAssetUtility: + m_EndAction: {fileID: 0} + m_InstanceID: 0 + m_Path: + m_Icon: {fileID: 0} + m_ResourceFile: + m_ListAreaState: + m_SelectedInstanceIDs: 68fbffff + m_LastClickedInstanceID: -1176 + m_HadKeyboardFocusLastEvent: 0 + m_ExpandedInstanceIDs: c6230000 + m_RenameOverlay: + m_UserAcceptedRename: 0 + m_Name: + m_OriginalName: + m_EditFieldRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + m_UserData: 0 + m_IsWaitingForDelay: 0 + m_IsRenaming: 0 + m_OriginalEventType: 11 + m_IsRenamingFilename: 1 + m_ClientGUIView: {fileID: 0} + m_CreateAssetUtility: + m_EndAction: {fileID: 0} + m_InstanceID: 0 + m_Path: + m_Icon: {fileID: 0} + m_ResourceFile: + m_NewAssetIndexInList: -1 + m_ScrollPosition: {x: 0, y: 0} + m_GridSize: 64 + m_DirectoriesAreaWidth: 110 +--- !u!114 &15 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12015, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_AutoRepaintOnSceneChange: 1 + m_MinSize: {x: 200, y: 200} + m_MaxSize: {x: 4000, y: 4000} + m_TitleContent: + m_Text: Game + m_Image: {fileID: -2087823869225018852, guid: 0000000000000000d000000000000000, + type: 0} + m_Tooltip: + m_DepthBufferBits: 32 + m_Pos: + serializedVersion: 2 + x: 0 + y: 19 + width: 971 + height: 421 + m_MaximizeOnPlay: 0 + m_Gizmos: 0 + m_Stats: 0 + m_SelectedSizes: 00000000000000000000000000000000000000000000000000000000000000000000000000000000 + m_TargetDisplay: 0 + m_ZoomArea: + m_HRangeLocked: 0 + m_VRangeLocked: 0 + m_HBaseRangeMin: -242.75 + m_HBaseRangeMax: 242.75 + m_VBaseRangeMin: -101 + m_VBaseRangeMax: 101 + m_HAllowExceedBaseRangeMin: 1 + m_HAllowExceedBaseRangeMax: 1 + m_VAllowExceedBaseRangeMin: 1 + m_VAllowExceedBaseRangeMax: 1 + m_ScaleWithWindow: 0 + m_HSlider: 0 + m_VSlider: 0 + m_IgnoreScrollWheelUntilClicked: 0 + m_EnableMouseInput: 1 + m_EnableSliderZoom: 0 + m_UniformScale: 1 + m_UpDirection: 1 + m_DrawArea: + serializedVersion: 2 + x: 0 + y: 17 + width: 971 + height: 404 + m_Scale: {x: 2, y: 2} + m_Translation: {x: 485.5, y: 202} + m_MarginLeft: 0 + m_MarginRight: 0 + m_MarginTop: 0 + m_MarginBottom: 0 + m_LastShownAreaInsideMargins: + serializedVersion: 2 + x: -242.75 + y: -101 + width: 485.5 + height: 202 + m_MinimalGUI: 1 + m_defaultScale: 2 + m_TargetTexture: {fileID: 0} + m_CurrentColorSpace: 0 + m_LastWindowPixelSize: {x: 1942, y: 842} + m_ClearInEditMode: 1 + m_NoCameraWarning: 1 + m_LowResolutionForAspectRatios: 01000000000100000100 +--- !u!114 &16 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12013, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_AutoRepaintOnSceneChange: 1 + m_MinSize: {x: 200, y: 200} + m_MaxSize: {x: 4000, y: 4000} + m_TitleContent: + m_Text: Scene + m_Image: {fileID: 2318424515335265636, guid: 0000000000000000d000000000000000, + type: 0} + m_Tooltip: + m_DepthBufferBits: 32 + m_Pos: + serializedVersion: 2 + x: 0 + y: 19 + width: 971 + height: 445 + m_SceneLighting: 1 + lastFramingTime: 0 + m_2DMode: 0 + m_isRotationLocked: 0 + m_AudioPlay: 0 + m_Position: + m_Target: {x: 0, y: 0, z: 0} + speed: 2 + m_Value: {x: 0, y: 0, z: 0} + m_RenderMode: 0 + m_ValidateTrueMetals: 0 + m_SceneViewState: + showFog: 1 + showMaterialUpdate: 0 + showSkybox: 1 + showFlares: 1 + showImageEffects: 1 + grid: + xGrid: + m_Target: 0 + speed: 2 + m_Value: 0 + yGrid: + m_Target: 1 + speed: 2 + m_Value: 1 + zGrid: + m_Target: 0 + speed: 2 + m_Value: 0 + m_Rotation: + m_Target: {x: -0.08717229, y: 0.89959055, z: -0.21045254, w: -0.3726226} + speed: 2 + m_Value: {x: -0.08717229, y: 0.89959055, z: -0.21045254, w: -0.3726226} + m_Size: + m_Target: 10 + speed: 2 + m_Value: 10 + m_Ortho: + m_Target: 0 + speed: 2 + m_Value: 0 + m_LastSceneViewRotation: {x: 0, y: 0, z: 0, w: 0} + m_LastSceneViewOrtho: 0 + m_ReplacementShader: {fileID: 0} + m_ReplacementString: + m_LastLockedObject: {fileID: 0} + m_ViewIsLockedToObject: 0 +--- !u!114 &17 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12061, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_AutoRepaintOnSceneChange: 0 + m_MinSize: {x: 200, y: 200} + m_MaxSize: {x: 4000, y: 4000} + m_TitleContent: + m_Text: Hierarchy + m_Image: {fileID: -590624980919486359, guid: 0000000000000000d000000000000000, + type: 0} + m_Tooltip: + m_DepthBufferBits: 0 + m_Pos: + serializedVersion: 2 + x: 2 + y: 19 + width: 286 + height: 445 + m_TreeViewState: + scrollPos: {x: 0, y: 0} + m_SelectedIDs: 68fbffff + m_LastClickedID: -1176 + m_ExpandedIDs: 7efbffff00000000 + m_RenameOverlay: + m_UserAcceptedRename: 0 + m_Name: + m_OriginalName: + m_EditFieldRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + m_UserData: 0 + m_IsWaitingForDelay: 0 + m_IsRenaming: 0 + m_OriginalEventType: 11 + m_IsRenamingFilename: 0 + m_ClientGUIView: {fileID: 0} + m_SearchString: + m_ExpandedScenes: + - + m_CurrenRootInstanceID: 0 + m_Locked: 0 + m_CurrentSortingName: TransformSorting diff --git a/Assets/TutorialInfo/Layout.wlt.meta b/Assets/TutorialInfo/Layout.wlt.meta new file mode 100644 index 0000000..92800c6 --- /dev/null +++ b/Assets/TutorialInfo/Layout.wlt.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 96e98bffd05413f489cd9851fc862d1f +timeCreated: 1487337779 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TutorialInfo/Scripts.meta b/Assets/TutorialInfo/Scripts.meta new file mode 100644 index 0000000..02da605 --- /dev/null +++ b/Assets/TutorialInfo/Scripts.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 5a9bcd70e6a4b4b05badaa72e827d8e0 +folderAsset: yes +timeCreated: 1475835190 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TutorialInfo/Scripts/Editor.meta b/Assets/TutorialInfo/Scripts/Editor.meta new file mode 100644 index 0000000..f59f099 --- /dev/null +++ b/Assets/TutorialInfo/Scripts/Editor.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 3ad9b87dffba344c89909c6d1b1c17e1 +folderAsset: yes +timeCreated: 1475593892 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TutorialInfo/Scripts/Editor/ReadmeEditor.cs b/Assets/TutorialInfo/Scripts/Editor/ReadmeEditor.cs new file mode 100644 index 0000000..ad55eca --- /dev/null +++ b/Assets/TutorialInfo/Scripts/Editor/ReadmeEditor.cs @@ -0,0 +1,242 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; +using System; +using System.IO; +using System.Reflection; + +[CustomEditor(typeof(Readme))] +[InitializeOnLoad] +public class ReadmeEditor : Editor +{ + static string s_ShowedReadmeSessionStateName = "ReadmeEditor.showedReadme"; + + static string s_ReadmeSourceDirectory = "Assets/TutorialInfo"; + + const float k_Space = 16f; + + static ReadmeEditor() + { + EditorApplication.delayCall += SelectReadmeAutomatically; + } + + static void RemoveTutorial() + { + if (EditorUtility.DisplayDialog("Remove Readme Assets", + + $"All contents under {s_ReadmeSourceDirectory} will be removed, are you sure you want to proceed?", + "Proceed", + "Cancel")) + { + if (Directory.Exists(s_ReadmeSourceDirectory)) + { + FileUtil.DeleteFileOrDirectory(s_ReadmeSourceDirectory); + FileUtil.DeleteFileOrDirectory(s_ReadmeSourceDirectory + ".meta"); + } + else + { + Debug.Log($"Could not find the Readme folder at {s_ReadmeSourceDirectory}"); + } + + var readmeAsset = SelectReadme(); + if (readmeAsset != null) + { + var path = AssetDatabase.GetAssetPath(readmeAsset); + FileUtil.DeleteFileOrDirectory(path + ".meta"); + FileUtil.DeleteFileOrDirectory(path); + } + + AssetDatabase.Refresh(); + } + } + + static void SelectReadmeAutomatically() + { + if (!SessionState.GetBool(s_ShowedReadmeSessionStateName, false)) + { + var readme = SelectReadme(); + SessionState.SetBool(s_ShowedReadmeSessionStateName, true); + + if (readme && !readme.loadedLayout) + { + LoadLayout(); + readme.loadedLayout = true; + } + } + } + + static void LoadLayout() + { + var assembly = typeof(EditorApplication).Assembly; + var windowLayoutType = assembly.GetType("UnityEditor.WindowLayout", true); + var method = windowLayoutType.GetMethod("LoadWindowLayout", BindingFlags.Public | BindingFlags.Static); + method.Invoke(null, new object[] { Path.Combine(Application.dataPath, "TutorialInfo/Layout.wlt"), false }); + } + + static Readme SelectReadme() + { + var ids = AssetDatabase.FindAssets("Readme t:Readme"); + if (ids.Length == 1) + { + var readmeObject = AssetDatabase.LoadMainAssetAtPath(AssetDatabase.GUIDToAssetPath(ids[0])); + + Selection.objects = new UnityEngine.Object[] { readmeObject }; + + return (Readme)readmeObject; + } + else + { + Debug.Log("Couldn't find a readme"); + return null; + } + } + + protected override void OnHeaderGUI() + { + var readme = (Readme)target; + Init(); + + var iconWidth = Mathf.Min(EditorGUIUtility.currentViewWidth / 3f - 20f, 128f); + + GUILayout.BeginHorizontal("In BigTitle"); + { + if (readme.icon != null) + { + GUILayout.Space(k_Space); + GUILayout.Label(readme.icon, GUILayout.Width(iconWidth), GUILayout.Height(iconWidth)); + } + GUILayout.Space(k_Space); + GUILayout.BeginVertical(); + { + + GUILayout.FlexibleSpace(); + GUILayout.Label(readme.title, TitleStyle); + GUILayout.FlexibleSpace(); + } + GUILayout.EndVertical(); + GUILayout.FlexibleSpace(); + } + GUILayout.EndHorizontal(); + } + + public override void OnInspectorGUI() + { + var readme = (Readme)target; + Init(); + + foreach (var section in readme.sections) + { + if (!string.IsNullOrEmpty(section.heading)) + { + GUILayout.Label(section.heading, HeadingStyle); + } + + if (!string.IsNullOrEmpty(section.text)) + { + GUILayout.Label(section.text, BodyStyle); + } + + if (!string.IsNullOrEmpty(section.linkText)) + { + if (LinkLabel(new GUIContent(section.linkText))) + { + Application.OpenURL(section.url); + } + } + + GUILayout.Space(k_Space); + } + + if (GUILayout.Button("Remove Readme Assets", ButtonStyle)) + { + RemoveTutorial(); + } + } + + bool m_Initialized; + + GUIStyle LinkStyle + { + get { return m_LinkStyle; } + } + + [SerializeField] + GUIStyle m_LinkStyle; + + GUIStyle TitleStyle + { + get { return m_TitleStyle; } + } + + [SerializeField] + GUIStyle m_TitleStyle; + + GUIStyle HeadingStyle + { + get { return m_HeadingStyle; } + } + + [SerializeField] + GUIStyle m_HeadingStyle; + + GUIStyle BodyStyle + { + get { return m_BodyStyle; } + } + + [SerializeField] + GUIStyle m_BodyStyle; + + GUIStyle ButtonStyle + { + get { return m_ButtonStyle; } + } + + [SerializeField] + GUIStyle m_ButtonStyle; + + void Init() + { + if (m_Initialized) + return; + m_BodyStyle = new GUIStyle(EditorStyles.label); + m_BodyStyle.wordWrap = true; + m_BodyStyle.fontSize = 14; + m_BodyStyle.richText = true; + + m_TitleStyle = new GUIStyle(m_BodyStyle); + m_TitleStyle.fontSize = 26; + + m_HeadingStyle = new GUIStyle(m_BodyStyle); + m_HeadingStyle.fontStyle = FontStyle.Bold; + m_HeadingStyle.fontSize = 18; + + m_LinkStyle = new GUIStyle(m_BodyStyle); + m_LinkStyle.wordWrap = false; + + // Match selection color which works nicely for both light and dark skins + m_LinkStyle.normal.textColor = new Color(0x00 / 255f, 0x78 / 255f, 0xDA / 255f, 1f); + m_LinkStyle.stretchWidth = false; + + m_ButtonStyle = new GUIStyle(EditorStyles.miniButton); + m_ButtonStyle.fontStyle = FontStyle.Bold; + + m_Initialized = true; + } + + bool LinkLabel(GUIContent label, params GUILayoutOption[] options) + { + var position = GUILayoutUtility.GetRect(label, LinkStyle, options); + + Handles.BeginGUI(); + Handles.color = LinkStyle.normal.textColor; + Handles.DrawLine(new Vector3(position.xMin, position.yMax), new Vector3(position.xMax, position.yMax)); + Handles.color = Color.white; + Handles.EndGUI(); + + EditorGUIUtility.AddCursorRect(position, MouseCursor.Link); + + return GUI.Button(position, label, LinkStyle); + } +} diff --git a/Assets/TutorialInfo/Scripts/Editor/ReadmeEditor.cs.meta b/Assets/TutorialInfo/Scripts/Editor/ReadmeEditor.cs.meta new file mode 100644 index 0000000..f038618 --- /dev/null +++ b/Assets/TutorialInfo/Scripts/Editor/ReadmeEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 476cc7d7cd9874016adc216baab94a0a +timeCreated: 1484146680 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TutorialInfo/Scripts/Readme.cs b/Assets/TutorialInfo/Scripts/Readme.cs new file mode 100644 index 0000000..95f6269 --- /dev/null +++ b/Assets/TutorialInfo/Scripts/Readme.cs @@ -0,0 +1,16 @@ +using System; +using UnityEngine; + +public class Readme : ScriptableObject +{ + public Texture2D icon; + public string title; + public Section[] sections; + public bool loadedLayout; + + [Serializable] + public class Section + { + public string heading, text, linkText, url; + } +} diff --git a/Assets/TutorialInfo/Scripts/Readme.cs.meta b/Assets/TutorialInfo/Scripts/Readme.cs.meta new file mode 100644 index 0000000..935153f --- /dev/null +++ b/Assets/TutorialInfo/Scripts/Readme.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: fcf7219bab7fe46a1ad266029b2fee19 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: + - icon: {instanceID: 0} + executionOrder: 0 + icon: {fileID: 2800000, guid: a186f8a87ca4f4d3aa864638ad5dfb65, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UI Toolkit.meta b/Assets/UI Toolkit.meta new file mode 100644 index 0000000..2c5635a --- /dev/null +++ b/Assets/UI Toolkit.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 329e9fe65afd87c4ba9b75083ccdb384 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UI Toolkit/PanelSettings.asset b/Assets/UI Toolkit/PanelSettings.asset new file mode 100644 index 0000000..615eedc --- /dev/null +++ b/Assets/UI Toolkit/PanelSettings.asset @@ -0,0 +1,38 @@ +%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: 19101, guid: 0000000000000000e000000000000000, type: 0} + m_Name: PanelSettings + m_EditorClassIdentifier: + themeUss: {fileID: -4733365628477956816, guid: 07a9ea9507a4db84f883d2a811632918, + type: 3} + m_TargetTexture: {fileID: 0} + m_ScaleMode: 1 + m_Scale: 1 + m_ReferenceDpi: 96 + m_FallbackDpi: 96 + m_ReferenceResolution: {x: 1200, y: 800} + m_ScreenMatchMode: 0 + m_Match: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 + m_ClearDepthStencil: 1 + m_ClearColor: 0 + m_ColorClearValue: {r: 0, g: 0, b: 0, a: 0} + m_DynamicAtlasSettings: + m_MinAtlasSize: 64 + m_MaxAtlasSize: 4096 + m_MaxSubTextureSize: 64 + m_ActiveFilters: 31 + m_AtlasBlitShader: {fileID: 9101, guid: 0000000000000000f000000000000000, type: 0} + m_RuntimeShader: {fileID: 9100, guid: 0000000000000000f000000000000000, type: 0} + m_RuntimeWorldShader: {fileID: 9102, guid: 0000000000000000f000000000000000, type: 0} + textSettings: {fileID: 0} diff --git a/Assets/UI Toolkit/PanelSettings.asset.meta b/Assets/UI Toolkit/PanelSettings.asset.meta new file mode 100644 index 0000000..9362628 --- /dev/null +++ b/Assets/UI Toolkit/PanelSettings.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7085e9cd0c737af4aad102900c61ffee +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UI Toolkit/UnityThemes.meta b/Assets/UI Toolkit/UnityThemes.meta new file mode 100644 index 0000000..a095e79 --- /dev/null +++ b/Assets/UI Toolkit/UnityThemes.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: bdf035438f4ad9246bd611ced305c2fa +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UI Toolkit/UnityThemes/UnityDefaultRuntimeTheme.tss b/Assets/UI Toolkit/UnityThemes/UnityDefaultRuntimeTheme.tss new file mode 100644 index 0000000..1056e07 --- /dev/null +++ b/Assets/UI Toolkit/UnityThemes/UnityDefaultRuntimeTheme.tss @@ -0,0 +1 @@ +@import url("unity-theme://default"); \ No newline at end of file diff --git a/Assets/UI Toolkit/UnityThemes/UnityDefaultRuntimeTheme.tss.meta b/Assets/UI Toolkit/UnityThemes/UnityDefaultRuntimeTheme.tss.meta new file mode 100644 index 0000000..cea63b5 --- /dev/null +++ b/Assets/UI Toolkit/UnityThemes/UnityDefaultRuntimeTheme.tss.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 07a9ea9507a4db84f883d2a811632918 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 12388, guid: 0000000000000000e000000000000000, type: 0} + disableValidation: 0 diff --git a/Assets/WayspotAnchorDataUtility.cs b/Assets/WayspotAnchorDataUtility.cs new file mode 100644 index 0000000..8f71fb7 --- /dev/null +++ b/Assets/WayspotAnchorDataUtility.cs @@ -0,0 +1,60 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; +using System.Collections.Generic; +using System.Linq; + +using Niantic.ARDK.AR.WayspotAnchors; + +using UnityEngine; + +namespace WayspotAnchors +{ + public static class WayspotAnchorDataUtility + { + private const string DataKey = "wayspot_anchor_payloads"; + + public static void SaveLocalPayloads(WayspotAnchorPayload[] wayspotAnchorPayloads) + { + var wayspotAnchorsData = new WayspotAnchorsData(); + wayspotAnchorsData.Payloads = wayspotAnchorPayloads.Select(a => a.Serialize()).ToArray(); + string wayspotAnchorsJson = JsonUtility.ToJson(wayspotAnchorsData); + PlayerPrefs.SetString(DataKey, wayspotAnchorsJson); + } + + public static WayspotAnchorPayload[] LoadLocalPayloads() + { + if (PlayerPrefs.HasKey(DataKey)) + { + var payloads = new List(); + var json = PlayerPrefs.GetString(DataKey); + var wayspotAnchorsData = JsonUtility.FromJson(json); + foreach (var wayspotAnchorPayload in wayspotAnchorsData.Payloads) + { + var payload = WayspotAnchorPayload.Deserialize(wayspotAnchorPayload); + payloads.Add(payload); + } + + return payloads.ToArray(); + } + else + { + return Array.Empty(); + } + } + + public static void ClearLocalPayloads() + { + if (PlayerPrefs.HasKey(DataKey)) + { + PlayerPrefs.DeleteKey(DataKey); + } + } + + [Serializable] + private class WayspotAnchorsData + { + /// The payloads to save via JsonUtility + public string[] Payloads = Array.Empty(); + } + } +} diff --git a/Assets/WayspotAnchorDataUtility.cs.meta b/Assets/WayspotAnchorDataUtility.cs.meta new file mode 100644 index 0000000..c832ff7 --- /dev/null +++ b/Assets/WayspotAnchorDataUtility.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 90c3c08f8a36ab74d826ad5c1389cfc3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/WayspotAnchorManager.cs b/Assets/WayspotAnchorManager.cs new file mode 100644 index 0000000..87ff63a --- /dev/null +++ b/Assets/WayspotAnchorManager.cs @@ -0,0 +1,308 @@ +// Copyright 2022 Niantic, Inc. All Rights Reserved. +using System; +using System.Collections.Generic; +using System.Linq; + +using Niantic.ARDK.AR; +using Niantic.ARDK.AR.ARSessionEventArgs; +using Niantic.ARDK.AR.HitTest; +using Niantic.ARDK.AR.WayspotAnchors; +using Niantic.ARDK.LocationService; +using Niantic.ARDK.Utilities.Input.Legacy; + +using UnityEngine; +using UnityEngine.UI; + +namespace WayspotAnchors +{ + public class WayspotAnchorManager: MonoBehaviour + { + [Tooltip("The anchor that will be placed")] + [SerializeField] + private GameObject _anchorPrefab; + + [Tooltip("Camera used to place the anchors via raycasting")] + [SerializeField] + private Camera _camera; + + [Tooltip("Text used to display the current status of the demo")] + [SerializeField] + private Text _statusLog; + + [Tooltip("Text used to show the current localization state")] + [SerializeField] + private Text _localizationStatus; + + private WayspotAnchorService _wayspotAnchorService; + private IARSession _arSession; + private LocalizationState _localizationState; + + private readonly Dictionary _wayspotAnchorGameObjects = + new Dictionary(); + + private void Awake() + { + // This is necessary for setting the user id associated with the current user. + // We strongly recommend generating and using User IDs. Accurate user information allows + // Niantic to support you in maintaining data privacy best practices and allows you to + // understand usage patterns of features among your users. + // ARDK has no strict format or length requirements for User IDs, although the User ID string + // must be a UTF8 string. We recommend avoiding using an ID that maps back directly to the + // user. So, for example, don’t use email addresses, or login IDs. Instead, you should + // generate a unique ID for each user. We recommend generating a GUID. + // When the user logs out, clear ARDK's user id with ArdkGlobalConfig.ClearUserIdOnLogout + + // Sample code: + // // GetCurrentUserId() is your code that gets a user ID string from your login service + // var userId = GetCurrentUserId(); + // ArdkGlobalConfig.SetUserIdOnLogin(userId); + + _statusLog.text = "Initializing Session."; + } + + private void OnEnable() + { + ARSessionFactory.SessionInitialized += HandleSessionInitialized; + } + + private void Update() + { + if (_wayspotAnchorService == null) + { + return; + } + //Get the pose where you tap on the screen + var success = TryGetTouchInput(out Matrix4x4 localPose); + if (_wayspotAnchorService.LocalizationState == LocalizationState.Localized) + { + if (success) //Check is screen tap was a valid tap + { + PlaceAnchor(localPose); //Create the Wayspot Anchor and place the GameObject + } + } + else + { + if (success) //Check is screen tap was a valid tap + { + _statusLog.text = "Must localize before placing anchor."; + } + if(_localizationState != _wayspotAnchorService.LocalizationState) + { + _wayspotAnchorGameObjects.Values.ToList().ForEach(a => a.SetActive(false)); + } + } + _localizationStatus.text = _wayspotAnchorService.LocalizationState.ToString(); + _localizationState = _wayspotAnchorService.LocalizationState; + } + + private void OnDisable() + { + ARSessionFactory.SessionInitialized -= HandleSessionInitialized; + } + + private void OnDestroy() + { + _wayspotAnchorService.Dispose(); + } + + /// Saves all of the existing wayspot anchors + public void SaveWayspotAnchors() + { + if (_wayspotAnchorGameObjects.Count > 0) + { + var wayspotAnchors = _wayspotAnchorService.GetAllWayspotAnchors(); + var payloads = wayspotAnchors.Select(a => a.Payload); + WayspotAnchorDataUtility.SaveLocalPayloads(payloads.ToArray()); + } + else + { + WayspotAnchorDataUtility.SaveLocalPayloads(Array.Empty()); + } + + _statusLog.text = "Saved Wayspot Anchors."; + } + + /// Loads all of the saved wayspot anchors + public void LoadWayspotAnchors() + { + if (_wayspotAnchorService.LocalizationState != LocalizationState.Localized) + { + _statusLog.text = "Must localize before loading anchors."; + return; + } + + var payloads = WayspotAnchorDataUtility.LoadLocalPayloads(); + if (payloads.Length > 0) + { + var wayspotAnchors = _wayspotAnchorService.RestoreWayspotAnchors(payloads); + CreateAnchorGameObjects(wayspotAnchors); + _statusLog.text = "Loaded Wayspot Anchors."; + } + else + { + _statusLog.text = "No anchors to load."; + } + } + + /// Clears all of the active wayspot anchors + public void ClearAnchorGameObjects() + { + if (_wayspotAnchorGameObjects.Count == 0) + { + _statusLog.text = "No anchors to clear."; + return; + } + + foreach (var anchor in _wayspotAnchorGameObjects) + { + Destroy(anchor.Value); + } + + _wayspotAnchorService.DestroyWayspotAnchors(_wayspotAnchorGameObjects.Keys.ToArray()); + _wayspotAnchorGameObjects.Clear(); + _statusLog.text = "Cleared Wayspot Anchors."; + } + + /// Pauses the AR Session + public void PauseARSession() + { + if (_arSession.State == ARSessionState.Running) + { + _arSession.Pause(); + _statusLog.text = $"AR Session Paused."; + } + else + { + _statusLog.text = $"Cannot pause AR Session."; + } + } + + /// Resumes the AR Session + public void ResumeARSession() + { + if (_arSession.State == ARSessionState.Paused) + { + _arSession.Run(_arSession.Configuration); + _statusLog.text = $"AR Session Resumed."; + } + else + { + _statusLog.text = $"Cannot resume AR Session."; + } + } + + /// Restarts Wayspot Anchor Service + public void RestartWayspotAnchorService() + { + _wayspotAnchorService.Restart(); + } + + private void HandleSessionInitialized(AnyARSessionInitializedArgs anyARSessionInitializedArgs) + { + _statusLog.text = "Running Session..."; + _arSession = anyARSessionInitializedArgs.Session; + _arSession.Ran += HandleSessionRan; + } + + private void HandleSessionRan(ARSessionRanArgs arSessionRanArgs) + { + _arSession.Ran -= HandleSessionRan; + _wayspotAnchorService = CreateWayspotAnchorService(); + _statusLog.text = "Session Initialized."; + } + + private void PlaceAnchor(Matrix4x4 localPose) + { + _wayspotAnchorService.CreateWayspotAnchors(CreateAnchorGameObjects, localPose); + // Alternatively, you can make this method async and create wayspot anchors using await: + // var wayspotAnchors = await _wayspotAnchorService.CreateWayspotAnchorsAsync(localPose); + // CreateAnchorGameObjects(wayspotAnchors); + + _statusLog.text = "Anchor placed."; + } + + private WayspotAnchorService CreateWayspotAnchorService() + { + var wayspotAnchorsConfiguration = WayspotAnchorsConfigurationFactory.Create(); + + var locationService = LocationServiceFactory.Create(_arSession.RuntimeEnvironment); + locationService.Start(); + + var wayspotAnchorService = new WayspotAnchorService(_arSession, locationService, wayspotAnchorsConfiguration); + return wayspotAnchorService; + } + + private void CreateAnchorGameObjects(IWayspotAnchor[] wayspotAnchors) + { + foreach (var wayspotAnchor in wayspotAnchors) + { + if (_wayspotAnchorGameObjects.ContainsKey(wayspotAnchor.ID)) + { + continue; + } + wayspotAnchor.TrackingStateUpdated += HandleWayspotAnchorTrackingUpdated; + var id = wayspotAnchor.ID; + var anchor = Instantiate(_anchorPrefab); + anchor.SetActive(false); + anchor.name = $"Anchor {id}"; + _wayspotAnchorGameObjects.Add(id, anchor); + } + } + + private void HandleWayspotAnchorTrackingUpdated(WayspotAnchorResolvedArgs wayspotAnchorResolvedArgs) + { + var anchor = _wayspotAnchorGameObjects[wayspotAnchorResolvedArgs.ID].transform; + anchor.position = wayspotAnchorResolvedArgs.Position; + anchor.rotation = wayspotAnchorResolvedArgs.Rotation; + anchor.gameObject.SetActive(true); + } + + private bool TryGetTouchInput(out Matrix4x4 localPose) + { + if (_arSession == null || PlatformAgnosticInput.touchCount <= 0) + { + localPose = Matrix4x4.zero; + return false; + } + + var touch = PlatformAgnosticInput.GetTouch(0); + if (touch.IsTouchOverUIObject()) + { + localPose = Matrix4x4.zero; + return false; + } + + if (touch.phase != TouchPhase.Began) + { + localPose = Matrix4x4.zero; + return false; + } + + var currentFrame = _arSession.CurrentFrame; + if (currentFrame == null) + { + localPose = Matrix4x4.zero; + return false; + } + + var results = currentFrame.HitTest + ( + _camera.pixelWidth, + _camera.pixelHeight, + touch.position, + ARHitTestResultType.ExistingPlane + ); + + int count = results.Count; + if (count <= 0) + { + localPose = Matrix4x4.zero; + return false; + } + + var result = results[0]; + localPose = result.WorldTransform; + return true; + } + } +} diff --git a/Assets/WayspotAnchorManager.cs.meta b/Assets/WayspotAnchorManager.cs.meta new file mode 100644 index 0000000..075cf4b --- /dev/null +++ b/Assets/WayspotAnchorManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 113b9d20890f31f4d864c69586d8bda0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/compass.png b/Assets/compass.png new file mode 100644 index 0000000..60ce4ee Binary files /dev/null and b/Assets/compass.png differ diff --git a/Assets/compass.png.meta b/Assets/compass.png.meta new file mode 100644 index 0000000..4496a95 --- /dev/null +++ b/Assets/compass.png.meta @@ -0,0 +1,146 @@ +fileFormatVersion: 2 +guid: 1df24786ab9ee03439ed6f5eb8d0b370 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 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: 1 + aniso: 1 + mipBias: 0 + 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: 1 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Server + 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: Android + 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: WebGL + 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: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/manifest.json b/Packages/manifest.json new file mode 100644 index 0000000..b2c3982 --- /dev/null +++ b/Packages/manifest.json @@ -0,0 +1,45 @@ +{ + "dependencies": { + "com.unity.collab-proxy": "1.15.18", + "com.unity.feature.mobile": "1.0.0", + "com.unity.ide.rider": "3.0.13", + "com.unity.ide.visualstudio": "2.0.14", + "com.unity.ide.vscode": "1.2.5", + "com.unity.test-framework": "1.1.31", + "com.unity.textmeshpro": "3.0.6", + "com.unity.timeline": "1.6.4", + "com.unity.ugui": "1.0.0", + "com.unity.visualscripting": "1.7.6", + "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..ce8b5cb --- /dev/null +++ b/Packages/packages-lock.json @@ -0,0 +1,411 @@ +{ + "dependencies": { + "com.unity.adaptiveperformance": { + "version": "3.0.2", + "depth": 1, + "source": "registry", + "dependencies": { + "com.unity.subsystemregistration": "1.1.0", + "com.unity.profiling.core": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.collab-proxy": { + "version": "1.15.18", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.services.core": "1.0.1" + }, + "url": "https://packages.unity.com" + }, + "com.unity.ext.nunit": { + "version": "1.0.6", + "depth": 1, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.feature.mobile": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.mobile.android-logcat": "1.2.3", + "com.unity.adaptiveperformance": "3.0.2", + "com.unity.mobile.notifications": "2.0.0" + } + }, + "com.unity.ide.rider": { + "version": "3.0.13", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.ext.nunit": "1.0.6" + }, + "url": "https://packages.unity.com" + }, + "com.unity.ide.visualstudio": { + "version": "2.0.14", + "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.mobile.android-logcat": { + "version": "1.2.3", + "depth": 1, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.mobile.notifications": { + "version": "2.0.0", + "depth": 1, + "source": "registry", + "dependencies": { + "com.unity.modules.androidjni": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.profiling.core": { + "version": "1.0.2", + "depth": 2, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.services.core": { + "version": "1.0.1", + "depth": 1, + "source": "registry", + "dependencies": { + "com.unity.modules.unitywebrequest": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.subsystemregistration": { + "version": "1.1.0", + "depth": 2, + "source": "registry", + "dependencies": { + "com.unity.modules.subsystems": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.test-framework": { + "version": "1.1.31", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.ext.nunit": "1.0.6", + "com.unity.modules.imgui": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.textmeshpro": { + "version": "3.0.6", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.ugui": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.timeline": { + "version": "1.6.4", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.modules.director": "1.0.0", + "com.unity.modules.animation": "1.0.0", + "com.unity.modules.audio": "1.0.0", + "com.unity.modules.particlesystem": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.ugui": { + "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.visualscripting": { + "version": "1.7.6", + "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.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.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.uielementsnative": "1.0.0" + } + }, + "com.unity.modules.uielementsnative": { + "version": "1.0.0", + "depth": 1, + "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.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..07ebfb0 --- /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: 1024 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/DynamicsManager.asset b/ProjectSettings/DynamicsManager.asset new file mode 100644 index 0000000..cdc1f3e --- /dev/null +++ b/ProjectSettings/DynamicsManager.asset @@ -0,0 +1,34 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!55 &1 +PhysicsManager: + m_ObjectHideFlags: 0 + serializedVersion: 11 + 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 + m_ClothInterCollisionStiffness: 0 + m_ContactsGeneration: 1 + m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + m_AutoSimulation: 1 + m_AutoSyncTransforms: 0 + m_ReuseCollisionCallbacks: 1 + m_ClothInterCollisionSettingsToggle: 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_DefaultMaxAngluarSpeed: 7 diff --git a/ProjectSettings/EditorBuildSettings.asset b/ProjectSettings/EditorBuildSettings.asset new file mode 100644 index 0000000..56ab36a --- /dev/null +++ b/ProjectSettings/EditorBuildSettings.asset @@ -0,0 +1,24 @@ +%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/Main.unity + guid: b6474ea881770b3409e04772a882bc0a + - enabled: 1 + path: Assets/Scenes/SearchGPS.unity + guid: a95637ff7c61c6b42bd0c563a86e921a + - enabled: 1 + path: Assets/Scenes/VPSCreate.unity + guid: 9416b9171502e0e4e87f1802caef1483 + - enabled: 1 + path: Assets/Scenes/VPSSearch.unity + guid: 7fc50a6b4f982a94085782c09fa13a9f + m_configObjects: + com.unity.adaptiveperformance.loader_settings: {fileID: 11400000, guid: 6f70b1763ea9d4749a5714274f31dcd2, + type: 2} + com.unity.adaptiveperformance.simulator.provider_settings: {fileID: 11400000, + guid: 9f408d13013cdc6418ca440c6ce0dd7e, type: 2} diff --git a/ProjectSettings/EditorSettings.asset b/ProjectSettings/EditorSettings.asset new file mode 100644 index 0000000..f920544 --- /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: 0 + 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;rsp;asmref + 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..19a73f0 --- /dev/null +++ b/ProjectSettings/GraphicsSettings.asset @@ -0,0 +1,165 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!30 &1 +GraphicsSettings: + m_ObjectHideFlags: 0 + serializedVersion: 13 + 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_LegacyDeferred: + m_Mode: 1 + m_Shader: {fileID: 63, 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_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} + m_PreloadedShaders: [] + m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, + type: 0} + m_CustomRenderPipeline: {fileID: 0} + m_TransparencySortMode: 0 + m_TransparencySortAxis: {x: 0, y: 0, z: 1} + m_DefaultRenderingPath: 1 + m_DefaultMobileRenderingPath: 1 + m_TierSettings: + - serializedVersion: 5 + m_BuildTarget: 4 + m_Tier: 0 + m_Settings: + standardShaderQuality: 1 + renderingPath: 1 + hdrMode: 2 + realtimeGICPUUsage: 25 + useReflectionProbeBoxProjection: 0 + useReflectionProbeBlending: 0 + useHDR: 0 + useDetailNormalMap: 0 + useCascadedShadowMaps: 0 + prefer32BitShadowMaps: 0 + enableLPPV: 0 + useDitherMaskForAlphaBlendedShadows: 0 + m_Automatic: 0 + - serializedVersion: 5 + m_BuildTarget: 4 + m_Tier: 1 + m_Settings: + standardShaderQuality: 1 + renderingPath: 1 + hdrMode: 2 + realtimeGICPUUsage: 25 + useReflectionProbeBoxProjection: 0 + useReflectionProbeBlending: 0 + useHDR: 0 + useDetailNormalMap: 0 + useCascadedShadowMaps: 0 + prefer32BitShadowMaps: 0 + enableLPPV: 0 + useDitherMaskForAlphaBlendedShadows: 0 + m_Automatic: 0 + - serializedVersion: 5 + m_BuildTarget: 4 + m_Tier: 2 + m_Settings: + standardShaderQuality: 1 + renderingPath: 1 + hdrMode: 2 + realtimeGICPUUsage: 25 + useReflectionProbeBoxProjection: 0 + useReflectionProbeBlending: 0 + useHDR: 0 + useDetailNormalMap: 0 + useCascadedShadowMaps: 0 + prefer32BitShadowMaps: 0 + enableLPPV: 0 + useDitherMaskForAlphaBlendedShadows: 0 + m_Automatic: 0 + - serializedVersion: 5 + m_BuildTarget: 7 + m_Tier: 0 + m_Settings: + standardShaderQuality: 1 + renderingPath: 1 + hdrMode: 2 + realtimeGICPUUsage: 25 + useReflectionProbeBoxProjection: 0 + useReflectionProbeBlending: 0 + useHDR: 0 + useDetailNormalMap: 0 + useCascadedShadowMaps: 0 + prefer32BitShadowMaps: 0 + enableLPPV: 0 + useDitherMaskForAlphaBlendedShadows: 0 + m_Automatic: 0 + - serializedVersion: 5 + m_BuildTarget: 7 + m_Tier: 1 + m_Settings: + standardShaderQuality: 1 + renderingPath: 1 + hdrMode: 2 + realtimeGICPUUsage: 25 + useReflectionProbeBoxProjection: 0 + useReflectionProbeBlending: 0 + useHDR: 0 + useDetailNormalMap: 0 + useCascadedShadowMaps: 0 + prefer32BitShadowMaps: 0 + enableLPPV: 0 + useDitherMaskForAlphaBlendedShadows: 0 + m_Automatic: 0 + - serializedVersion: 5 + m_BuildTarget: 7 + m_Tier: 2 + m_Settings: + standardShaderQuality: 1 + renderingPath: 1 + hdrMode: 2 + realtimeGICPUUsage: 25 + useReflectionProbeBoxProjection: 0 + useReflectionProbeBlending: 0 + useHDR: 0 + useDetailNormalMap: 0 + useCascadedShadowMaps: 0 + prefer32BitShadowMaps: 0 + enableLPPV: 0 + useDitherMaskForAlphaBlendedShadows: 0 + m_Automatic: 0 + m_LightmapStripping: 0 + m_FogStripping: 0 + m_InstancingStripping: 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_LightsUseLinearIntensity: 0 + m_LightsUseColorTemperature: 0 + m_LogWhenShaderIsCompiled: 0 + m_AllowEnlightenSupportForUpgradedProject: 0 diff --git a/ProjectSettings/InputManager.asset b/ProjectSettings/InputManager.asset new file mode 100644 index 0000000..17c8f53 --- /dev/null +++ b/ProjectSettings/InputManager.asset @@ -0,0 +1,295 @@ +%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 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/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/NotificationsSettings.asset b/ProjectSettings/NotificationsSettings.asset new file mode 100644 index 0000000..43e12f9 --- /dev/null +++ b/ProjectSettings/NotificationsSettings.asset @@ -0,0 +1,42 @@ +{ + "MonoBehaviour": { + "m_Enabled": true, + "m_EditorHideFlags": 0, + "m_Name": "", + "m_EditorClassIdentifier": "", + "ToolbarIndex": 0, + "m_iOSNotificationSettingsValues": { + "m_Keys": [ + "UnityNotificationRequestAuthorizationOnAppLaunch", + "UnityNotificationDefaultAuthorizationOptions", + "UnityAddRemoteNotificationCapability", + "UnityNotificationRequestAuthorizationForRemoteNotificationsOnAppLaunch", + "UnityRemoteNotificationForegroundPresentationOptions", + "UnityUseAPSReleaseEnvironment", + "UnityUseLocationNotificationTrigger" + ], + "m_Values": [ + "True", + "7", + "False", + "False", + "-1", + "False", + "False" + ] + }, + "m_AndroidNotificationSettingsValues": { + "m_Keys": [ + "UnityNotificationAndroidRescheduleOnDeviceRestart", + "UnityNotificationAndroidUseCustomActivity", + "UnityNotificationAndroidCustomActivityString" + ], + "m_Values": [ + "False", + "False", + "com.unity3d.player.UnityPlayerActivity" + ] + }, + "DrawableResources": [] + } +} \ No newline at end of file diff --git a/ProjectSettings/PackageManagerSettings.asset b/ProjectSettings/PackageManagerSettings.asset new file mode 100644 index 0000000..9aa5017 --- /dev/null +++ b/ProjectSettings/PackageManagerSettings.asset @@ -0,0 +1,35 @@ +%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_EnablePackageDependencies: 0 + m_AdvancedSettingsExpanded: 1 + m_ScopedRegistriesSettingsExpanded: 1 + m_SeeAllPackageVersions: 0 + oneTimeWarningShown: 0 + m_Registries: + - m_Id: main + m_Name: + m_Url: https://packages.unity.com + m_Scopes: [] + m_IsDefault: 1 + m_Capabilities: 7 + m_UserSelectedRegistryName: + m_UserAddingNewScopedRegistry: 0 + m_RegistryInfoDraft: + m_Modified: 0 + m_ErrorMessage: + m_UserModificationsInstanceId: -886 + m_OriginalInstanceId: -888 + m_LoadAssets: 0 diff --git a/ProjectSettings/Physics2DSettings.asset b/ProjectSettings/Physics2DSettings.asset new file mode 100644 index 0000000..47880b1 --- /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: 1 + 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..27588d9 --- /dev/null +++ b/ProjectSettings/ProjectSettings.asset @@ -0,0 +1,902 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!129 &1 +PlayerSettings: + m_ObjectHideFlags: 0 + serializedVersion: 23 + productGUID: 63f9ae9618c8b7546a91e30cfee2aca8 + AndroidProfiler: 0 + AndroidFilterTouchesWhenObscured: 0 + AndroidEnableSustainedPerformanceMode: 0 + defaultScreenOrientation: 4 + targetDevice: 2 + useOnDemandResources: 0 + accelerometerFrequency: 60 + companyName: DefaultCompany + productName: ARDK - SG - PP + 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_MTRendering: 1 + mipStripping: 0 + numberOfMipsStripped: 0 + m_StackTraceTypes: 010000000100000001000000000000000100000001000000 + iosShowActivityIndicatorOnLoading: -1 + androidShowActivityIndicatorOnLoading: -1 + iosUseCustomAppBackgroundBehavior: 0 + iosAllowHTTPDownload: 1 + allowedAutorotateToPortrait: 1 + allowedAutorotateToPortraitUpsideDown: 1 + allowedAutorotateToLandscapeRight: 1 + allowedAutorotateToLandscapeLeft: 1 + useOSAutorotation: 1 + use32BitDisplayBuffer: 1 + preserveFramebufferAlpha: 0 + disableDepthAndStencilBuffers: 0 + androidStartInFullscreen: 1 + androidRenderOutsideSafeArea: 1 + androidUseSwappy: 1 + androidBlitType: 2 + androidResizableWindow: 0 + androidDefaultWindowWidth: 1920 + androidDefaultWindowHeight: 1080 + androidMinimumWindowWidth: 400 + androidMinimumWindowHeight: 300 + androidFullscreenMode: 1 + defaultIsNativeResolution: 1 + macRetinaSupport: 1 + runInBackground: 1 + captureSingleScreen: 0 + muteOtherAudioSources: 0 + Prepare IOS For Recording: 0 + Force IOS Speakers When Recording: 0 + deferSystemGesturesMode: 0 + hideHomeButton: 0 + submitAnalytics: 1 + usePlayerLog: 1 + 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: 0 + switchQueueControlMemory: 16384 + switchQueueComputeMemory: 262144 + switchNVNShaderPoolsGranularity: 33554432 + switchNVNDefaultPoolsGranularity: 16777216 + switchNVNOtherPoolsGranularity: 16777216 + switchNVNMaxPublicTextureIDCount: 0 + switchNVNMaxPublicSamplerIDCount: 0 + stadiaPresentMode: 0 + stadiaTargetFramerate: 0 + vulkanNumSwapchainBuffers: 3 + vulkanEnableSetSRGBWrite: 0 + vulkanEnablePreTransform: 0 + vulkanEnableLateAcquireNextImage: 0 + vulkanEnableCommandBufferRecycling: 1 + m_SupportedAspectRatios: + 4:3: 1 + 5:4: 1 + 16:10: 1 + 16:9: 1 + Others: 1 + bundleVersion: 1.0.2 + preloadedAssets: [] + metroInputSource: 0 + wsaTransparentSwapchain: 0 + m_HolographicPauseOnTrackingLoss: 1 + xboxOneDisableKinectGpuReservation: 1 + xboxOneEnable7thCore: 1 + vrSettings: + enable360StereoCapture: 0 + isWsaHolographicRemotingEnabled: 0 + enableFrameTimingStats: 0 + useHDRDisplay: 0 + D3DHDRBitDepth: 0 + m_ColorGamuts: 00000000 + targetPixelDensity: 30 + resolutionScalingMode: 0 + androidSupportedAspectRatio: 1 + androidMaxAspectRatio: 2.1 + applicationIdentifier: + Android: com.DefaultCompany.ARDKSGPP + Standalone: com.DefaultCompany.ARDK---SG---PP + buildNumber: + Standalone: 0 + iPhone: 0 + tvOS: 0 + overrideDefaultApplicationIdentifier: 0 + AndroidBundleVersionCode: 1 + AndroidMinSdkVersion: 22 + AndroidTargetSdkVersion: 29 + AndroidPreferredInstallLocation: 1 + aotOptions: + stripEngineCode: 1 + iPhoneStrippingLevel: 0 + iPhoneScriptCallOptimization: 0 + ForceInternetPermission: 0 + ForceSDCardPermission: 0 + CreateWallpaper: 0 + APKExpansionFiles: 0 + keepLoadedShadersAlive: 0 + StripUnusedMeshComponents: 1 + VertexChannelCompressionMask: 4054 + iPhoneSdkVersion: 988 + iOSTargetOSVersionString: 11.0 + tvOSSdkVersion: 0 + tvOSRequireExtendedGameController: 0 + tvOSTargetOSVersionString: 11.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: + iOSManualSigningProvisioningProfileType: 0 + tvOSManualSigningProvisioningProfileType: 0 + appleEnableAutomaticSigning: 0 + iOSRequireARKit: 0 + iOSAutomaticallyDetectAndAddCapabilities: 1 + appleEnableProMotion: 0 + shaderPrecisionModel: 0 + clonedFromGUID: 3df0038eaa8740a438c96d5b01ba661e + templatePackageId: com.unity.template.mobile3d@2.0.1 + templateDefaultScene: Assets/Scenes/SampleScene.unity + useCustomMainManifest: 0 + useCustomLauncherManifest: 0 + useCustomMainGradleTemplate: 0 + useCustomLauncherGradleManifest: 0 + useCustomBaseGradleTemplate: 0 + useCustomGradlePropertiesTemplate: 0 + useCustomProguardFile: 0 + AndroidTargetArchitectures: 2 + AndroidTargetDevices: 0 + AndroidSplashScreenScale: 0 + androidSplashScreen: {fileID: 0} + AndroidKeystoreName: + AndroidKeyaliasName: + 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 + AndroidMinifyWithR8: 0 + AndroidMinifyRelease: 0 + AndroidMinifyDebug: 0 + AndroidValidateAppBundleSize: 1 + AndroidAppBundleSizeToValidate: 150 + m_BuildTargetIcons: [] + m_BuildTargetPlatformIcons: + - m_BuildTarget: Android + m_Icons: + - 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_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_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_BuildTargetBatching: + - m_BuildTarget: Standalone + m_StaticBatching: 1 + m_DynamicBatching: 0 + - m_BuildTarget: tvOS + m_StaticBatching: 1 + m_DynamicBatching: 0 + - m_BuildTarget: Android + m_StaticBatching: 1 + m_DynamicBatching: 0 + - m_BuildTarget: iPhone + m_StaticBatching: 1 + m_DynamicBatching: 0 + - m_BuildTarget: WebGL + m_StaticBatching: 0 + m_DynamicBatching: 0 + m_BuildTargetGraphicsJobs: + - m_BuildTarget: MacStandaloneSupport + m_GraphicsJobs: 0 + - m_BuildTarget: Switch + m_GraphicsJobs: 1 + - m_BuildTarget: MetroSupport + m_GraphicsJobs: 1 + - m_BuildTarget: AppleTVSupport + m_GraphicsJobs: 0 + - m_BuildTarget: BJMSupport + m_GraphicsJobs: 1 + - m_BuildTarget: LinuxStandaloneSupport + m_GraphicsJobs: 1 + - m_BuildTarget: PS4Player + m_GraphicsJobs: 1 + - m_BuildTarget: iOSSupport + m_GraphicsJobs: 0 + - m_BuildTarget: WindowsStandaloneSupport + m_GraphicsJobs: 1 + - m_BuildTarget: XboxOnePlayer + m_GraphicsJobs: 1 + - m_BuildTarget: LuminSupport + m_GraphicsJobs: 0 + - m_BuildTarget: AndroidPlayer + m_GraphicsJobs: 0 + - m_BuildTarget: WebGLSupport + m_GraphicsJobs: 0 + m_BuildTargetGraphicsJobMode: + - m_BuildTarget: PS4Player + m_GraphicsJobMode: 0 + - m_BuildTarget: XboxOnePlayer + m_GraphicsJobMode: 0 + m_BuildTargetGraphicsAPIs: + - m_BuildTarget: AndroidPlayer + m_APIs: 0b000000 + m_Automatic: 0 + - m_BuildTarget: iOSSupport + m_APIs: 10000000 + m_Automatic: 1 + - m_BuildTarget: AppleTVSupport + m_APIs: 10000000 + m_Automatic: 1 + - m_BuildTarget: WebGLSupport + m_APIs: 0b000000 + m_Automatic: 1 + m_BuildTargetVRSettings: + - m_BuildTarget: Standalone + m_Enabled: 0 + m_Devices: + - Oculus + - OpenVR + openGLRequireES31: 0 + openGLRequireES31AEP: 0 + openGLRequireES32: 0 + m_TemplateCustomTags: {} + mobileMTRendering: + Android: 1 + iPhone: 1 + tvOS: 1 + m_BuildTargetGroupLightmapEncodingQuality: + - m_BuildTarget: Android + m_EncodingQuality: 1 + - m_BuildTarget: iPhone + m_EncodingQuality: 1 + - m_BuildTarget: tvOS + m_EncodingQuality: 1 + m_BuildTargetGroupLightmapSettings: [] + m_BuildTargetNormalMapEncoding: [] + m_BuildTargetDefaultTextureCompressionFormat: + - m_BuildTarget: Android + m_Format: 3 + playModeTestRunnerEnabled: 0 + runPlayModeTestAsEditModeTest: 0 + actionOnDotNetUnhandledException: 1 + enableInternalProfiler: 0 + logObjCUncaughtExceptions: 1 + enableCrashReportAPI: 0 + cameraUsageDescription: + locationUsageDescription: + microphoneUsageDescription: + bluetoothUsageDescription: + switchNMETAOverride: + switchNetLibKey: + switchSocketMemoryPoolSize: 6144 + switchSocketAllocatorPoolSize: 128 + switchSocketConcurrencyLimit: 14 + switchScreenResolutionBehavior: 2 + switchUseCPUProfiler: 0 + switchUseGOLDLinker: 0 + switchLTOSetting: 0 + switchApplicationID: 0x01004b9000490000 + switchNSODependencies: + 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 + switchTouchScreenUsage: 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 + switchSocketConfigEnabled: 0 + switchTcpInitialSendBufferSize: 32 + switchTcpInitialReceiveBufferSize: 64 + switchTcpAutoSendBufferSizeMax: 256 + switchTcpAutoReceiveBufferSizeMax: 256 + switchUdpSendBufferSize: 9 + switchUdpReceiveBufferSize: 42 + switchSocketBufferEfficiency: 4 + switchSocketInitializeEnabled: 1 + switchNetworkInterfaceManagerInitializeEnabled: 1 + switchPlayerConnectionEnabled: 1 + switchUseNewStyleFilepaths: 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: 1 + 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: 0 + 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 + ps4GPU800MHz: 1 + ps4attribEyeToEyeDistanceSettingVR: 0 + ps4IncludedModules: [] + ps4attribVROutputEnabled: 0 + monoEnv: + splashScreenBackgroundSourceLandscape: {fileID: 0} + splashScreenBackgroundSourcePortrait: {fileID: 0} + blurSplashScreenBackground: 1 + spritePackerPolicy: + webGLMemorySize: 16 + webGLExceptionSupport: 1 + webGLNameFilesAsHashes: 0 + webGLDataCaching: 1 + webGLDebugSymbols: 0 + webGLEmscriptenArgs: + webGLModulesDirectory: + webGLTemplate: APPLICATION:Default + webGLAnalyzeBuildSize: 0 + webGLUseEmbeddedResources: 0 + webGLCompressionFormat: 1 + webGLWasmArithmeticExceptions: 0 + webGLLinkerTarget: 1 + webGLThreadsSupport: 0 + webGLDecompressionFallback: 0 + scriptingDefineSymbols: {} + additionalCompilerArguments: {} + platformArchitecture: {} + scriptingBackend: + Android: 1 + il2cppCompilerConfiguration: {} + managedStrippingLevel: {} + incrementalIl2cppBuild: {} + suppressCommonWarnings: 1 + allowUnsafeCode: 0 + useDeterministicCompilation: 1 + enableRoslynAnalyzers: 1 + additionalIl2CppArgs: + scriptingRuntimeVersion: 1 + gcIncremental: 1 + assemblyVersionValidation: 1 + gcWBarrierValidation: 0 + apiCompatibilityLevelPerPlatform: {} + m_RenderingPath: 1 + m_MobileRenderingPath: 1 + metroPackageName: Template_3D + metroPackageVersion: + metroCertificatePath: + metroCertificatePassword: + metroCertificateSubject: + metroCertificateIssuer: + metroCertificateNotAfter: 0000000000000000 + metroApplicationDescription: Template_3D + 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: + Build: 0 + Collab: 0 + Game Performance: 0 + Legacy Analytics: 0 + Purchasing: 0 + UDP: 0 + UNet: 1 + Unity Ads: 0 + luminIcon: + m_Name: + m_ModelFolderPath: + m_PortalFolderPath: + luminCert: + m_CertPath: + m_SignPackage: 1 + luminIsChannelApp: 0 + luminVersion: + m_VersionCode: 1 + m_VersionName: + apiCompatibilityLevel: 6 + activeInputHandler: 0 + cloudProjectId: 77811eeb-80b1-4e04-803f-50b122fc0f0b + framebufferDepthMemorylessMode: 0 + qualitySettingsNames: [] + projectName: ARDK - SG - PP + organizationId: sg-22-praktikum + cloudEnabled: 0 + legacyClampBlendShapeWeights: 0 + playerDataPath: + forceSRGBBlit: 1 + virtualTexturingSupportEnabled: 0 diff --git a/ProjectSettings/ProjectVersion.txt b/ProjectSettings/ProjectVersion.txt new file mode 100644 index 0000000..90d6509 --- /dev/null +++ b/ProjectSettings/ProjectVersion.txt @@ -0,0 +1,2 @@ +m_EditorVersion: 2021.3.1f1 +m_EditorVersionWithRevision: 2021.3.1f1 (3b70a0754835) diff --git a/ProjectSettings/QualitySettings.asset b/ProjectSettings/QualitySettings.asset new file mode 100644 index 0000000..d3b23fc --- /dev/null +++ b/ProjectSettings/QualitySettings.asset @@ -0,0 +1,238 @@ +%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: Very Low + pixelLightCount: 0 + shadows: 0 + shadowResolution: 0 + shadowProjection: 1 + shadowCascades: 1 + shadowDistance: 15 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 0 + skinWeights: 1 + textureQuality: 1 + anisotropicTextures: 0 + antiAliasing: 0 + softParticles: 0 + softVegetation: 0 + realtimeReflectionProbes: 0 + billboardsFaceCameraPosition: 0 + vSyncCount: 0 + lodBias: 0.3 + 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: 0} + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Low + 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: 16 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + asyncUploadPersistentBuffer: 1 + resolutionScalingFixedDPIFactor: 1 + customRenderPipeline: {fileID: 0} + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Medium + 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: 2 + textureQuality: 0 + anisotropicTextures: 1 + antiAliasing: 0 + softParticles: 0 + softVegetation: 0 + realtimeReflectionProbes: 0 + billboardsFaceCameraPosition: 0 + vSyncCount: 0 + lodBias: 0.7 + 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: 0} + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: High + 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: 2 + textureQuality: 0 + anisotropicTextures: 1 + antiAliasing: 0 + softParticles: 0 + softVegetation: 1 + realtimeReflectionProbes: 1 + billboardsFaceCameraPosition: 1 + vSyncCount: 0 + lodBias: 1 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 256 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + asyncUploadPersistentBuffer: 1 + resolutionScalingFixedDPIFactor: 1 + customRenderPipeline: {fileID: 0} + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Very High + pixelLightCount: 3 + shadows: 2 + shadowResolution: 2 + shadowProjection: 1 + shadowCascades: 2 + shadowDistance: 70 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 1 + skinWeights: 4 + textureQuality: 0 + anisotropicTextures: 1 + antiAliasing: 2 + softParticles: 1 + softVegetation: 1 + realtimeReflectionProbes: 1 + billboardsFaceCameraPosition: 1 + vSyncCount: 0 + lodBias: 1.5 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 1024 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + asyncUploadPersistentBuffer: 1 + resolutionScalingFixedDPIFactor: 1 + customRenderPipeline: {fileID: 0} + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Ultra + pixelLightCount: 4 + shadows: 2 + shadowResolution: 2 + shadowProjection: 1 + shadowCascades: 4 + shadowDistance: 150 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 1 + skinWeights: 4 + textureQuality: 0 + anisotropicTextures: 1 + antiAliasing: 4 + softParticles: 1 + softVegetation: 1 + realtimeReflectionProbes: 1 + billboardsFaceCameraPosition: 1 + vSyncCount: 0 + lodBias: 2 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 4096 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + asyncUploadPersistentBuffer: 1 + resolutionScalingFixedDPIFactor: 1 + customRenderPipeline: {fileID: 0} + excludedTargetPlatforms: [] + m_PerPlatformDefaultQuality: + Android: 2 + Lumin: 5 + Nintendo 3DS: 5 + Nintendo Switch: 5 + PS4: 5 + PSP2: 2 + Stadia: 5 + Standalone: 5 + WebGL: 3 + Windows Store Apps: 5 + XboxOne: 5 + iPhone: 2 + tvOS: 2 diff --git a/ProjectSettings/SceneTemplateSettings.json b/ProjectSettings/SceneTemplateSettings.json new file mode 100644 index 0000000..6f3e60f --- /dev/null +++ b/ProjectSettings/SceneTemplateSettings.json @@ -0,0 +1,167 @@ +{ + "templatePinStates": [], + "dependencyTypeInfos": [ + { + "userAdded": false, + "type": "UnityEngine.AnimationClip", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEditor.Animations.AnimatorController", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.AnimatorOverrideController", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEditor.Audio.AudioMixerController", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.ComputeShader", + "ignore": true, + "defaultInstantiationMode": 1, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.Cubemap", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.GameObject", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEditor.LightingDataAsset", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": false + }, + { + "userAdded": false, + "type": "UnityEngine.LightingSettings", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.Material", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEditor.MonoScript", + "ignore": true, + "defaultInstantiationMode": 1, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.PhysicMaterial", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.PhysicsMaterial2D", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.Rendering.PostProcessing.PostProcessProfile", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.Rendering.PostProcessing.PostProcessResources", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.Rendering.VolumeProfile", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEditor.SceneAsset", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": false + }, + { + "userAdded": false, + "type": "UnityEngine.Shader", + "ignore": true, + "defaultInstantiationMode": 1, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.ShaderVariantCollection", + "ignore": true, + "defaultInstantiationMode": 1, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.Texture", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.Texture2D", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.Timeline.TimelineAsset", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + } + ], + "defaultDependencyTypeInfo": { + "userAdded": false, + "type": "", + "ignore": false, + "defaultInstantiationMode": 1, + "supportsModification": true + }, + "newSceneOverride": 0 +} \ No newline at end of file diff --git a/ProjectSettings/TagManager.asset b/ProjectSettings/TagManager.asset new file mode 100644 index 0000000..1c92a78 --- /dev/null +++ b/ProjectSettings/TagManager.asset @@ -0,0 +1,43 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!78 &1 +TagManager: + serializedVersion: 2 + tags: [] + layers: + - Default + - TransparentFX + - Ignore Raycast + - + - Water + - UI + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + m_SortingLayers: + - name: Default + uniqueID: 0 + locked: 0 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/TimelineSettings.asset b/ProjectSettings/TimelineSettings.asset new file mode 100644 index 0000000..cfaebd7 --- /dev/null +++ b/ProjectSettings/TimelineSettings.asset @@ -0,0 +1,16 @@ +%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: a287be6c49135cd4f9b2b8666c39d999, type: 3} + m_Name: + m_EditorClassIdentifier: + assetDefaultFramerate: 60 + m_DefaultFrameRate: 60 diff --git a/ProjectSettings/UnityConnectSettings.asset b/ProjectSettings/UnityConnectSettings.asset new file mode 100644 index 0000000..6125b30 --- /dev/null +++ b/ProjectSettings/UnityConnectSettings.asset @@ -0,0 +1,35 @@ +%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 + 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/ProjectSettings/boot.config b/ProjectSettings/boot.config new file mode 100644 index 0000000..e69de29 diff --git a/UIElementsSchema/UIElements.xsd b/UIElementsSchema/UIElements.xsd new file mode 100644 index 0000000..8ccfa88 --- /dev/null +++ b/UIElementsSchema/UIElements.xsd @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/UIElementsSchema/Unity.Cloud.Collaborate.Components.ChangeListEntries.xsd b/UIElementsSchema/Unity.Cloud.Collaborate.Components.ChangeListEntries.xsd new file mode 100644 index 0000000..37db2cb --- /dev/null +++ b/UIElementsSchema/Unity.Cloud.Collaborate.Components.ChangeListEntries.xsd @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/UIElementsSchema/Unity.Cloud.Collaborate.Components.xsd b/UIElementsSchema/Unity.Cloud.Collaborate.Components.xsd new file mode 100644 index 0000000..06b7da5 --- /dev/null +++ b/UIElementsSchema/Unity.Cloud.Collaborate.Components.xsd @@ -0,0 +1,332 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/UIElementsSchema/Unity.Cloud.Collaborate.Views.xsd b/UIElementsSchema/Unity.Cloud.Collaborate.Views.xsd new file mode 100644 index 0000000..f6ec2fb --- /dev/null +++ b/UIElementsSchema/Unity.Cloud.Collaborate.Views.xsd @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/UIElementsSchema/Unity.Profiling.Editor.xsd b/UIElementsSchema/Unity.Profiling.Editor.xsd new file mode 100644 index 0000000..32d7ed8 --- /dev/null +++ b/UIElementsSchema/Unity.Profiling.Editor.xsd @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/UIElementsSchema/Unity.UI.Builder.xsd b/UIElementsSchema/Unity.UI.Builder.xsd new file mode 100644 index 0000000..0de8a5b --- /dev/null +++ b/UIElementsSchema/Unity.UI.Builder.xsd @@ -0,0 +1,953 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/UIElementsSchema/UnityEditor.AdaptivePerformance.UI.Editor.xsd b/UIElementsSchema/UnityEditor.AdaptivePerformance.UI.Editor.xsd new file mode 100644 index 0000000..1556599 --- /dev/null +++ b/UIElementsSchema/UnityEditor.AdaptivePerformance.UI.Editor.xsd @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/UIElementsSchema/UnityEditor.Experimental.GraphView.xsd b/UIElementsSchema/UnityEditor.Experimental.GraphView.xsd new file mode 100644 index 0000000..f9b22e3 --- /dev/null +++ b/UIElementsSchema/UnityEditor.Experimental.GraphView.xsd @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/UIElementsSchema/UnityEditor.Overlays.xsd b/UIElementsSchema/UnityEditor.Overlays.xsd new file mode 100644 index 0000000..d60844f --- /dev/null +++ b/UIElementsSchema/UnityEditor.Overlays.xsd @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/UIElementsSchema/UnityEditor.PackageManager.UI.Internal.xsd b/UIElementsSchema/UnityEditor.PackageManager.UI.Internal.xsd new file mode 100644 index 0000000..665abd5 --- /dev/null +++ b/UIElementsSchema/UnityEditor.PackageManager.UI.Internal.xsd @@ -0,0 +1,584 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/UIElementsSchema/UnityEditor.Search.xsd b/UIElementsSchema/UnityEditor.Search.xsd new file mode 100644 index 0000000..216cd6d --- /dev/null +++ b/UIElementsSchema/UnityEditor.Search.xsd @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/UIElementsSchema/UnityEditor.ShortcutManagement.xsd b/UIElementsSchema/UnityEditor.ShortcutManagement.xsd new file mode 100644 index 0000000..400097b --- /dev/null +++ b/UIElementsSchema/UnityEditor.ShortcutManagement.xsd @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/UIElementsSchema/UnityEditor.UIElements.Debugger.xsd b/UIElementsSchema/UnityEditor.UIElements.Debugger.xsd new file mode 100644 index 0000000..a2be34b --- /dev/null +++ b/UIElementsSchema/UnityEditor.UIElements.Debugger.xsd @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/UIElementsSchema/UnityEditor.UIElements.xsd b/UIElementsSchema/UnityEditor.UIElements.xsd new file mode 100644 index 0000000..d16ef98 --- /dev/null +++ b/UIElementsSchema/UnityEditor.UIElements.xsd @@ -0,0 +1,896 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/UIElementsSchema/UnityEngine.UIElements.xsd b/UIElementsSchema/UnityEngine.UIElements.xsd new file mode 100644 index 0000000..60d663f --- /dev/null +++ b/UIElementsSchema/UnityEngine.UIElements.xsd @@ -0,0 +1,896 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file