using Newtonsoft.Json; using System; using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Runtime.Serialization; using UnityEngine; namespace Assets.AR { [Serializable] public class RouteDetailData { public RouteInfoData RouteInfo; public List Geometry; public List VideoPoints; public List Splits; public long Record; public long UserRecord; public static RouteDetailData LoadFromFile(string path) { var jsonSerializer = new JsonSerializer(); jsonSerializer.Converters.Add((JsonConverter)new VectorDataConverter()); using (var fileStream = File.Open(path, FileMode.Open)) { using (var reader1 = new StreamReader(fileStream)) { using (var reader2 = new JsonTextReader((TextReader)reader1)) return jsonSerializer.Deserialize((JsonReader)reader2); } } } } public class RouteDetailSplitData { private bool lapFinish; private int lapFinishIndex; public double Distance; public string Name; public bool IsLapFinish => this.lapFinish; public int LapFinishIndex => !this.IsLapFinish ? -1 : this.lapFinishIndex; public void SetLapFinish(bool lapFinish, int lapFinishIndex) { this.lapFinish = lapFinish; this.lapFinishIndex = lapFinishIndex; } public override bool Equals(object obj) { if (obj == null || !this.GetType().Equals(obj.GetType())) return false; var routeDetailSplitData = obj as RouteDetailSplitData; return this.Distance == routeDetailSplitData.Distance && string.Equals(this.Name, routeDetailSplitData.Name); } public override int GetHashCode() { var hashCode = 23 * 31 + this.Distance.GetHashCode(); if (this.Name != null) hashCode = hashCode * 31 + this.Name.GetHashCode(); return hashCode; } } public class RouteVideoPointData { public double Distance; public double VideoTime; } [Serializable] public class RouteInfoData { private double lapLength; private double lapUpclimb; public string Name; public string CountryCode; public string VideoScreen; public string Profile; public int Version; public int Rating; public int RatingCount; public double Length; public int Upclimb; public double MaxSlope; public double AvgSlope; public bool IsFavourite; public string ARFileUrl; public List Videos; public bool SuitableForRunning; public bool SuitableForCycling; public bool IsMultiLap; public int LiveSegmentsCount; public bool HasVideo => this.Videos != null && this.Videos.Count > 0; public bool IsAr => !string.IsNullOrEmpty(this.ARFileUrl); public double LapLength => this.lapLength != 0.0 ? this.lapLength : this.Length; public double LapUpclimb => this.lapUpclimb != 0.0 ? this.lapUpclimb : (double)this.Upclimb; public void SetLapLength(double lapLength) => this.lapLength = lapLength; public void SetLapUpclimb(double lapUpclimb) => this.lapUpclimb = lapUpclimb; } public class RouteVideoData { public const int MobileQuality = 540; public const int DesktopQuality = 720; public const int HdQuality = 1080; public const int QhdQuality = 1440; public bool IsOFlow; public int Quality; public string Url; public long Size; public static int[] AllQualitites() => new int[4] { 540, 720, 1080, 1440 }; public static int[] StreamingQualities() => new int[3] { 540, 720, 1080 }; } public class RouteGeometryPointData { public double Latitude; public double Longitude; public double Distance; public double Altitude; } [Serializable] public class ARData { public ARRouteData Route; public ARObjectData[] Objects; public ARPanoramaData[] Panoramas; public ARPanoramaData[] Panoramas20; public byte[] SaveToByteData() => EncoderUtils.ToGzipBytes(JsonConvert.SerializeObject((object)this)); public static ARData LoadFromByteData(byte[] data) => JsonUtility.FromJson(EncoderUtils.UncompressGzipToString(data)); public static ARData LoadFromFile(string path) { var jsonSerializer = new JsonSerializer(); jsonSerializer.Converters.Add((JsonConverter)new VectorDataConverter()); using (var fileStream = File.Open(path, FileMode.Open)) { using (var reader1 = new StreamReader((Stream)fileStream)) { using (var reader2 = new JsonTextReader((TextReader)reader1)) return jsonSerializer.Deserialize((JsonReader)reader2); } } } } public class VectorDataConverter : JsonConverter { public override bool CanConvert(Type objectType) => objectType == typeof(VectorData); public override object ReadJson( JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var vectorData = new VectorData(); reader.Read(); vectorData.x = (float)reader.ReadAsDouble().Value; reader.Read(); vectorData.y = (float)reader.ReadAsDouble().Value; reader.Read(); vectorData.z = (float)reader.ReadAsDouble().Value; reader.Read(); return (object)vectorData; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) => throw new NotImplementedException(); } [Serializable] public class ARObjectData { [OptionalField] public string Hash; public int ObjectTypeId; public float Distance; public VectorData PositionOffset; public VectorData RotationOffset; public VectorData Scale; public float ManualVisibility; public ARObjectTimeTransformData[] TimeData; public string CustomUrl; public string ArName; } [Serializable] public class ARPanoramaData { public string name; public string url; public float frame; public int visibilityRear; public int visibilityFront; public float[] matrix; } [Serializable] public class ARObjectTimeTransformData { public int Frame; public float Distance; public VectorData PositionOffset; public VectorData RotationOffset; public VectorData Scale; } [Serializable] public class ARRouteData { public int[] Visibility; public VectorData[] CameraPositions; public VectorData[] CameraRotations; public VectorData[] CameraRotationsRear; public float[] LightRotationFrames; public VectorData[] LightRotations; public float[] ShadowIntensityFrames; public float[] ShadowIntensities; public float[] SphericalHarmonics; public int[] SlamSegments; public CameraProjectionParameters[] CameraProjectionParameters; public bool LeftHanded; public int VideoFrameOffset; public int VideoFrameOffsetMac = -1; public float CameraHeight; public float RiderScale = 1f; public int[] LeftSideOffsetFrames; public float[] LeftSideOffsets; public int[] RightSideOffsetFrames; public float[] RightSideOffsets; public VectorData CameraRotationsOffset; public float Lane; } public class VectorData { public float x; public float y; public float z; public Vector3 ToUnityVector() => new Vector3(this.x, this.y, this.z); public VectorData() { } public VectorData(Vector3 unityVector) { this.x = unityVector.x; this.y = unityVector.y; this.z = unityVector.z; } } [Serializable] public class CameraProjectionParameters { public float alpha; public float beta; public float cx; public float cy; public CameraProjectionParameters Clone() => new CameraProjectionParameters() { alpha = this.alpha, beta = this.beta, cx = this.cx, cy = this.cy }; public static CameraProjectionParameters Lerp( CameraProjectionParameters a, CameraProjectionParameters b, float t) { return new CameraProjectionParameters() { alpha = Mathf.Lerp(a.alpha, b.alpha, t), beta = Mathf.Lerp(a.beta, b.beta, t), cx = Mathf.Lerp(a.cx, b.cx, t), cy = Mathf.Lerp(a.cy, b.cy, t) }; } } }