// This code is part of the Fungus library (http://fungusgames.com) maintained by Chris Gregan (http://twitter.com/gofungus).
// It is released for free under the MIT open source license (https://github.com/snozbot/fungus/blob/master/LICENSE)
using UnityEngine;
using UnityEngine.EventSystems;
namespace Fungus
{
///
/// Supported modes for clicking through a Say Dialog.
///
public enum ClickMode
{
/// Clicking disabled.
Disabled,
/// Click anywhere on screen to advance.
ClickAnywhere,
/// Click anywhere on Say Dialog to advance.
ClickOnDialog,
/// Click on continue button to advance.
ClickOnButton
}
///
/// Input handler for say dialogs.
///
public class DialogInput : MonoBehaviour
{
[Tooltip("Click to advance story")]
[SerializeField] protected ClickMode clickMode;
[Tooltip("Delay between consecutive clicks. Useful to prevent accidentally clicking through story.")]
[SerializeField] protected float nextClickDelay = 0f;
[Tooltip("Allow holding Cancel to fast forward text")]
[SerializeField] protected bool cancelEnabled = true;
[Tooltip("Ignore input if a Menu dialog is currently active")]
[SerializeField] protected bool ignoreMenuClicks = true;
protected bool dialogClickedFlag;
protected bool nextLineInputFlag;
protected float ignoreClickTimer;
protected StandaloneInputModule currentStandaloneInputModule;
protected Writer writer;
protected virtual void Awake()
{
writer = GetComponent();
CheckEventSystem();
}
// There must be an Event System in the scene for Say and Menu input to work.
// This method will automatically instantiate one if none exists.
protected virtual void CheckEventSystem()
{
EventSystem eventSystem = GameObject.FindObjectOfType();
if (eventSystem == null)
{
// Auto spawn an Event System from the prefab
GameObject prefab = Resources.Load("Prefabs/EventSystem");
if (prefab != null)
{
GameObject go = Instantiate(prefab) as GameObject;
go.name = "EventSystem";
}
}
}
protected virtual void Update()
{
if (EventSystem.current == null)
{
return;
}
if (currentStandaloneInputModule == null)
{
currentStandaloneInputModule = EventSystem.current.GetComponent();
}
if (writer != null && writer.IsWriting)
{
if (Input.GetButtonDown(currentStandaloneInputModule.submitButton) ||
(cancelEnabled && Input.GetButton(currentStandaloneInputModule.cancelButton)))
{
SetNextLineFlag();
}
}
switch (clickMode)
{
case ClickMode.Disabled:
break;
case ClickMode.ClickAnywhere:
if (Input.GetMouseButtonDown(0))
{
SetNextLineFlag();
}
break;
case ClickMode.ClickOnDialog:
if (dialogClickedFlag)
{
SetNextLineFlag();
dialogClickedFlag = false;
}
break;
}
if (ignoreClickTimer > 0f)
{
ignoreClickTimer = Mathf.Max (ignoreClickTimer - Time.deltaTime, 0f);
}
if (ignoreMenuClicks)
{
// Ignore input events if a Menu is being displayed
if (MenuDialog.ActiveMenuDialog != null &&
MenuDialog.ActiveMenuDialog.IsActive() &&
MenuDialog.ActiveMenuDialog.DisplayedOptionsCount > 0)
{
dialogClickedFlag = false;
nextLineInputFlag = false;
}
}
// Tell any listeners to move to the next line
if (nextLineInputFlag)
{
var inputListeners = gameObject.GetComponentsInChildren();
for (int i = 0; i < inputListeners.Length; i++)
{
var inputListener = inputListeners[i];
inputListener.OnNextLineEvent();
}
nextLineInputFlag = false;
}
}
#region Public members
///
/// Trigger next line input event from script.
///
public virtual void SetNextLineFlag()
{
nextLineInputFlag = true;
}
///
/// Set the dialog clicked flag (usually from an Event Trigger component in the dialog UI).
///
public virtual void SetDialogClickedFlag()
{
// Ignore repeat clicks for a short time to prevent accidentally clicking through the character dialogue
if (ignoreClickTimer > 0f)
{
return;
}
ignoreClickTimer = nextClickDelay;
// Only applies in Click On Dialog mode
if (clickMode == ClickMode.ClickOnDialog)
{
dialogClickedFlag = true;
}
}
///
/// Sets the button clicked flag.
///
public virtual void SetButtonClickedFlag()
{
// Only applies if clicking is not disabled
if (clickMode != ClickMode.Disabled)
{
SetNextLineFlag();
}
}
#endregion
}
}