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); | ||
|  |             } | ||
|  |         } | ||
|  |     } | ||
|  | } |