An easy to use Unity 3D library for creating illustrated Interactive Fiction games and more.
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.

230 lines
4.9 KiB

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)
{
AudioSource typingAudio = parentDialog.GetComponent<AudioSource>();
if (beepPerCharacter && (writingSpeed <= slowBeepsAt || writingSpeed >= fastBeepsAt)) // beeps match character speed at these speeds
oneBeep = true;
else
oneBeep = false;
if (typingAudio != null)
{
typingAudio.Stop();
if (!oneBeep)
typingAudio.Play();
}
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)
{
if (typingAudio != null &&
glyph.hasPunctuationPause)
{
parentDialog.SetTypingSoundVolume(false);
}
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 (typingAudio != null &&
glyph.hideTimer == 0f)
{
parentDialog.SetTypingSoundVolume(true);
}
if (finished)
{
return false; // Glyph is still hidden
}
}
}
if (typingAudio != null)
{
parentDialog.SetTypingSoundVolume(false);
}
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;
}
}
}