ccl4/blueberryPeak/Assets/Wwise/Timeline/Runtime/AkTimelineEventPlayable.cs
AgentSchmisch 9144907a10 ANGST
2025-06-12 18:45:34 +02:00

773 lines
23 KiB
C#

using System;
using System.Collections.Generic;
#if !(UNITY_DASHBOARD_WIDGET || UNITY_WEBPLAYER || UNITY_WII || UNITY_WIIU || UNITY_NACL || UNITY_FLASH || UNITY_BLACKBERRY) // Disable under unsupported platforms.
#if !UNITY_2019_1_OR_NEWER
#define AK_ENABLE_TIMELINE
#endif
#if AK_ENABLE_TIMELINE
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2025 Audiokinetic Inc.
*******************************************************************************/
/// @brief Defines the behavior of a \ref AkTimelineEventPlayable within a \ref AkTimelineEventTrack.
/// \sa
/// - \ref AkTimelineEventTrack
/// - \ref AkTimelineEventPlayable
public class AkTimelineEventPlayableBehavior : UnityEngine.Playables.PlayableBehaviour
{
private float currentDuration = -1f;
private float currentDurationProportion = 1f;
private bool eventIsPlaying
{
get
{
return playingId != 0;
}
}
private float previousEventStartTime;
private uint playingId = 0;
private const uint CallbackFlags = (uint)(AkCallbackType.AK_EndOfEvent | AkCallbackType.AK_Duration);
private void CallbackHandler(object in_cookie, AkCallbackType in_type, AkCallbackInfo in_info)
{
if (in_type == AkCallbackType.AK_EndOfEvent)
{
StopEvent();
}
else if (in_type == AkCallbackType.AK_Duration)
{
var estimatedDuration = (in_info as AkDurationCallbackInfo).fEstimatedDuration;
currentDuration = estimatedDuration * currentDurationProportion / 1000f;
}
}
#if UNITY_EDITOR
private static bool CanPostEvents
{
get { return UnityEditor.SessionState.GetBool("AkTimelineEventPlayableBehavior.CanPostEvents", true); }
set { UnityEditor.SessionState.SetBool("AkTimelineEventPlayableBehavior.CanPostEvents", value); }
}
[UnityEditor.InitializeOnLoadMethod]
private static void DetermineCanPostEvents()
{
if (UnityEditor.AssetDatabase.IsAssetImportWorkerProcess())
{
return;
}
UnityEditor.Compilation.CompilationPipeline.assemblyCompilationFinished += (string text, UnityEditor.Compilation.CompilerMessage[] messages) =>
{
if (!UnityEditor.EditorApplication.isPlaying)
{
CanPostEvents = true;
}
};
UnityEditor.EditorApplication.playModeStateChanged += (UnityEditor.PlayModeStateChange playMode) =>
{
if (playMode == UnityEditor.PlayModeStateChange.ExitingEditMode)
{
CanPostEvents = true;
}
if (playMode == UnityEditor.PlayModeStateChange.EnteredEditMode)
{
CanPostEvents = true;
}
};
}
#endif
[System.Flags]
private enum Actions
{
None = 0,
Playback = 1 << 0,
Retrigger = 1 << 1,
DelayedStop = 1 << 2,
Seek = 1 << 3,
FadeIn = 1 << 4,
FadeOut = 1 << 5
}
private Actions requiredActions;
private const int scrubPlaybackLengthMs = 100;
public AK.Wwise.Event akEvent;
public float eventDurationMax;
public float eventDurationMin;
public float blendInDuration;
public float blendOutDuration;
public float easeInDuration;
public float easeOutDuration;
public AkCurveInterpolation blendInCurve;
public AkCurveInterpolation blendOutCurve;
public UnityEngine.GameObject eventObject;
public bool retriggerEvent;
public bool StopEventAtClipEnd;
public bool PrintDebugInformation = false;
private bool IsScrubbing(UnityEngine.Playables.Playable playable, UnityEngine.Playables.FrameData info)
{
#if UNITY_EDITOR
if (!UnityEngine.Application.isPlaying)
{
return info.evaluationType == UnityEngine.Playables.FrameData.EvaluationType.Evaluate;
}
#endif
var previousTime = UnityEngine.Playables.PlayableExtensions.GetPreviousTime(playable);
var currentTime = UnityEngine.Playables.PlayableExtensions.GetTime(playable);
var computedDelta = System.Math.Abs(currentTime - previousTime);
// Unfortunately, we can't use info.seekOccurred, because it is always true.
// When time is explicitely set using playable.time, deltaTime is zero, evaluationType is Evaluate, and
// either previous time or current time is non-zero
// However, if time is added to playable.time (for example, playable.time += 1;), evaluationType remains
// Playing.
return (info.deltaTime == 0 && (previousTime >= 0 || currentTime >= 0)) || (computedDelta > info.deltaTime);
}
void PrintInfo(string FunctionName, UnityEngine.Playables.Playable playable, UnityEngine.Playables.FrameData info)
{
if (PrintDebugInformation)
{
var previousTime = UnityEngine.Playables.PlayableExtensions.GetPreviousTime(playable);
var currentTime = UnityEngine.Playables.PlayableExtensions.GetTime(playable);
var computedDelta = System.Math.Abs(currentTime - previousTime);
UnityEngine.Debug.Log($"{FunctionName}: prevTime={previousTime}; curTime={currentTime}; computedDelta={computedDelta}; evalType={info.evaluationType}; deltaTime={info.deltaTime}; playState={info.effectivePlayState}; timeHeld={info.timeHeld}; speed={info.effectiveSpeed}; parentSpeed={info.effectiveParentSpeed}");
}
}
public override void PrepareFrame(UnityEngine.Playables.Playable playable, UnityEngine.Playables.FrameData info)
{
base.PrepareFrame(playable, info);
PrintInfo("PrepareFrame", playable, info);
if (akEvent == null)
{
return;
}
var shouldPlay = ShouldPlay(playable);
if (IsScrubbing(playable, info) && shouldPlay)
{
requiredActions |= Actions.Seek;
if (playingId == 0)
{
requiredActions |= Actions.Playback;
#if UNITY_EDITOR
if (!UnityEngine.Application.isPlaying)
{
// If we've explicitly set the playhead, only play a small snippet.
requiredActions |= Actions.DelayedStop;
}
#endif
CheckForFadeInFadeOut(playable);
}
}
else if (shouldPlay && playingId == 0 && (requiredActions & Actions.Playback) == 0)
{
// The clip is playing but the event hasn't been triggered. We need to start the event and jump to the correct time.
requiredActions |= Actions.Retrigger;
CheckForFadeInFadeOut(playable);
}
else
{
CheckForFadeOut(playable, UnityEngine.Playables.PlayableExtensions.GetTime(playable));
}
}
private const float alph = 0.05f;
public override void OnBehaviourPlay(UnityEngine.Playables.Playable playable, UnityEngine.Playables.FrameData info)
{
PrintInfo("OnBehaviourPlay", playable, info);
base.OnBehaviourPlay(playable, info);
if (akEvent == null)
{
return;
}
if (!ShouldPlay(playable))
{
return;
}
requiredActions |= Actions.Playback;
if (IsScrubbing(playable, info))
{
#if UNITY_EDITOR
if (!UnityEngine.Application.isPlaying)
{
// If we've explicitly set the playhead, only play a small snippet.
requiredActions |= Actions.DelayedStop;
}
#endif
}
else if (GetProportionalTime(playable) > alph)
{
// we need to jump to the correct position in the case where the event is played from some non-start position.
requiredActions |= Actions.Seek;
}
CheckForFadeInFadeOut(playable);
}
public override void OnBehaviourPause(UnityEngine.Playables.Playable playable, UnityEngine.Playables.FrameData info)
{
PrintInfo("OnBehaviourPause", playable, info);
base.OnBehaviourPause(playable, info);
if (eventObject != null && akEvent != null && StopEventAtClipEnd)
{
StopEvent();
}
}
public override void ProcessFrame(UnityEngine.Playables.Playable playable, UnityEngine.Playables.FrameData info, object playerData)
{
PrintInfo("ProcessFrame", playable, info);
base.ProcessFrame(playable, info, playerData);
if (akEvent == null)
{
return;
}
var obj = playerData as UnityEngine.GameObject;
if (obj != null)
{
eventObject = obj;
}
if (eventObject == null)
{
return;
}
if ((requiredActions & Actions.Playback) != 0)
{
PlayEvent();
}
else if ((requiredActions & Actions.Seek) != 0)
{
SeekToTime(playable);
}
if ((requiredActions & Actions.Retrigger) != 0)
{
RetriggerEvent(playable);
}
if ((requiredActions & Actions.DelayedStop) != 0)
{
StopEvent(scrubPlaybackLengthMs);
}
if ((requiredActions & Actions.FadeOut) != 0)
{
TriggerFadeOut(playable);
}
if ((requiredActions & Actions.FadeIn) != 0)
{
TriggerFadeIn(playable);
}
requiredActions = Actions.None;
}
/** Check the playable time against the Wwise event duration to see if playback should occur.
*/
private bool ShouldPlay(UnityEngine.Playables.Playable playable)
{
var previousTime = UnityEngine.Playables.PlayableExtensions.GetPreviousTime(playable);
var currentTime = UnityEngine.Playables.PlayableExtensions.GetTime(playable);
#if UNITY_EDITOR
// In editor, do not automatically play the event if the cursor is already in the section.
if (!UnityEditor.EditorApplication.isPlaying)
{
if (previousTime == 0.0 && System.Math.Abs(currentTime - previousTime) > 1.0)
{
return false;
}
}
#endif
if (previousTime > currentTime)
{
return true;
}
if (retriggerEvent)
{
return true;
}
// If max and min duration values from metadata are equal, we can assume a deterministic event.
if (eventDurationMax.Equals(eventDurationMin) && !eventDurationMin.Equals(-1f))
{
return currentTime < eventDurationMax;
}
currentTime -= previousEventStartTime;
var maxDuration = currentDuration.Equals(-1f) ? (float)UnityEngine.Playables.PlayableExtensions.GetDuration(playable) : currentDuration;
return currentTime < maxDuration;
}
private void CheckForFadeInFadeOut(UnityEngine.Playables.Playable playable)
{
var currentClipTime = UnityEngine.Playables.PlayableExtensions.GetTime(playable);
if (blendInDuration > currentClipTime || easeInDuration > currentClipTime)
{
requiredActions |= Actions.FadeIn;
}
CheckForFadeOut(playable, currentClipTime);
}
private void CheckForFadeOut(UnityEngine.Playables.Playable playable, double currentClipTime)
{
var timeLeft = UnityEngine.Playables.PlayableExtensions.GetDuration(playable) - currentClipTime;
if (blendOutDuration >= timeLeft || easeOutDuration >= timeLeft)
{
requiredActions |= Actions.FadeOut;
}
}
private void TriggerFadeIn(UnityEngine.Playables.Playable playable)
{
var currentClipTime = UnityEngine.Playables.PlayableExtensions.GetTime(playable);
var fadeDuration = UnityEngine.Mathf.Max(easeInDuration, blendInDuration) - currentClipTime;
if (fadeDuration > 0)
{
AkUnitySoundEngine.ExecuteActionOnPlayingID(AkActionOnEventType.AkActionOnEventType_Pause, playingId, 0, blendInCurve);
AkUnitySoundEngine.ExecuteActionOnPlayingID(AkActionOnEventType.AkActionOnEventType_Resume, playingId, (int)(fadeDuration * 1000), blendInCurve);
}
}
private void TriggerFadeOut(UnityEngine.Playables.Playable playable)
{
var fadeDuration = UnityEngine.Playables.PlayableExtensions.GetDuration(playable) - UnityEngine.Playables.PlayableExtensions.GetTime(playable);
AkUnitySoundEngine.ExecuteActionOnPlayingID(AkActionOnEventType.AkActionOnEventType_Stop, playingId, (int)(fadeDuration * 1000), blendOutCurve);
}
private void StopEvent(int transition = 0)
{
if (playingId == 0)
{
return;
}
AkUnitySoundEngine.ExecuteActionOnPlayingID(AkActionOnEventType.AkActionOnEventType_Stop, playingId);
playingId = 0;
}
private bool PostEvent()
{
#if UNITY_EDITOR
if (!CanPostEvents)
{
playingId = AkUnitySoundEngine.AK_INVALID_PLAYING_ID;
}
#endif
if(playingId == 0)
{
playingId = akEvent.Post(eventObject, CallbackFlags, CallbackHandler, null);
return playingId != 0;
}
return false;
}
private void PlayEvent()
{
if (!PostEvent())
{
return;
}
currentDurationProportion = 1f;
previousEventStartTime = 0f;
}
private void RetriggerEvent(UnityEngine.Playables.Playable playable)
{
if (!PostEvent())
{
return;
}
currentDurationProportion = 1f - SeekToTime(playable);
previousEventStartTime = (float)UnityEngine.Playables.PlayableExtensions.GetTime(playable);
}
private float GetProportionalTime(UnityEngine.Playables.Playable playable)
{
// If max and min duration values from metadata are equal, we can assume a deterministic event.
if (eventDurationMax == eventDurationMin && eventDurationMin != -1f)
{
// If the timeline clip has length greater than the event duration, we want to loop.
return (float)UnityEngine.Playables.PlayableExtensions.GetTime(playable) % eventDurationMax / eventDurationMax;
}
var currentTime = (float)UnityEngine.Playables.PlayableExtensions.GetTime(playable) - previousEventStartTime;
if (currentTime < 0)
{
return -1f;
}
var maxDuration = currentDuration == -1f ? (float)UnityEngine.Playables.PlayableExtensions.GetDuration(playable) : currentDuration;
// If the timeline clip has length greater than the event duration, we want to loop.
return currentTime % maxDuration / maxDuration;
}
// Seek to the current time, taking looping into account.
private float SeekToTime(UnityEngine.Playables.Playable playable)
{
var proportionalTime = GetProportionalTime(playable);
if (proportionalTime >= 1f) // Avoids Wwise "seeking beyond end of event: audio will stop" error.
{
return 1f;
}
if (proportionalTime < 0f)
{
return 0f;
}
#if UNITY_EDITOR
if (!CanPostEvents)
{
return proportionalTime;
}
#endif
if (playingId != 0)
{
AkUnitySoundEngine.SeekOnEvent(akEvent.Id, eventObject, proportionalTime, false, playingId);
}
return proportionalTime;
}
}
/// @brief A playable asset containing a Wwise event that can be placed within a \ref AkTimelineEventTrack in a timeline.
/// @details Use this class to play Wwise events from a timeline and synchronize them to the animation. Events will be emitted from the GameObject that is bound to the AkTimelineEventTrack.
/// \sa
/// - \ref AkTimelineEventTrack
/// - \ref AkTimelineEventPlayableBehavior
public class AkTimelineEventPlayable : UnityEngine.Playables.PlayableAsset, UnityEngine.Timeline.ITimelineClipAsset
{
public AK.Wwise.Event akEvent = new AK.Wwise.Event();
[UnityEngine.SerializeField]
private AkCurveInterpolation blendInCurve = AkCurveInterpolation.AkCurveInterpolation_Linear;
[UnityEngine.SerializeField]
private AkCurveInterpolation blendOutCurve = AkCurveInterpolation.AkCurveInterpolation_Linear;
public float eventDurationMax = -1f;
public float eventDurationMin = -1f;
[System.NonSerialized]
public UnityEngine.Timeline.TimelineClip owningClip;
[UnityEngine.SerializeField]
private bool retriggerEvent = false;
public bool UseWwiseEventDuration = true;
public bool PrintDebugInformation = false;
[UnityEngine.SerializeField]
private bool StopEventAtClipEnd = true;
UnityEngine.Timeline.ClipCaps UnityEngine.Timeline.ITimelineClipAsset.clipCaps
{
get { return UnityEngine.Timeline.ClipCaps.Looping | UnityEngine.Timeline.ClipCaps.Blending; }
}
public override UnityEngine.Playables.Playable CreatePlayable(UnityEngine.Playables.PlayableGraph graph, UnityEngine.GameObject owner)
{
var playable = UnityEngine.Playables.ScriptPlayable<AkTimelineEventPlayableBehavior>.Create(graph);
if (akEvent == null)
{
return playable;
}
var b = playable.GetBehaviour();
b.akEvent = akEvent;
b.blendInCurve = blendInCurve;
b.blendOutCurve = blendOutCurve;
b.PrintDebugInformation = PrintDebugInformation;
if (owningClip != null)
{
b.easeInDuration = (float)owningClip.easeInDuration;
b.easeOutDuration = (float)owningClip.easeOutDuration;
b.blendInDuration = (float)owningClip.blendInDuration;
b.blendOutDuration = (float)owningClip.blendOutDuration;
}
else
{
b.easeInDuration = b.easeOutDuration = b.blendInDuration = b.blendOutDuration = 0;
}
b.retriggerEvent = retriggerEvent;
b.StopEventAtClipEnd = StopEventAtClipEnd;
b.eventObject = owner;
b.eventDurationMin = eventDurationMin;
b.eventDurationMax = eventDurationMax;
if (eventDurationMin.Equals(eventDurationMax) && eventDurationMax.Equals(0f))
{
b.eventDurationMin = -1f;
b.eventDurationMax = -1f;
eventDurationMin = -1f;
eventDurationMax = -1f;
}
return playable;
}
#if UNITY_EDITOR
[UnityEditor.CustomEditor(typeof(AkTimelineEventPlayable), true)]
public class Editor : UnityEditor.Editor
{
private AkTimelineEventPlayable m_AkTimelineEventPlayable;
private UnityEditor.SerializedProperty akEvent;
private UnityEditor.SerializedProperty retriggerEvent;
private UnityEditor.SerializedProperty UseWwiseEventDuration;
private UnityEditor.SerializedProperty PrintDebugInformation;
private UnityEditor.SerializedProperty StopEventAtClipEnd;
private UnityEditor.SerializedProperty blendInCurve;
private UnityEditor.SerializedProperty blendOutCurve;
public void OnEnable()
{
m_AkTimelineEventPlayable = target as AkTimelineEventPlayable;
if (m_AkTimelineEventPlayable == null)
{
return;
}
akEvent = serializedObject.FindProperty("akEvent");
retriggerEvent = serializedObject.FindProperty("retriggerEvent");
UseWwiseEventDuration = serializedObject.FindProperty("UseWwiseEventDuration");
PrintDebugInformation = serializedObject.FindProperty("PrintDebugInformation");
StopEventAtClipEnd = serializedObject.FindProperty("StopEventAtClipEnd");
blendInCurve = serializedObject.FindProperty("blendInCurve");
blendOutCurve = serializedObject.FindProperty("blendOutCurve");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
{
UnityEditor.EditorGUILayout.PropertyField(akEvent, new UnityEngine.GUIContent("Event: "));
UnityEditor.EditorGUILayout.PropertyField(blendInCurve);
UnityEditor.EditorGUILayout.PropertyField(blendOutCurve);
}
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
{
UnityEditor.EditorGUILayout.PropertyField(UseWwiseEventDuration, new UnityEngine.GUIContent("Use Wwise Event Duration: ", "The clip duration is set to the duration of the Wwise Event"));
if (!UpdateClipInformation(m_AkTimelineEventPlayable.owningClip, m_AkTimelineEventPlayable.akEvent, serializedObject, UseWwiseEventDuration.boolValue))
{
UnityEditor.EditorGUILayout.HelpBox(string.Format("The duration of the Wwise event \"{0}\" has not been determined. Playback for this event may be inconsistent. " +
"Ensure that the event is associated with a generated SoundBank!", m_AkTimelineEventPlayable.akEvent.Name), UnityEditor.MessageType.Warning);
}
if (!UseWwiseEventDuration.boolValue)
{
var StopEventAtClipEndValue = StopEventAtClipEnd.boolValue;
var retriggerEventValue = retriggerEvent.boolValue;
UnityEditor.EditorGUILayout.PropertyField(StopEventAtClipEnd, new UnityEngine.GUIContent("Stop Event At End Of Clip: "));
UnityEditor.EditorGUILayout.PropertyField(retriggerEvent, new UnityEngine.GUIContent("Loop: ", "When checked, an event will loop until the end of the clip."));
if (retriggerEvent.boolValue && !StopEventAtClipEnd.boolValue)
{
if (!retriggerEventValue)
{
StopEventAtClipEnd.boolValue = true;
}
else if (StopEventAtClipEndValue)
{
retriggerEvent.boolValue = false;
}
}
}
}
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
{
UnityEditor.EditorGUILayout.PropertyField(PrintDebugInformation);
}
serializedObject.ApplyModifiedProperties();
}
private static void UpdateProgressBar(int index, int count)
{
float progress = (float)index / count;
UnityEditor.EditorUtility.DisplayProgressBar("Wwise Integration", "Fixing clip durations of AkTimelineEventPlayables...", progress);
}
[UnityEditor.InitializeOnLoadMethod]
public static void SetupSoundbankSetting()
{
if (UnityEditor.AssetDatabase.IsAssetImportWorkerProcess())
{
return;
}
string[] settingsToEnable = {"SoundBankGenerateEstimatedDuration"};
AkUtilities.ToggleBoolSoundbankSettingInWproj(settingsToEnable, AkWwiseEditorSettings.WwiseProjectAbsolutePath, true);
UnityEditor.EditorApplication.delayCall += UpdateAllClips;
WwiseProjectDatabase.SoundBankDirectoryUpdated += UpdateAllClips;
}
private static void UpdateAllClips()
{
var guids = UnityEditor.AssetDatabase.FindAssets("t:AkTimelineEventPlayable", new[] { "Assets" });
if (guids.Length < 1)
{
return;
}
var processedGuids = new System.Collections.Generic.HashSet<string>();
for (var i = 0; i < guids.Length; i++)
{
UpdateProgressBar(i, guids.Length);
var guid = guids[i];
if (processedGuids.Contains(guid))
{
continue;
}
processedGuids.Add(guid);
var path = UnityEditor.AssetDatabase.GUIDToAssetPath(guid);
var objects = UnityEditor.AssetDatabase.LoadAllAssetsAtPath(path);
var instanceIds = new System.Collections.Generic.List<int>();
foreach (var obj in objects)
{
if (obj == null)
{
continue;
}
var id = obj.GetInstanceID();
if (!instanceIds.Contains(id))
{
instanceIds.Add(id);
}
}
for (; instanceIds.Count > 0; instanceIds.RemoveAt(0))
{
var id = instanceIds[0];
objects = UnityEditor.AssetDatabase.LoadAllAssetsAtPath(path);
foreach (var obj in objects)
{
if (obj && obj.GetInstanceID() == id)
{
var playable = obj as AkTimelineEventPlayable;
if (playable)
{
var serializedObject = new UnityEditor.SerializedObject(playable);
var setClipDuration = serializedObject.FindProperty("UseWwiseEventDuration").boolValue;
UpdateClipInformation(playable.owningClip, playable.akEvent, serializedObject, setClipDuration);
serializedObject.ApplyModifiedProperties();
}
break;
}
}
}
}
UnityEditor.EditorUtility.ClearProgressBar();
}
/// <summary>
/// The minimum clip duration. This value is set to 1/60 of a second which generally represents the time of 1 frame.
/// </summary>
private const double MinimumDurationInSeconds = 1.0 / 60;
/// <summary>
/// Updates the associated clip information and the event durations.
/// </summary>
/// <returns>Returns true if the Wwise event is found in the project data.</returns>
private static bool UpdateClipInformation(UnityEngine.Timeline.TimelineClip clip, AK.Wwise.Event akEvent,
UnityEditor.SerializedObject serializedObject, bool setClipDuration)
{
var clipDuration = MinimumDurationInSeconds;
var maxDuration = -1.0f;
var minDuration = -1.0f;
AkUtilities.GetEventDurations(akEvent.Id, ref maxDuration, ref minDuration);
if (maxDuration != -1.0f)
{
serializedObject.FindProperty("eventDurationMin").floatValue = minDuration;
serializedObject.FindProperty("eventDurationMax").floatValue = maxDuration;
if (maxDuration > clipDuration)
{
clipDuration = maxDuration;
}
}
if (clip != null)
{
clip.displayName = akEvent.Name;
if (setClipDuration)
{
clip.duration = clipDuration;
}
}
return maxDuration != -1.0f;
}
}
#endif //#if UNITY_EDITOR
}
#endif // AK_ENABLE_TIMELINE
#endif // #if ! (UNITY_DASHBOARD_WIDGET || UNITY_WEBPLAYER || UNITY_WII || UNITY_WIIU || UNITY_NACL || UNITY_FLASH || UNITY_BLACKBERRY) // Disable under unsupported platforms.