Created
March 7, 2021 08:27
-
-
Save tkymx/e7d65cceec76d2ec32def19fa7335367 to your computer and use it in GitHub Desktop.
CloneTimelineAsset の複製
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private class TimelinePrivateMethodAndField : ITimelinePrivateMethodAndField | |
{ | |
private readonly MethodInfo _timelineAddMethod; | |
private readonly MethodInfo _timelineRemoveMethod; | |
private readonly MethodInfo _trackAddMethod; | |
private readonly MethodInfo _trackRemoveMethod; | |
private readonly FieldInfo _trackParentField; | |
public TimelinePrivateMethodAndField() | |
{ | |
GetPrivateMethodAndField( | |
out _timelineAddMethod, | |
out _timelineRemoveMethod, | |
out _trackAddMethod, | |
out _trackRemoveMethod, | |
out _trackParentField); | |
} | |
public void AddTrackToTimeline(TimelineAsset timelineAsset, TrackAsset trackAsset) | |
{ | |
_timelineAddMethod.Invoke(timelineAsset, new object[]{trackAsset}); | |
} | |
public void RemoveTrackFromTimeline(TimelineAsset timelineAsset, TrackAsset trackAsset) | |
{ | |
_timelineRemoveMethod.Invoke(timelineAsset, new object[] {trackAsset}); | |
} | |
public void AddClipToTrack(TrackAsset trackAsset, PlayableAsset playableAsset) | |
{ | |
_trackAddMethod.Invoke(trackAsset, new object[] {playableAsset}); | |
} | |
public void RemoveClipFromTrack(TrackAsset trackAsset, PlayableAsset playableAsset) | |
{ | |
_trackRemoveMethod.Invoke(trackAsset, new object[] {playableAsset}); | |
} | |
public void SetParentToTrack(TrackAsset trackAsset, PlayableAsset parent) | |
{ | |
_trackParentField.SetValue(trackAsset, parent); | |
} | |
private static void GetPrivateMethodAndField( | |
out MethodInfo timelineAddMethod, | |
out MethodInfo timelineRemoveMethod, | |
out MethodInfo trackAddMethod, | |
out MethodInfo trackRemoveMethod, | |
out FieldInfo trackParentField) | |
{ | |
var timelineType = typeof(TimelineAsset); | |
timelineAddMethod = timelineType.GetMethod("AddTrackInternal",BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.NonPublic); | |
timelineRemoveMethod = timelineType.GetMethod("RemoveTrack",BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.NonPublic); | |
if (timelineAddMethod == null || timelineRemoveMethod == null) | |
{ | |
throw new Exception("AddTrackInternal と RemoveTrack が見つかりません"); | |
} | |
var trackType = typeof(TrackAsset); | |
trackAddMethod = trackType.GetMethod("AddChild",BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.NonPublic); | |
trackRemoveMethod = trackType.GetMethod("RemoveSubTrack",BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.NonPublic); | |
trackParentField = trackType.GetField("m_Parent", BindingFlags.Instance | BindingFlags.NonPublic); | |
if (trackAddMethod == null || trackRemoveMethod == null || trackParentField == null) | |
{ | |
throw new Exception("AddChild と RemoveSubTrack と m_Parent が見つかりません"); | |
} | |
} | |
} | |
private static TimelineAsset CloneTimelineAsset(PlayableDirector playableDirector, TimelineAsset sourceAsset) | |
{ | |
// 親情報の保存 | |
var parents = sourceAsset.GetOutputTracks().Select(__ => __.parent).ToList(); | |
// TimeLineAsset のインスタンス化 | |
var timelineInstance = Object.Instantiate(sourceAsset); | |
timelineInstance.name = sourceAsset.name; | |
// メソッド取得 | |
var timelinePrivateMethodAndField = new TimelinePrivateMethodAndField(); | |
// トラックのインスタンス化 | |
InstantiateTrack(playableDirector, timelineInstance, timelinePrivateMethodAndField); | |
// 親の再設定 | |
var count = 0; | |
foreach (var trackAsset in sourceAsset.GetOutputTracks()) | |
{ | |
var parent = parents[count]; | |
timelinePrivateMethodAndField.SetParentToTrack(trackAsset, parent); | |
count++; | |
} | |
return timelineInstance; | |
} | |
private static void InstantiateTrack(PlayableDirector playableDirector, TimelineAsset timelineInstance,ITimelinePrivateMethodAndField timelinePrivateMethodAndField) | |
{ | |
foreach (var trackAsset in timelineInstance.GetRootTracks()) | |
{ | |
if (trackAsset == timelineInstance.markerTrack) | |
{ | |
continue; | |
} | |
var trackInstance = Object.Instantiate<TrackAsset>(trackAsset); | |
trackInstance.name = trackAsset.name; | |
timelinePrivateMethodAndField.AddTrackToTimeline(timelineInstance, trackInstance); | |
timelinePrivateMethodAndField.RemoveTrackFromTimeline(timelineInstance, trackAsset); | |
ReplaceBinding(playableDirector, trackAsset, trackInstance); | |
InstantiateClipAsset(trackInstance); | |
InstantiateChildTrackAsset(playableDirector, trackInstance, timelinePrivateMethodAndField); | |
} | |
} | |
private static void InstantiateChildTrackAsset(PlayableDirector playableDirector, TrackAsset trackInstance, ITimelinePrivateMethodAndField timelinePrivateMethodAndField) | |
{ | |
foreach (var childTrack in trackInstance.GetChildTracks()) | |
{ | |
var childTrackInstance = Object.Instantiate<TrackAsset>(childTrack); | |
childTrackInstance.name = childTrack.name; | |
timelinePrivateMethodAndField.AddClipToTrack(trackInstance, childTrackInstance); | |
timelinePrivateMethodAndField.RemoveClipFromTrack(trackInstance, childTrack); | |
ReplaceBinding(playableDirector, childTrack, childTrackInstance); | |
InstantiateClipAsset(trackInstance); | |
InstantiateChildTrackAsset(playableDirector, childTrackInstance, timelinePrivateMethodAndField); | |
} | |
} | |
private static void ReplaceBinding(PlayableDirector playableDirector, TrackAsset source, TrackAsset destination) | |
{ | |
var genericBinding = playableDirector.GetGenericBinding(source); | |
playableDirector.SetGenericBinding(destination, genericBinding); | |
} | |
private static void InstantiateClipAsset(TrackAsset trackInstance) | |
{ | |
foreach (var timelineClip in trackInstance.GetClips()) | |
{ | |
var clipInstance = Object.Instantiate(timelineClip.asset); | |
clipInstance.name = timelineClip.asset.name; | |
timelineClip.asset = clipInstance; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment