ProjectDDD/Assets/Plugins/Pixel Crushers/Dialogue System/Scripts/MVC/Sequencer/Commands/SequencerCommandAudioWaitOnce.cs

222 lines
8.7 KiB (Stored with Git LFS)
C#

// Copyright (c) Pixel Crushers. All rights reserved.
using UnityEngine;
using System.Collections;
namespace PixelCrushers.DialogueSystem.SequencerCommands
{
/// <summary>
/// Implements sequencer command: AudioWaitOnce(audioClip[, subject[, audioClips...]])
/// This command will check for an internal lua variable of the entrytag/audioclip name, and
/// if it exists/is true, the audio will be skipped. after one playback, the variable
/// will be created and marked as true.
/// Contributed by Franklin Kester.
/// </summary>
[AddComponentMenu("")] // Hide from menu.
public class SequencerCommandAudioWaitOnce : SequencerCommand
{
static private string _VarPrefix = "once_";
private float _stopTime = 0;
private AudioSource _audioSource = null;
private int _nextClipIndex = 2;
private AudioClip _currentClip = null;
private AudioClip _originalClip = null;
private bool _restoreOriginalClip = false; // Don't restore original; could stop next entry's AudioWait that runs same frame.
protected bool isLoadingAudio = false;
public IEnumerator Start()
{
string audioClipName = GetParameter(0);
Transform subject = GetSubject(1);
_nextClipIndex = 2;
if (audioClipName == null || audioClipName.Length < 1)
{
if (DialogueDebug.logWarnings)
{
Debug.LogWarningFormat("{0}: Sequencer: AudioWaitOnce(): no audio clip name given", DialogueDebug.Prefix);
}
if (!this.hasNextClip()) { Stop(); }
}
if (DialogueDebug.logInfo)
{
Debug.LogFormat("{0}: Sequencer: AudioWaitOnce({1}) on {2}", DialogueDebug.Prefix, GetParameters(), subject);
}
if (this.hasPlayedAlready(audioClipName))
{
if (DialogueDebug.logInfo)
{
Debug.LogFormat("{0}: Sequencer: AudioWaitOnce(): clip {1} already played, skipping", DialogueDebug.Prefix, audioClipName);
if (!this.hasNextClip()) { Stop(); }
}
}
_audioSource = SequencerTools.GetAudioSource(subject);
if (_audioSource == null)
{
if (DialogueDebug.logWarnings)
{
Debug.LogWarningFormat("{0}: Sequencer: AudioWaitOnce(): can't find or add AudioSource to {1}.", DialogueDebug.Prefix, subject.name );
}
// doesn't matter if we have other clips, no audio source means no play
Stop();
}
else
{
_originalClip = _audioSource.clip;
_stopTime = DialogueTime.time + 1; // Give time for yield return null.
yield return null;
_originalClip = _audioSource.clip;
TryAudioClip(audioClipName);
}
}
private void TryAudioClip(string audioClipName)
{
try
{
if (string.IsNullOrEmpty(audioClipName))
{
if (DialogueDebug.logWarnings) Debug.LogWarning(string.Format("{0}: Sequencer: AudioWait() command: Audio clip name is blank.", new System.Object[] { DialogueDebug.Prefix }));
_stopTime = 0;
}
else if (this.hasPlayedAlready(audioClipName))
{
Debug.LogFormat("{0}: Sequencer: AudioWaitOnce(): clip {1} already played, skipping", DialogueDebug.Prefix, audioClipName);
_stopTime = DialogueTime.time;
// this prevents stop time from being overwritten below
return;
}
else
{
isLoadingAudio = true;
DialogueManager.LoadAsset(audioClipName, typeof(AudioClip),
(asset) =>
{
isLoadingAudio = false;
markAsPlayedAlready(audioClipName);
var audioClip = asset as AudioClip;
if (audioClip == null)
{
if (DialogueDebug.logWarnings && Sequencer.reportMissingAudioFiles) Debug.LogWarning(string.Format("{0}: Sequencer: AudioWait() command: Clip '{1}' wasn't found.", new System.Object[] { DialogueDebug.Prefix, audioClipName }));
_stopTime = 0;
}
else
{
if (IsAudioMuted())
{
if (DialogueDebug.logInfo) Debug.Log(string.Format("{0}: Sequencer: AudioWait(): waiting but not playing '{1}'; audio is muted.", new System.Object[] { DialogueDebug.Prefix, audioClipName }));
}
else if (_audioSource != null) // Check in case AudioSource was destroyed while loading Addressable.
{
if (DialogueDebug.logInfo) Debug.Log(string.Format("{0}: Sequencer: AudioWait(): playing '{1}'.", new System.Object[] { DialogueDebug.Prefix, audioClipName }));
_currentClip = audioClip;
_audioSource.clip = audioClip;
_audioSource.Play();
}
_stopTime = DialogueTime.time + SequencerCommandAudioWait.GetAudioClipLength(_audioSource, audioClip);
}
});
}
}
catch (System.Exception)
{
_stopTime = 0;
}
}
/// <summary>
/// returns a new string prefixed by the internal _VarPrefix, and appended by given audioClipName
/// </summary>
/// <param name="audioClipName">audio clip name to use for append</param>
/// <returns></returns>
private string buildOnceVarName(string audioClipName)
{
return _VarPrefix + audioClipName;
}
/// <summary>
/// checks for an internal lua variable of the given audio clip name to see if it's been played already.
/// returns true if yes, false if no or not found
/// </summary>
/// <param name="audioClipName">audio clip name to test</param>
/// <returns></returns>
private bool hasPlayedAlready(string audioClipName)
{
return DialogueLua.GetVariable(this.buildOnceVarName(audioClipName)).asBool;
}
/// <summary>
/// sets the internal variable that dictates the given audio clip was already played
/// </summary>
/// <param name="audioClipName"></param>
private void markAsPlayedAlready(string audioClipName)
{
DialogueLua.SetVariable(this.buildOnceVarName(audioClipName), true);
}
/// <summary>
/// checks to see if the next parameter clip index is valid (ie there's another clip waiting to be played)
/// </summary>
/// <returns></returns>
private bool hasNextClip()
{
return _nextClipIndex < parameters.Length;
}
public void Update()
{
if (DialogueTime.time >= _stopTime)
{
DialogueManager.UnloadAsset(_currentClip);
_currentClip = null;
if (!isLoadingAudio)
{
if (this.hasNextClip())
{
TryAudioClip(GetParameter(_nextClipIndex));
_nextClipIndex++;
}
else
{
_currentClip = null;
Stop();
}
}
}
}
public void OnDialogueSystemPause()
{
if (_audioSource == null) { return; }
_audioSource.Pause();
}
public void OnDialogueSystemUnpause()
{
if (_audioSource == null) { return; }
_audioSource.Play();
}
public void OnDestroy()
{
if (_audioSource != null)
{
if (_audioSource.isPlaying && (_audioSource.clip == _currentClip))
{
_audioSource.Stop();
}
if (_restoreOriginalClip) _audioSource.clip = _originalClip;
DialogueManager.UnloadAsset(_currentClip);
}
}
}
}