You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
170 lines
6.6 KiB
170 lines
6.6 KiB
using System; |
|
using System.Collections.Generic; |
|
using System.Linq; |
|
using UnityEditor.Build; |
|
using UnityEditor.Build.Reporting; |
|
using UnityEngine.Playables; |
|
using UnityEngine.SceneManagement; |
|
using UnityEngine.Timeline; |
|
|
|
namespace UnityEditor.Timeline.Analytics |
|
{ |
|
class TimelineSceneInfo |
|
{ |
|
public Dictionary<string, int> trackCount = new Dictionary<string, int> |
|
{ |
|
{"ActivationTrack", 0}, |
|
{"AnimationTrack", 0}, |
|
{"AudioTrack", 0}, |
|
{"ControlTrack", 0}, |
|
{"PlayableTrack", 0}, |
|
{"UserType", 0}, |
|
{"Other", 0} |
|
}; |
|
|
|
public Dictionary<string, int> userTrackTypesCount = new Dictionary<string, int>(); |
|
public HashSet<TimelineAsset> uniqueDirectors = new HashSet<TimelineAsset>(); |
|
public int numTracks = 0; |
|
public int minDuration = int.MaxValue; |
|
public int maxDuration = int.MinValue; |
|
public int minNumTracks = int.MaxValue; |
|
public int maxNumTracks = int.MinValue; |
|
public int numRecorded = 0; |
|
} |
|
|
|
[Serializable] |
|
struct TrackInfo |
|
{ |
|
public string name; |
|
public double percent; |
|
} |
|
|
|
[Serializable] |
|
class TimelineEventInfo |
|
{ |
|
public int num_timelines; |
|
public int min_duration, max_duration; |
|
public int min_num_tracks, max_num_tracks; |
|
public double recorded_percent; |
|
public List<TrackInfo> track_info = new List<TrackInfo>(); |
|
public string most_popular_user_track = string.Empty; |
|
|
|
public TimelineEventInfo(TimelineSceneInfo sceneInfo) |
|
{ |
|
num_timelines = sceneInfo.uniqueDirectors.Count; |
|
min_duration = sceneInfo.minDuration; |
|
max_duration = sceneInfo.maxDuration; |
|
min_num_tracks = sceneInfo.minNumTracks; |
|
max_num_tracks = sceneInfo.maxNumTracks; |
|
recorded_percent = Math.Round(100.0 * sceneInfo.numRecorded / sceneInfo.numTracks, 1); |
|
|
|
foreach (KeyValuePair<string, int> kv in sceneInfo.trackCount.Where(x => x.Value > 0)) |
|
{ |
|
track_info.Add(new TrackInfo() |
|
{ |
|
name = kv.Key, |
|
percent = Math.Round(100.0 * kv.Value / sceneInfo.numTracks, 1) |
|
}); |
|
} |
|
|
|
if (sceneInfo.userTrackTypesCount.Any()) |
|
{ |
|
most_popular_user_track = sceneInfo.userTrackTypesCount |
|
.First(x => x.Value == sceneInfo.userTrackTypesCount.Values.Max()).Key; |
|
} |
|
} |
|
|
|
public static bool IsUserType(Type t) |
|
{ |
|
string nameSpace = t.Namespace; |
|
return string.IsNullOrEmpty(nameSpace) || !nameSpace.StartsWith("UnityEngine.Timeline"); |
|
} |
|
} |
|
|
|
|
|
static class TimelineAnalytics |
|
{ |
|
static TimelineSceneInfo _timelineSceneInfo = new TimelineSceneInfo(); |
|
|
|
class TimelineAnalyticsPreProcess : IPreprocessBuildWithReport |
|
{ |
|
public int callbackOrder { get { return 0; } } |
|
public void OnPreprocessBuild(BuildReport report) |
|
{ |
|
_timelineSceneInfo = new TimelineSceneInfo(); |
|
} |
|
} |
|
|
|
class TimelineAnalyticsProcess : IProcessSceneWithReport |
|
{ |
|
public int callbackOrder |
|
{ |
|
get { return 0; } |
|
} |
|
|
|
public void OnProcessScene(Scene scene, BuildReport report) |
|
{ |
|
var timelines = UnityEngine.Object.FindObjectsOfType<PlayableDirector>().Select(pd => pd.playableAsset).OfType<TimelineAsset>().Distinct(); |
|
|
|
foreach (var timeline in timelines) |
|
{ |
|
if (_timelineSceneInfo.uniqueDirectors.Add(timeline)) |
|
{ |
|
_timelineSceneInfo.numTracks += timeline.flattenedTracks.Count(); |
|
_timelineSceneInfo.minDuration = Math.Min(_timelineSceneInfo.minDuration, (int)(timeline.duration * 1000)); |
|
_timelineSceneInfo.maxDuration = Math.Max(_timelineSceneInfo.maxDuration, (int)(timeline.duration * 1000)); |
|
_timelineSceneInfo.minNumTracks = Math.Min(_timelineSceneInfo.minNumTracks, timeline.flattenedTracks.Count()); |
|
_timelineSceneInfo.maxNumTracks = Math.Max(_timelineSceneInfo.maxNumTracks, timeline.flattenedTracks.Count()); |
|
|
|
foreach (var track in timeline.flattenedTracks) |
|
{ |
|
string key = track.GetType().Name; |
|
if (_timelineSceneInfo.trackCount.ContainsKey(key)) |
|
{ |
|
_timelineSceneInfo.trackCount[key]++; |
|
} |
|
else |
|
{ |
|
if (TimelineEventInfo.IsUserType(track.GetType())) |
|
{ |
|
_timelineSceneInfo.trackCount["UserType"]++; |
|
if (_timelineSceneInfo.userTrackTypesCount.ContainsKey(key)) |
|
_timelineSceneInfo.userTrackTypesCount[key]++; |
|
else |
|
_timelineSceneInfo.userTrackTypesCount[key] = 1; |
|
} |
|
else |
|
_timelineSceneInfo.trackCount["Other"]++; |
|
} |
|
|
|
if (track.clips.Any(x => x.recordable)) |
|
_timelineSceneInfo.numRecorded++; |
|
else |
|
{ |
|
var animationTrack = track as AnimationTrack; |
|
if (animationTrack != null) |
|
{ |
|
if (animationTrack.CanConvertToClipMode()) |
|
_timelineSceneInfo.numRecorded++; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
class TimelineAnalyticsPostProcess : IPostprocessBuildWithReport |
|
{ |
|
public int callbackOrder { get { return 0; } } |
|
public void OnPostprocessBuild(BuildReport report) |
|
{ |
|
if (_timelineSceneInfo.uniqueDirectors.Count > 0) |
|
{ |
|
var timelineEvent = new TimelineEventInfo(_timelineSceneInfo); |
|
EditorAnalytics.SendEventTimelineInfo(timelineEvent); |
|
} |
|
} |
|
} |
|
} |
|
}
|
|
|