Extrapolation.cs
3.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
using System;
using UnityEngine;
// Extension methods responsible for managing extrapolation time
namespace UnityEngine.Timeline
{
static class Extrapolation
{
/// <summary>
/// The minimum amount of extrapolation time to apply
/// </summary>
internal static readonly double kMinExtrapolationTime = TimeUtility.kTimeEpsilon * 1000;
// Calculates the extrapolation times
internal static void CalculateExtrapolationTimes(this TrackAsset asset)
{
TimelineClip[] clips = asset.clips;
if (clips == null || clips.Length == 0)
return;
// extrapolation not supported
if (!clips[0].SupportsExtrapolation())
return;
var orderedClips = SortClipsByStartTime(clips);
if (orderedClips.Length > 0)
{
// post extrapolation is the minimum time to the next clip
for (int i = 0; i < orderedClips.Length; i++)
{
double minTime = double.PositiveInfinity;
for (int j = 0; j < orderedClips.Length; j++)
{
if (i == j)
continue;
double deltaTime = orderedClips[j].start - orderedClips[i].end;
if (deltaTime >= -TimeUtility.kTimeEpsilon && deltaTime < minTime)
minTime = Math.Min(minTime, deltaTime);
// check for overlapped clips
if (orderedClips[j].start <= orderedClips[i].end && orderedClips[j].end > orderedClips[i].end)
minTime = 0;
}
minTime = minTime <= kMinExtrapolationTime ? 0 : minTime;
orderedClips[i].SetPostExtrapolationTime(minTime);
}
// the first clip gets pre-extrapolation, then it's only respected if there is no post extrapolation
orderedClips[0].SetPreExtrapolationTime(Math.Max(0, orderedClips[0].start));
for (int i = 1; i < orderedClips.Length; i++)
{
double preTime = 0;
int prevClip = -1;
for (int j = 0; j < i; j++)
{
// overlap, no pre-time
if (orderedClips[j].end > orderedClips[i].start)
{
prevClip = -1;
preTime = 0;
break;
}
double gap = orderedClips[i].start - orderedClips[j].end;
if (prevClip == -1 || gap < preTime)
{
preTime = gap;
prevClip = j;
}
}
// check for a post extrapolation time
if (prevClip >= 0)
{
if (orderedClips[prevClip].postExtrapolationMode != TimelineClip.ClipExtrapolation.None)
preTime = 0;
}
preTime = preTime <= kMinExtrapolationTime ? 0 : preTime;
orderedClips[i].SetPreExtrapolationTime(preTime);
}
}
}
static TimelineClip[] SortClipsByStartTime(TimelineClip[] clips)
{
var orderedClips = new TimelineClip[clips.Length];
Array.Copy(clips, orderedClips, clips.Length);
Array.Sort(orderedClips, (clip1, clip2) => clip1.start.CompareTo(clip2.start));
return orderedClips;
}
}
}