159 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			159 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System;
 | |
| using UnityEngine.Playables;
 | |
| using UnityEngine.SceneManagement;
 | |
| 
 | |
| namespace UnityEngine.Timeline
 | |
| {
 | |
|     /// <summary>
 | |
|     /// Playable that controls and instantiates a Prefab.
 | |
|     /// </summary>
 | |
|     public class PrefabControlPlayable : PlayableBehaviour
 | |
|     {
 | |
|         GameObject m_Instance;
 | |
| 
 | |
| #if UNITY_EDITOR
 | |
|         private bool m_IsActiveCached;
 | |
| #endif
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Creates a Playable with a PrefabControlPlayable behaviour attached
 | |
|         /// </summary>
 | |
|         /// <param name="graph">The PlayableGraph to inject the Playable into.</param>
 | |
|         /// <param name="prefabGameObject">The prefab to instantiate from</param>
 | |
|         /// <param name="parentTransform">Transform to parent instance to. Can be null.</param>
 | |
|         /// <returns>Returns a Playabe with PrefabControlPlayable behaviour attached.</returns>
 | |
|         public static ScriptPlayable<PrefabControlPlayable> Create(PlayableGraph graph, GameObject prefabGameObject, Transform parentTransform)
 | |
|         {
 | |
|             if (prefabGameObject == null)
 | |
|                 return ScriptPlayable<PrefabControlPlayable>.Null;
 | |
| 
 | |
|             var handle = ScriptPlayable<PrefabControlPlayable>.Create(graph);
 | |
|             handle.GetBehaviour().Initialize(prefabGameObject, parentTransform);
 | |
|             return handle;
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// The instance of the prefab created by this behaviour
 | |
|         /// </summary>
 | |
|         public GameObject prefabInstance
 | |
|         {
 | |
|             get { return m_Instance; }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Initializes the behaviour with a prefab and parent transform
 | |
|         /// </summary>
 | |
|         /// <param name="prefabGameObject">The prefab to instantiate from</param>
 | |
|         /// <param name="parentTransform">Transform to parent instance to. Can be null.</param>
 | |
|         /// <returns>The created instance</returns>
 | |
|         public GameObject Initialize(GameObject prefabGameObject, Transform parentTransform)
 | |
|         {
 | |
|             if (prefabGameObject == null)
 | |
|                 throw new ArgumentNullException("Prefab cannot be null");
 | |
| 
 | |
|             if (m_Instance != null)
 | |
|             {
 | |
|                 Debug.LogWarningFormat("Prefab Control Playable ({0}) has already been initialized with a Prefab ({1}).", prefabGameObject.name, m_Instance.name);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
| #if UNITY_EDITOR
 | |
|                 if (!Application.isPlaying)
 | |
|                 {
 | |
|                     m_Instance = (GameObject)UnityEditor.PrefabUtility.InstantiatePrefab(prefabGameObject, parentTransform);
 | |
|                     UnityEditor.PrefabUtility.prefabInstanceUpdated += OnPrefabUpdated;
 | |
|                 }
 | |
|                 else
 | |
| #endif
 | |
|                 {
 | |
|                     m_Instance = Object.Instantiate(prefabGameObject, parentTransform, false);
 | |
|                 }
 | |
|                 m_Instance.name = prefabGameObject.name + " [Timeline]";
 | |
|                 m_Instance.SetActive(false);
 | |
|                 SetHideFlagsRecursive(m_Instance);
 | |
|             }
 | |
|             return m_Instance;
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// This function is called when the Playable that owns the PlayableBehaviour is destroyed.
 | |
|         /// </summary>
 | |
|         /// <param name="playable">The playable this behaviour is attached to.</param>
 | |
|         public override void OnPlayableDestroy(Playable playable)
 | |
|         {
 | |
|             if (m_Instance)
 | |
|             {
 | |
|                 if (Application.isPlaying)
 | |
|                     Object.Destroy(m_Instance);
 | |
|                 else
 | |
|                     Object.DestroyImmediate(m_Instance);
 | |
|             }
 | |
| 
 | |
| #if UNITY_EDITOR
 | |
|             UnityEditor.PrefabUtility.prefabInstanceUpdated -= OnPrefabUpdated;
 | |
| #endif
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// This function is called when the Playable play state is changed to Playables.PlayState.Playing.
 | |
|         /// </summary>
 | |
|         /// <param name="playable">The Playable that owns the current PlayableBehaviour.</param>
 | |
|         /// <param name="info">A FrameData structure that contains information about the current frame context.</param>
 | |
|         public override void OnBehaviourPlay(Playable playable, FrameData info)
 | |
|         {
 | |
|             if (m_Instance == null)
 | |
|                 return;
 | |
| 
 | |
|             m_Instance.SetActive(true);
 | |
| 
 | |
| #if UNITY_EDITOR
 | |
|             m_IsActiveCached = true;
 | |
| #endif
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// This function is called when the Playable play state is changed to PlayState.Paused.
 | |
|         /// </summary>
 | |
|         /// <param name="playable">The playable this behaviour is attached to.</param>
 | |
|         /// <param name="info">A FrameData structure that contains information about the current frame context.</param>
 | |
|         public override void OnBehaviourPause(Playable playable, FrameData info)
 | |
|         {
 | |
|             // OnBehaviourPause can be called if the graph is stopped for a variety of reasons
 | |
|             //  the effectivePlayState will test if the pause is due to the clip being out of bounds
 | |
|             if (m_Instance != null && info.effectivePlayState == PlayState.Paused)
 | |
|             {
 | |
|                 m_Instance.SetActive(false);
 | |
| #if UNITY_EDITOR
 | |
|                 m_IsActiveCached = false;
 | |
| #endif
 | |
|             }
 | |
|         }
 | |
| 
 | |
| #if UNITY_EDITOR
 | |
|         void OnPrefabUpdated(GameObject go)
 | |
|         {
 | |
|             if (go == m_Instance)
 | |
|             {
 | |
|                 SetHideFlagsRecursive(go);
 | |
|                 go.SetActive(m_IsActiveCached);
 | |
|             }
 | |
|         }
 | |
| 
 | |
| #endif
 | |
| 
 | |
|         static void SetHideFlagsRecursive(GameObject gameObject)
 | |
|         {
 | |
|             if (gameObject == null)
 | |
|                 return;
 | |
| 
 | |
|             gameObject.hideFlags = HideFlags.DontSaveInBuild | HideFlags.DontSaveInEditor;
 | |
|             if (!Application.isPlaying)
 | |
|                 gameObject.hideFlags |= HideFlags.HideInHierarchy;
 | |
|             foreach (Transform child in gameObject.transform)
 | |
|             {
 | |
|                 SetHideFlagsRecursive(child.gameObject);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 |