// 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 } }