// 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)
#if UNITY_5_3_OR_NEWER
using UnityEngine ;
using UnityEngine.UI ;
using UnityEngine.SceneManagement ;
namespace Fungus
{
/// <summary>
/// A singleton game object which displays a simple UI for the save system.
/// </summary>
public class SaveMenu : MonoBehaviour
{
[Tooltip("The string key used to store save game data in Player Prefs. If you have multiple games defined in the same Unity project, use a unique key for each one.")]
[SerializeField] protected string saveDataKey = FungusConstants . DefaultSaveDataKey ;
[Tooltip("Automatically load the most recently saved game on startup")]
[SerializeField] protected bool loadOnStart = true ;
[Tooltip("Automatically save game to disk after each Save Point command executes. This also disables the Save and Load menu buttons.")]
[SerializeField] protected bool autoSave = false ;
[Tooltip("Delete the save game data from disk when player restarts the game. Useful for testing, but best switched off for release builds.")]
[SerializeField] protected bool restartDeletesSave = false ;
[Tooltip("The CanvasGroup containing the save menu buttons")]
[SerializeField] protected CanvasGroup saveMenuGroup ;
[Tooltip("The button which hides / displays the save menu")]
[SerializeField] protected Button saveMenuButton ;
[Tooltip("The button which saves the save history to disk")]
[SerializeField] protected Button saveButton ;
[Tooltip("The button which loads the save history from disk")]
[SerializeField] protected Button loadButton ;
[Tooltip("The button which rewinds the save history to the previous save point.")]
[SerializeField] protected Button rewindButton ;
[Tooltip("The button which fast forwards the save history to the next save point.")]
[SerializeField] protected Button forwardButton ;
[Tooltip("The button which restarts the game.")]
[SerializeField] protected Button restartButton ;
[Tooltip("The button that shows conversation history.")]
[SerializeField] protected Button historyButton ;
[Tooltip("A scrollable text field used for displaying conversation history.")]
[SerializeField] protected ScrollRect historyView ;
[Tooltip("The CanvasGroup containing the save menu buttons")]
[SerializeField] protected CanvasGroup historyMenuGroup ;
[Tooltip("A scrollable text field used for debugging the save data. The text field should be disabled in normal use.")]
[SerializeField] protected ScrollRect debugView ;
protected static bool saveMenuActive = false ;
protected static bool historyMenuActive = false ;
protected AudioSource clickAudioSource ;
protected LTDescr fadeTween ;
protected static SaveMenu instance ;
protected virtual void Awake ( )
{
// Only one instance of SaveMenu may exist
if ( instance ! = null )
{
Destroy ( gameObject ) ;
return ;
}
instance = this ;
GameObject . DontDestroyOnLoad ( this ) ;
clickAudioSource = GetComponent < AudioSource > ( ) ;
}
protected virtual void Start ( )
{
if ( ! saveMenuActive )
{
saveMenuGroup . alpha = 0f ;
}
if ( ! historyMenuActive )
{
historyMenuGroup . alpha = 0f ;
}
var saveManager = FungusManager . Instance . SaveManager ;
// Make a note of the current scene. This will be used when restarting the game.
if ( string . IsNullOrEmpty ( saveManager . StartScene ) )
{
saveManager . StartScene = SceneManager . GetActiveScene ( ) . name ;
}
if ( loadOnStart )
{
if ( saveManager . SaveDataExists ( saveDataKey ) )
{
saveManager . Load ( saveDataKey ) ;
}
}
}
protected virtual void Update ( )
{
var saveManager = FungusManager . Instance . SaveManager ;
// Hide the Save and Load buttons if autosave is on
bool showSaveAndLoad = ! autoSave ;
if ( saveButton . IsActive ( ) ! = showSaveAndLoad )
{
saveButton . gameObject . SetActive ( showSaveAndLoad ) ;
loadButton . gameObject . SetActive ( showSaveAndLoad ) ;
}
if ( showSaveAndLoad )
{
if ( saveButton ! = null )
{
// Don't allow saving unless there's at least one save point in the history,
// This avoids the case where you could try to load a save data with 0 save points.
saveButton . interactable = saveManager . NumSavePoints > 0 ;
}
if ( loadButton ! = null )
{
loadButton . interactable = saveManager . SaveDataExists ( saveDataKey ) ;
}
}
if ( rewindButton ! = null )
{
rewindButton . interactable = saveManager . NumSavePoints > 0 ;
}
if ( forwardButton ! = null )
{
forwardButton . interactable = saveManager . NumRewoundSavePoints > 0 ;
}
if ( debugView . enabled )
{
var debugText = debugView . GetComponentInChildren < Text > ( ) ;
if ( debugText ! = null )
{
debugText . text = saveManager . GetDebugInfo ( ) ;
}
}
if ( historyView . enabled )
{
var historyText = historyView . GetComponentInChildren < Text > ( ) ;
if ( historyText ! = null )
{
historyText . text = FungusManager . Instance . NarrativeLog . GetPrettyHistory ( ) ;
}
}
}
protected virtual void OnEnable ( )
{
SaveManagerSignals . OnSavePointAdded + = OnSavePointAdded ;
}
protected virtual void OnDisable ( )
{
SaveManagerSignals . OnSavePointAdded - = OnSavePointAdded ;
}
protected virtual void OnSavePointAdded ( string savePointKey , string savePointDescription )
{
var saveManager = FungusManager . Instance . SaveManager ;
if ( autoSave & &
saveManager . NumSavePoints > 0 )
{
saveManager . Save ( saveDataKey ) ;
}
}
protected virtual void OnSaveReset ( )
{
var saveManager = FungusManager . Instance . SaveManager ;
}
protected void PlayClickSound ( )
{
if ( clickAudioSource ! = null )
{
clickAudioSource . Play ( ) ;
}
}
#region Public methods
/// <summary>
/// Gets the string key used to store save game data in Player Prefs.
/// </summary>
public virtual string SaveDataKey { get { return saveDataKey ; } }
/// <summary>
/// Toggles the expanded / collapsed state of the save menu.
/// Uses a tween to fade the menu UI in and out.
/// </summary>
public virtual void ToggleSaveMenu ( )
{
if ( fadeTween ! = null )
{
LeanTween . cancel ( fadeTween . id , true ) ;
fadeTween = null ;
}
if ( saveMenuActive )
{
// Switch menu off
LeanTween . value ( saveMenuGroup . gameObject , saveMenuGroup . alpha , 0f , 0.5f ) . setOnUpdate ( ( t ) = > {
saveMenuGroup . alpha = t ;
} ) . setOnComplete ( ( ) = > {
saveMenuGroup . alpha = 0f ;
} ) ;
}
else
{
// Switch menu on
LeanTween . value ( saveMenuGroup . gameObject , saveMenuGroup . alpha , 1f , 0.5f ) . setOnUpdate ( ( t ) = > {
saveMenuGroup . alpha = t ;
} ) . setOnComplete ( ( ) = > {
saveMenuGroup . alpha = 1f ;
} ) ;
}
saveMenuActive = ! saveMenuActive ;
}
/// <summary>
/// Handler function called when the Save button is pressed.
/// </summary>
public virtual void Save ( )
{
var saveManager = FungusManager . Instance . SaveManager ;
if ( saveManager . NumSavePoints > 0 )
{
PlayClickSound ( ) ;
saveManager . Save ( saveDataKey ) ;
}
}
/// <summary>
/// Handler function called when the Load button is pressed.
/// </summary>
public virtual void Load ( )
{
var saveManager = FungusManager . Instance . SaveManager ;
if ( saveManager . SaveDataExists ( saveDataKey ) )
{
PlayClickSound ( ) ;
saveManager . Load ( saveDataKey ) ;
}
}
/// <summary>
/// Handler function called when the Rewind button is pressed.
/// </summary>
public virtual void Rewind ( )
{
PlayClickSound ( ) ;
var saveManager = FungusManager . Instance . SaveManager ;
if ( saveManager . NumSavePoints > 0 )
{
saveManager . Rewind ( ) ;
}
}
/// <summary>
/// Handler function called when the Fast Forward button is pressed.
/// </summary>
public virtual void FastForward ( )
{
PlayClickSound ( ) ;
var saveManager = FungusManager . Instance . SaveManager ;
if ( saveManager . NumRewoundSavePoints > 0 )
{
saveManager . FastForward ( ) ;
}
}
/// <summary>
/// Handler function called when the Restart button is pressed.
/// </summary>
public virtual void Restart ( )
{
var saveManager = FungusManager . Instance . SaveManager ;
var narrativeLog = FungusManager . Instance . NarrativeLog ;
if ( string . IsNullOrEmpty ( saveManager . StartScene ) )
{
Debug . LogError ( "No start scene specified" ) ;
return ;
}
PlayClickSound ( ) ;
// Reset the Save History for a new game
saveManager . ClearHistory ( ) ;
narrativeLog . Clear ( ) ;
if ( restartDeletesSave )
{
saveManager . Delete ( saveDataKey ) ;
}
SceneManager . LoadScene ( saveManager . StartScene ) ;
}
public virtual void ToggleHistoryView ( )
{
if ( fadeTween ! = null )
{
LeanTween . cancel ( fadeTween . id , true ) ;
fadeTween = null ;
}
if ( historyMenuActive )
{
// Switch menu off
LeanTween . value ( historyMenuGroup . gameObject , historyMenuGroup . alpha , 0f , 0.5f ) . setOnUpdate ( ( t ) = > {
historyMenuGroup . alpha = t ;
} ) . setOnComplete ( ( ) = > {
historyMenuGroup . alpha = 0f ;
} ) ;
}
else
{
// Switch menu on
LeanTween . value ( historyMenuGroup . gameObject , historyMenuGroup . alpha , 1f , 0.5f ) . setOnUpdate ( ( t ) = > {
historyMenuGroup . alpha = t ;
} ) . setOnComplete ( ( ) = > {
historyMenuGroup . alpha = 1f ;
} ) ;
}
historyMenuActive = ! historyMenuActive ;
}
# endregion
}
}
# endif