chrisgregan
10 years ago
5 changed files with 162 additions and 417 deletions
@ -1,177 +0,0 @@ |
|||||||
using UnityEngine; |
|
||||||
using UnityEngine.UI; |
|
||||||
using UnityEngine.Events; |
|
||||||
using System; |
|
||||||
using System.Collections; |
|
||||||
using System.Collections.Generic; |
|
||||||
|
|
||||||
namespace Fungus |
|
||||||
{ |
|
||||||
|
|
||||||
public class Dialog : MonoBehaviour, IDialogInputListener |
|
||||||
{ |
|
||||||
public static Character speakingCharacter; |
|
||||||
|
|
||||||
public DialogAudio audioController = new DialogAudio(); |
|
||||||
|
|
||||||
public float fadeDuration = 1f; |
|
||||||
|
|
||||||
public Canvas dialogCanvas; |
|
||||||
public Text nameText; |
|
||||||
public Text storyText; |
|
||||||
public Image characterImage; |
|
||||||
|
|
||||||
protected bool wasPointerClicked; |
|
||||||
|
|
||||||
protected virtual void LateUpdate() |
|
||||||
{ |
|
||||||
wasPointerClicked = false; |
|
||||||
} |
|
||||||
|
|
||||||
public virtual void ShowDialog(bool visible) |
|
||||||
{ |
|
||||||
gameObject.SetActive(true); |
|
||||||
|
|
||||||
if (visible) |
|
||||||
{ |
|
||||||
// A new dialog is often shown as the result of a mouse click, so we need |
|
||||||
// to make sure the previous click doesn't register on the new dialogue |
|
||||||
wasPointerClicked = false; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public virtual void SetCharacter(Character character, Flowchart flowchart = null) |
|
||||||
{ |
|
||||||
if (character == null) |
|
||||||
{ |
|
||||||
if (characterImage != null) |
|
||||||
{ |
|
||||||
characterImage.gameObject.SetActive(false); |
|
||||||
} |
|
||||||
if (nameText != null) |
|
||||||
{ |
|
||||||
nameText.text = ""; |
|
||||||
} |
|
||||||
} |
|
||||||
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; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// |
|
||||||
// IDialogInput implementation |
|
||||||
// |
|
||||||
|
|
||||||
public virtual void OnNextLineEvent() |
|
||||||
{ |
|
||||||
wasPointerClicked = true; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,8 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: b7e8f397d6557484f91f9992f702cff5 |
|
||||||
MonoImporter: |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
@ -1,222 +0,0 @@ |
|||||||
using UnityEngine; |
|
||||||
using System.Collections; |
|
||||||
using System.Collections.Generic; |
|
||||||
|
|
||||||
namespace Fungus |
|
||||||
{ |
|
||||||
public class Glyph |
|
||||||
{ |
|
||||||
public float hideTimer; |
|
||||||
public string character; |
|
||||||
public bool boldActive; |
|
||||||
public bool italicActive; |
|
||||||
public bool colorActive; |
|
||||||
public string colorText; |
|
||||||
public bool hasPunctuationPause; |
|
||||||
} |
|
||||||
|
|
||||||
public class DialogText |
|
||||||
{ |
|
||||||
protected List<Glyph> glyphs = new List<Glyph>(); |
|
||||||
protected bool oneBeep = false; |
|
||||||
|
|
||||||
public bool boldActive { get; set; } |
|
||||||
public bool italicActive { get; set; } |
|
||||||
public bool colorActive { get; set; } |
|
||||||
public string colorText { get; set; } |
|
||||||
public float writingSpeed { get; set; } |
|
||||||
public float punctuationPause { get; set; } |
|
||||||
public float slowBeepsAt { get; set; } |
|
||||||
public float fastBeepsAt { get; set; } |
|
||||||
public bool beepPerCharacter { get; set; } |
|
||||||
public Dialog parentDialog { get; set; } |
|
||||||
|
|
||||||
public virtual void Clear() |
|
||||||
{ |
|
||||||
glyphs.Clear(); |
|
||||||
} |
|
||||||
|
|
||||||
public virtual void Append(string words) |
|
||||||
{ |
|
||||||
if (beepPerCharacter && (writingSpeed <= slowBeepsAt || writingSpeed >= fastBeepsAt)) // beeps match character speed at these speeds |
|
||||||
{ |
|
||||||
oneBeep = true; |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
oneBeep = false; |
|
||||||
} |
|
||||||
|
|
||||||
float hideTimer = 0f; |
|
||||||
if (writingSpeed > 0f) |
|
||||||
{ |
|
||||||
hideTimer = 1f / writingSpeed; |
|
||||||
} |
|
||||||
|
|
||||||
bool doPunctuationPause = false; |
|
||||||
for (int i = 0; i < words.Length; ++i) |
|
||||||
{ |
|
||||||
char c = words[i]; |
|
||||||
|
|
||||||
// Ignore leading newlines |
|
||||||
if (glyphs.Count == 0 && c == '\n') |
|
||||||
{ |
|
||||||
continue; |
|
||||||
} |
|
||||||
|
|
||||||
Glyph glyph = new Glyph(); |
|
||||||
glyph.hideTimer = hideTimer; |
|
||||||
if (doPunctuationPause && writingSpeed != 0) |
|
||||||
{ |
|
||||||
glyph.hasPunctuationPause = true; |
|
||||||
glyph.hideTimer += punctuationPause; |
|
||||||
doPunctuationPause = false; |
|
||||||
} |
|
||||||
|
|
||||||
glyph.character = c.ToString(); |
|
||||||
glyph.boldActive = boldActive; |
|
||||||
glyph.italicActive = italicActive; |
|
||||||
glyph.colorActive = colorActive; |
|
||||||
glyph.colorText = colorText; |
|
||||||
glyphs.Add(glyph); |
|
||||||
|
|
||||||
if (IsPunctuation(c)) // If punctuation, do punctuation pause |
|
||||||
{ |
|
||||||
doPunctuationPause = true; |
|
||||||
} |
|
||||||
|
|
||||||
// Special case: pause just before open parentheses |
|
||||||
if (i < words.Length - 2) |
|
||||||
{ |
|
||||||
if (words[i + 1] == '(') |
|
||||||
{ |
|
||||||
doPunctuationPause = true; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
protected virtual bool IsPunctuation(char character) |
|
||||||
{ |
|
||||||
return character == '.' || |
|
||||||
character == '?' || |
|
||||||
character == '!' || |
|
||||||
character == ',' || |
|
||||||
character == ':' || |
|
||||||
character == ';' || |
|
||||||
character == ')'; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Returns true when all glyphs are visible. |
|
||||||
*/ |
|
||||||
public virtual bool UpdateGlyphs(bool instantComplete) |
|
||||||
{ |
|
||||||
AudioSource typingAudio = parentDialog.GetComponent<AudioSource>(); |
|
||||||
|
|
||||||
float elapsedTime = Time.deltaTime; |
|
||||||
|
|
||||||
foreach (Glyph glyph in glyphs) |
|
||||||
{ |
|
||||||
if (instantComplete) |
|
||||||
{ |
|
||||||
glyph.hideTimer = 0f; |
|
||||||
continue; |
|
||||||
} |
|
||||||
|
|
||||||
if (glyph.hideTimer > 0f) |
|
||||||
{ |
|
||||||
// Don't pause audio on punctuation pause as it's very noticeable and distracting |
|
||||||
if (glyph.hasPunctuationPause) |
|
||||||
{ |
|
||||||
parentDialog.audioController.Pause(); |
|
||||||
} |
|
||||||
|
|
||||||
bool finished = false; |
|
||||||
if (elapsedTime > glyph.hideTimer) |
|
||||||
{ |
|
||||||
elapsedTime -= glyph.hideTimer; |
|
||||||
glyph.hideTimer = 0f; |
|
||||||
// Some elapsed time left over, so carry on to next glyph |
|
||||||
if ((oneBeep && typingAudio != null)) |
|
||||||
{ |
|
||||||
if (!typingAudio.isPlaying && |
|
||||||
(glyph.character != " " && glyph.character != "\t" && glyph.character != "\n" ) ) |
|
||||||
{ |
|
||||||
typingAudio.PlayOneShot(typingAudio.clip); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
glyph.hideTimer -= elapsedTime; |
|
||||||
glyph.hideTimer = Mathf.Max(glyph.hideTimer, 0f); |
|
||||||
finished = true; |
|
||||||
} |
|
||||||
|
|
||||||
// Check if we need to restore audio after a punctuation pause |
|
||||||
if (glyph.hideTimer == 0f) |
|
||||||
{ |
|
||||||
parentDialog.audioController.Resume(); |
|
||||||
} |
|
||||||
|
|
||||||
if (finished) |
|
||||||
{ |
|
||||||
return false; // Glyph is still hidden |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
parentDialog.audioController.Stop(); |
|
||||||
|
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
public virtual string GetDialogText() |
|
||||||
{ |
|
||||||
string outputText = ""; |
|
||||||
|
|
||||||
bool hideGlyphs = false; |
|
||||||
foreach (Glyph glyph in glyphs) |
|
||||||
{ |
|
||||||
// Wrap each individual character in rich text markup tags (if required) |
|
||||||
string start = ""; |
|
||||||
string end = ""; |
|
||||||
if (glyph.boldActive) |
|
||||||
{ |
|
||||||
start += "<b>"; |
|
||||||
end += "</b>"; |
|
||||||
} |
|
||||||
if (glyph.italicActive) |
|
||||||
{ |
|
||||||
start += "<i>"; |
|
||||||
end = "</i>" + end; // Have to nest tags correctly |
|
||||||
} |
|
||||||
|
|
||||||
if (!hideGlyphs && |
|
||||||
glyph.hideTimer > 0f) |
|
||||||
{ |
|
||||||
hideGlyphs = true; |
|
||||||
outputText += "<color=#FFFFFF00>"; |
|
||||||
} |
|
||||||
|
|
||||||
if (!hideGlyphs && |
|
||||||
glyph.colorActive) |
|
||||||
{ |
|
||||||
start += "<color=" + glyph.colorText + ">"; |
|
||||||
end += "</color>"; |
|
||||||
} |
|
||||||
|
|
||||||
outputText += start + glyph.character + end; |
|
||||||
} |
|
||||||
|
|
||||||
if (hideGlyphs) |
|
||||||
{ |
|
||||||
outputText += "</color>"; |
|
||||||
} |
|
||||||
|
|
||||||
return outputText; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,8 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: 4aada7218611f4257bddea1cd4ab8fcf |
|
||||||
MonoImporter: |
|
||||||
serializedVersion: 2 |
|
||||||
defaultReferences: [] |
|
||||||
executionOrder: 0 |
|
||||||
icon: {instanceID: 0} |
|
||||||
userData: |
|
Loading…
Reference in new issue