A game about forced loneliness, made by TACStudios
at master 187 lines 6.0 kB view raw
1//#define ANALYTICS_DEBUG 2using System; 3using System.Collections.Generic; 4using System.Diagnostics; 5using System.Linq; 6using System.Text; 7using UnityEngine.Analytics; 8using UnityEngine.Timeline; 9 10namespace UnityEditor.Timeline 11{ 12 class TimelineWindowAnalytics 13 { 14 const string vendorKey = "unity.timeline"; 15 const string eventName = "timeline_editor_info"; 16 const int version = 2; 17 const int maxEventsPerHour = 1000; 18 const int maxNumberOfElements = 1000; 19 20 [Serializable] 21 internal struct timeline_asset_stats 22#if UNITY_2023_2_OR_NEWER 23 : IAnalytic.IData 24#endif 25 { 26 public string asset_guid; 27 public double duration; 28 public double frame_rate; 29 public List<track_asset_stats> track_stats; 30 public double mix_samples_count, ripple_samples_count, replace_samples_count; 31 public string display_format; 32 } 33 34 [Serializable] 35 internal struct track_asset_stats 36 { 37 public string track_type; 38 public int clip_count; 39 public int marker_count; 40 } 41 42 class WindowAnalyticsStats 43 { 44 internal int[] editModeSamples = new int[3]; // EditModes 45 } 46 47#if UNITY_2023_2_OR_NEWER 48 [AnalyticInfo( 49 eventName: eventName, 50 vendorKey: vendorKey, 51 version: version, 52 maxEventsPerHour: maxEventsPerHour, 53 maxNumberOfElements: maxNumberOfElements)] 54 class TimelineWindowAnalyticsEvent : IAnalytic 55 { 56 public timeline_asset_stats timelineStats { get; } 57 bool m_CanSendData; 58 59 public TimelineWindowAnalyticsEvent() 60 { 61 m_CanSendData = GenerateTimelineAssetStats(out timeline_asset_stats data); 62 timelineStats = data; 63 } 64 65 public void Send() 66 { 67 if (m_CanSendData) 68 EditorAnalytics.SendAnalytic(this); 69 } 70 71 bool IAnalytic.TryGatherData(out IAnalytic.IData data, out Exception error) 72 { 73 error = null; 74 data = timelineStats; 75 return true; 76 } 77 } 78#endif 79 80 static WindowAnalyticsStats analyticsStats = new WindowAnalyticsStats(); 81 82 public void SendPlayEvent(bool start) 83 { 84 if (!start || !EditorAnalytics.enabled) 85 return; 86 87#if UNITY_2023_2_OR_NEWER 88 var analyticsEvent = new TimelineWindowAnalyticsEvent(); 89 LogAnalyticsData(analyticsEvent.timelineStats); 90 analyticsEvent.Send(); 91#else 92 EditorAnalytics.RegisterEventWithLimit(eventName, maxEventsPerHour, maxNumberOfElements, vendorKey, version); 93 var ret = GenerateTimelineAssetStats(out var data); 94 if (!ret) 95 return; 96 LogAnalyticsData(data); 97 EditorAnalytics.SendEventWithLimit(eventName, data, version); 98#endif 99 SendAfterSequenceChangeEvent(); 100 } 101 102 public void SendAfterSequenceChangeEvent() 103 { 104 analyticsStats = new WindowAnalyticsStats(); // Wipe Window Stats 105 } 106 107 public void SendManipulationEndedEvent() 108 { 109 analyticsStats.editModeSamples[(int)EditMode.editType]++; 110 } 111 112 internal static bool GenerateTimelineAssetStats(out timeline_asset_stats data) 113 { 114 var timeline = TimelineEditor.inspectedAsset; 115 if (timeline == null || 116 !AssetDatabase.TryGetGUIDAndLocalFileIdentifier(timeline, out var guid, out long _)) 117 { 118 data = new timeline_asset_stats(); 119 return false; 120 } 121 122 data = new timeline_asset_stats 123 { 124 asset_guid = guid, 125 duration = timeline.duration, 126 frame_rate = timeline.editorSettings.frameRate, 127 track_stats = GetTrackAssetStats(timeline), 128 display_format = TimelinePreferences.instance.timeFormat.ConvertToString(), 129 mix_samples_count = analyticsStats.editModeSamples[(int)EditMode.EditType.Mix], 130 ripple_samples_count = analyticsStats.editModeSamples[(int)EditMode.EditType.Ripple], 131 replace_samples_count = analyticsStats.editModeSamples[(int)EditMode.EditType.Replace], 132 }; 133 134 return true; 135 } 136 137 static List<track_asset_stats> GetTrackAssetStats(TimelineAsset timeline) 138 { 139 var ret = new List<track_asset_stats>(); 140 foreach (var track in timeline.flattenedTracks) 141 { 142 ret.Add(new track_asset_stats 143 { 144 track_type = track.GetType().FullName, 145 clip_count = track.GetClips().Count(), 146 marker_count = track.GetMarkers().Count() 147 } 148 ); 149 } 150 return ret; 151 } 152 153 [Conditional("ANALYTICS_DEBUG")] 154 static void LogAnalyticsData(timeline_asset_stats data) 155 { 156 UnityEngine.Debug.Log(UnityEngine.JsonUtility.ToJson(data, true)); 157 } 158 } 159 160 static class ConversionUtilities 161 { 162 internal static string ConvertToString<T>(this T e) where T : Enum 163 { 164 return Enum.GetName(typeof(T), e).ToSnakeCase(); 165 } 166 167 static string ToSnakeCase(this string str) 168 { 169 var sb = new StringBuilder(); 170 for (var i = 0; i < str.Length - 1; ++i) 171 { 172 var ch = str[i]; 173 var nCh = str[i + 1]; 174 if (char.IsUpper(ch) && char.IsLower(nCh)) 175 { 176 sb.Append("_"); 177 } 178 179 sb.Append(ch.ToString().ToLower()); 180 } 181 182 sb.Append(str[str.Length - 1].ToString().ToLower()); 183 184 return sb.ToString().TrimStart('_'); 185 } 186 } 187}