You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
315 lines
6.6 KiB
315 lines
6.6 KiB
using UnityEngine; |
|
using UnityEngine.UI; |
|
using System; |
|
using System.Collections; |
|
using System.Collections.Generic; |
|
|
|
namespace Fungus |
|
{ |
|
|
|
public class SayDialog : MonoBehaviour |
|
{ |
|
// Currently active Say Dialog used to display Say text |
|
public static SayDialog activeSayDialog; |
|
|
|
// Most recent speaking character |
|
public static Character speakingCharacter; |
|
|
|
public float fadeDuration = 0.25f; |
|
|
|
public Button continueButton; |
|
public Canvas dialogCanvas; |
|
public Text nameText; |
|
public Text storyText; |
|
public Image characterImage; |
|
|
|
protected WriterAudio writerAudio; |
|
protected Writer writer; |
|
protected CanvasGroup canvasGroup; |
|
|
|
protected bool fadeWhenDone = true; |
|
protected float targetAlpha = 0f; |
|
protected float fadeCoolDownTimer = 0f; |
|
|
|
public static SayDialog GetSayDialog() |
|
{ |
|
if (activeSayDialog == null) |
|
{ |
|
// Use first Say Dialog found in the scene (if any) |
|
SayDialog sd = GameObject.FindObjectOfType<SayDialog>(); |
|
if (sd != null) |
|
{ |
|
activeSayDialog = sd; |
|
} |
|
|
|
if (activeSayDialog == null) |
|
{ |
|
// Auto spawn a say dialog object from the prefab |
|
GameObject prefab = Resources.Load<GameObject>("SayDialog"); |
|
if (prefab != null) |
|
{ |
|
GameObject go = Instantiate(prefab) as GameObject; |
|
go.SetActive(false); |
|
go.name = "SayDialog"; |
|
activeSayDialog = go.GetComponent<SayDialog>(); |
|
} |
|
} |
|
} |
|
|
|
return activeSayDialog; |
|
} |
|
|
|
protected Writer GetWriter() |
|
{ |
|
if (writer != null) |
|
{ |
|
return writer; |
|
} |
|
|
|
writer = GetComponent<Writer>(); |
|
if (writer == null) |
|
{ |
|
writer = gameObject.AddComponent<Writer>(); |
|
} |
|
|
|
return writer; |
|
} |
|
|
|
protected CanvasGroup GetCanvasGroup() |
|
{ |
|
if (canvasGroup != null) |
|
{ |
|
return canvasGroup; |
|
} |
|
|
|
canvasGroup = GetComponent<CanvasGroup>(); |
|
if (canvasGroup == null) |
|
{ |
|
canvasGroup = gameObject.AddComponent<CanvasGroup>(); |
|
} |
|
|
|
return canvasGroup; |
|
} |
|
|
|
protected WriterAudio GetWriterAudio() |
|
{ |
|
if (writerAudio != null) |
|
{ |
|
return writerAudio; |
|
} |
|
|
|
writerAudio = GetComponent<WriterAudio>(); |
|
if (writerAudio == null) |
|
{ |
|
writerAudio = gameObject.AddComponent<WriterAudio>(); |
|
} |
|
|
|
return writerAudio; |
|
} |
|
|
|
protected void Start() |
|
{ |
|
// Dialog always starts invisible, will be faded in when writing starts |
|
GetCanvasGroup().alpha = 0f; |
|
} |
|
|
|
public virtual void Say(string text, bool clearPrevious, bool waitForInput, bool fadeWhenDone, AudioClip audioClip, Action onComplete) |
|
{ |
|
this.fadeWhenDone = fadeWhenDone; |
|
|
|
// Look for a character sound effect if no voice over clip is specified |
|
AudioClip clip = audioClip; |
|
if (speakingCharacter != null && |
|
clip == null) |
|
{ |
|
clip = speakingCharacter.soundEffect; |
|
} |
|
|
|
GetWriter().Write(text, clearPrevious, waitForInput, clip, onComplete); |
|
} |
|
|
|
protected virtual void LateUpdate() |
|
{ |
|
UpdateAlpha(); |
|
|
|
if (continueButton != null) |
|
{ |
|
continueButton.gameObject.SetActive( GetWriter().isWaitingForInput ); |
|
} |
|
} |
|
|
|
/** |
|
* Tell dialog to fade out if it's finished writing. |
|
*/ |
|
public virtual void FadeOut() |
|
{ |
|
fadeWhenDone = true; |
|
} |
|
|
|
/** |
|
* Stop a Say Dialog while its writing text. |
|
*/ |
|
public virtual void Stop() |
|
{ |
|
fadeWhenDone = true; |
|
GetWriter().Stop(); |
|
} |
|
|
|
protected virtual void UpdateAlpha() |
|
{ |
|
if (GetWriter().isWriting) |
|
{ |
|
targetAlpha = 1f; |
|
fadeCoolDownTimer = 0.1f; |
|
} |
|
else if (fadeWhenDone && fadeCoolDownTimer == 0f) |
|
{ |
|
targetAlpha = 0f; |
|
} |
|
else |
|
{ |
|
// Add a short delay before we start fading in case there's another Say command in the next frame or two. |
|
// This avoids a noticeable flicker between consecutive Say commands. |
|
fadeCoolDownTimer = Mathf.Max(0f, fadeCoolDownTimer - Time.deltaTime); |
|
} |
|
|
|
CanvasGroup canvasGroup = GetCanvasGroup(); |
|
float fadeDuration = GetSayDialog().fadeDuration; |
|
if (fadeDuration <= 0f) |
|
{ |
|
canvasGroup.alpha = targetAlpha; |
|
} |
|
else |
|
{ |
|
float delta = (1f / fadeDuration) * Time.deltaTime; |
|
float alpha = Mathf.MoveTowards(canvasGroup.alpha, targetAlpha, delta); |
|
canvasGroup.alpha = alpha; |
|
} |
|
} |
|
|
|
public virtual void SetCharacter(Character character, Flowchart flowchart = null) |
|
{ |
|
if (character == null) |
|
{ |
|
if (characterImage != null) |
|
{ |
|
characterImage.gameObject.SetActive(false); |
|
} |
|
if (nameText != null) |
|
{ |
|
nameText.text = ""; |
|
} |
|
speakingCharacter = null; |
|
} |
|
else |
|
{ |
|
Character prevSpeakingCharacter = speakingCharacter; |
|
speakingCharacter = character; |
|
|
|
// Dim portraits of non-speaking characters |
|
foreach (Stage s in Stage.activeStages) |
|
{ |
|
if (s.dimPortraits) |
|
{ |
|
foreach (Character c in s.charactersOnStage) |
|
{ |
|
if (prevSpeakingCharacter != speakingCharacter) |
|
{ |
|
if (c != speakingCharacter) |
|
{ |
|
Portrait.SetDimmed(c, s, true); |
|
} |
|
else |
|
{ |
|
Portrait.SetDimmed(c, s, false); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
string characterName = character.nameText; |
|
|
|
if (characterName == "") |
|
{ |
|
// Use game object name as default |
|
characterName = character.name; |
|
} |
|
|
|
if (flowchart != null) |
|
{ |
|
characterName = flowchart.SubstituteVariables(characterName); |
|
} |
|
|
|
SetCharacterName(characterName, character.nameColor); |
|
} |
|
} |
|
|
|
public virtual void SetCharacterImage(Sprite image) |
|
{ |
|
if (characterImage != null) |
|
{ |
|
if (image != null) |
|
{ |
|
characterImage.sprite = image; |
|
characterImage.gameObject.SetActive(true); |
|
} |
|
else |
|
{ |
|
characterImage.gameObject.SetActive(false); |
|
} |
|
} |
|
} |
|
|
|
public virtual void SetCharacterName(string name, Color color) |
|
{ |
|
if (nameText != null) |
|
{ |
|
nameText.text = name; |
|
nameText.color = color; |
|
} |
|
} |
|
|
|
public virtual void Clear() |
|
{ |
|
ClearStoryText(); |
|
|
|
// Kill any active write coroutine |
|
StopAllCoroutines(); |
|
} |
|
|
|
protected virtual void ClearStoryText() |
|
{ |
|
if (storyText != null) |
|
{ |
|
storyText.text = ""; |
|
} |
|
} |
|
|
|
public static void StopPortraitTweens() |
|
{ |
|
// Stop all tweening portraits |
|
foreach( Character c in Character.activeCharacters ) |
|
{ |
|
if (c.state.portraitImage != null) |
|
{ |
|
if (LeanTween.isTweening(c.state.portraitImage.gameObject)) |
|
{ |
|
LeanTween.cancel(c.state.portraitImage.gameObject, true); |
|
|
|
Portrait.SetRectTransform(c.state.portraitImage.rectTransform, c.state.position); |
|
if (c.state.dimmed == true) |
|
{ |
|
c.state.portraitImage.color = new Color(0.5f, 0.5f, 0.5f, 1f); |
|
} |
|
else |
|
{ |
|
c.state.portraitImage.color = Color.white; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
}
|
|
|