public void BuildPlaybackPrefab(ProgressBar progress)
        {
            var timeline = ScriptableObject.CreateInstance <TimelineAsset>();

            var animationTrack = timeline.CreateTrack <AnimationTrack>(null, "Playback Animation");

            var clip = generateCompressedClip(progress);

            var playableAsset = ScriptableObject.CreateInstance <AnimationPlayableAsset>();

            playableAsset.clip      = clip;
            playableAsset.hideFlags = HideFlags.HideInInspector | HideFlags.HideInHierarchy;
            playableAsset.name      = "Recorded Animation";

            var timelineClip = animationTrack.CreateClip(clip);

            timelineClip.duration    = clip.length;
            timelineClip.asset       = playableAsset;
            timelineClip.displayName = "Recorded Animation";

            //If a clip is not recordable, it will not show up as editable in the timeline view.
            //For whatever reason unity decided that imported clips are not recordable, so we hack a
            //private variable to force them to be!  This seems to have no ill effects but if things go
            //wrong we can just revert this line
            timelineClip.GetType().GetField("m_Recordable", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(timelineClip, true);

            //Try to generate a leap recording if we have leap data
            RecordingTrack recordingTrack = null;
            LeapRecording  leapRecording  = null;

            string framesPath = Path.Combine(dataFolder.Path, "Frames.data");

            if (File.Exists(framesPath))
            {
                List <Frame> frames = new List <Frame>();

                progress.Begin(1, "Loading Leap Data", "", () => {
                    progress.Step();
                    using (var reader = File.OpenText(framesPath)) {
                        while (true)
                        {
                            string line = reader.ReadLine();
                            if (string.IsNullOrEmpty(line))
                            {
                                break;
                            }

                            frames.Add(JsonUtility.FromJson <Frame>(line));
                        }
                    }
                });

                leapRecording = ScriptableObject.CreateInstance(_leapRecordingType) as LeapRecording;
                if (leapRecording != null)
                {
                    leapRecording.name = "Recorded Leap Data";
                    leapRecording.LoadFrames(frames);
                }
                else
                {
                    Debug.LogError("Unable to create Leap recording: Invalid type specification for "
                                   + "LeapRecording implementation.", this);
                }
            }

            string assetPath = Path.Combine(assetFolder.Path, recordingName + ".asset");

            AssetDatabase.CreateAsset(timeline, assetPath);
            AssetDatabase.AddObjectToAsset(playableAsset, timeline);
            AssetDatabase.AddObjectToAsset(animationTrack, timeline);
            AssetDatabase.AddObjectToAsset(clip, timeline);

            //If we do have a leap recording, create a recording track to house it
            if (leapRecording != null)
            {
                recordingTrack = timeline.CreateTrack <RecordingTrack>(null, "Leap Recording");

                var recordingClip = recordingTrack.CreateDefaultClip();
                recordingClip.duration = leapRecording.length;

                var recordingAsset = recordingClip.asset as RecordingClip;
                recordingAsset.recording = leapRecording;

                AssetDatabase.AddObjectToAsset(leapRecording, timeline);
            }

            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();

            //Create the playable director and link it to the new timeline
            var director = gameObject.AddComponent <PlayableDirector>();

            director.playableAsset = timeline;

            //Create the animator
            gameObject.AddComponent <Animator>();

            //Link the animation track to the animator
            //(it likes to point to gameobject instead of the animator directly)
            director.SetGenericBinding(animationTrack.outputs.Query().First().sourceObject, gameObject);

            //Destroy existing provider
            var provider = gameObject.GetComponentInChildren <LeapProvider>();

            if (provider != null)
            {
                GameObject providerObj = provider.gameObject;
                DestroyImmediate(provider);
                //If a leap recording track exists, spawn a playable provider and link it to the track
                if (recordingTrack != null)
                {
                    var playableProvider = providerObj.AddComponent <LeapPlayableProvider>();
                    director.SetGenericBinding(recordingTrack.outputs.Query().First().sourceObject, playableProvider);
                }
            }

            buildAudioTracks(progress, director, timeline);
            buildMethodRecordingTracks(progress, director, timeline);

            progress.Begin(1, "", "Finalizing Prefab", () => {
                GameObject myGameObject = gameObject;
                DestroyImmediate(this);

                string prefabPath = Path.Combine(assetFolder.Path, recordingName + ".prefab");
                PrefabUtility.SaveAsPrefabAsset(myGameObject, prefabPath.Replace('\\', '/'));
            });
        }
Пример #2
0
        public void BuildPlaybackPrefab(ProgressBar progress)
        {
            var timeline = ScriptableObject.CreateInstance <TimelineAsset>();

            var animationTrack = timeline.CreateTrack <AnimationTrack>(null, "Playback Animation");

            var clip = generateCompressedClip(progress);

            var timelineClip = animationTrack.CreateClip(clip);

            timelineClip.duration        = clip.length;
            timelineClip.asset           = clip;
            timelineClip.underlyingAsset = clip;

            //Try to generate a leap recording if we have leap data
            RecordingTrack recordingTrack = null;
            LeapRecording  leapRecording  = null;

            if (leapData.Count > 0)
            {
                leapRecording = ScriptableObject.CreateInstance(_leapRecordingType) as LeapRecording;
                if (leapRecording != null)
                {
                    leapRecording.LoadFrames(leapData);
                }
                else
                {
                    Debug.LogError("Unable to create Leap recording: Invalid type specification for "
                                   + "LeapRecording implementation.", this);
                }
            }

            string assetPath = Path.Combine(assetFolder.Path, recordingName + ".asset");

            AssetDatabase.CreateAsset(timeline, assetPath);
            AssetDatabase.AddObjectToAsset(animationTrack, timeline);
            AssetDatabase.AddObjectToAsset(clip, timeline);

            //If we do have a leap recording, create a recording track to house it
            if (leapRecording != null)
            {
                recordingTrack = timeline.CreateTrack <RecordingTrack>(null, "Leap Recording");

                var recordingClip = recordingTrack.CreateDefaultClip();
                recordingClip.duration = leapRecording.length;

                var recordingAsset = recordingClip.asset as RecordingClip;
                recordingAsset.recording = leapRecording;

                AssetDatabase.AddObjectToAsset(leapRecording, timeline);
            }

            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();

            foreach (var recording in GetComponentsInChildren <RecordedData>(includeInactive: true))
            {
                DestroyImmediate(recording);
            }

            //Create the playable director and link it to the new timeline
            var director = gameObject.AddComponent <PlayableDirector>();

            director.playableAsset = timeline;

            //Create the animator and link it to the animation track
            var animator = gameObject.AddComponent <Animator>();

            director.SetGenericBinding(animationTrack.outputs.Query().First().sourceObject, animator);

            //Destroy existing provider
            var provider = gameObject.GetComponentInChildren <LeapProvider>();

            if (provider != null)
            {
                GameObject providerObj = provider.gameObject;
                DestroyImmediate(provider);
                //If a leap recording track exists, spawn a playable provider and link it to the track
                if (recordingTrack != null)
                {
                    var playableProvider = providerObj.AddComponent <LeapPlayableProvider>();
                    director.SetGenericBinding(recordingTrack.outputs.Query().First().sourceObject, playableProvider);
                }
            }

            buildAudioTracks(progress, director, timeline);

            progress.Begin(1, "", "Finalizing Prefab", () => {
                GameObject myGameObject = gameObject;
                DestroyImmediate(this);

                string prefabPath = Path.Combine(assetFolder.Path, recordingName + ".prefab");
                PrefabUtility.CreatePrefab(prefabPath.Replace('\\', '/'), myGameObject);
            });
        }