// Copyright (c) Pixel Crushers. All rights reserved.
using UnityEngine;
using System.Collections;
namespace PixelCrushers.DialogueSystem
{
///
/// A static wrapper class for the built-in Time class. This class allows the user to specify
/// whether the dialogue system functions in realtime, gameplay time, or a custom time. If the
/// game is paused during conversations by setting Time.timeScale = 0, then the Dialogue
/// System should use realtime or it will also be paused. However, if you want the Dialogue
/// System to observe the timeScale, then you can use gameplay time (for example, if you want
/// the Sequencer to observe timeScale). If you want to manage time on your own, set the mode
/// to Custom and manually set DialogueTime.time every frame.
///
public static class DialogueTime
{
///
/// Dialogue System time mode.
///
public enum TimeMode
{
///
/// Ignore Time.timeScale. Internally, use Time.realtimeSinceStartup.
///
Realtime,
///
/// Observe Time.timeScale. Internally, use Time.time.
///
Gameplay,
///
/// Your code must manually manage the time.
///
Custom
}
///
/// Gets or sets the time mode. Setting this also sets GameTime.mode.
///
///
/// The mode.
///
public static TimeMode mode
{
get { return m_mode; }
set
{
m_mode = value;
switch (value)
{
case TimeMode.Realtime:
GameTime.mode = GameTimeMode.Realtime;
break;
case TimeMode.Gameplay:
GameTime.mode = GameTimeMode.UnityStandard;
break;
case TimeMode.Custom:
GameTime.mode = GameTimeMode.Manual;
break;
}
}
}
private static TimeMode m_mode = TimeMode.Realtime;
///
/// Gets the time based on the current Mode.
///
///
/// The time.
///
public static float time
{
get
{
switch (mode)
{
default:
case TimeMode.Realtime:
return (m_isPaused ? s_realtimeWhenPaused : Time.realtimeSinceStartup) - s_totalRealtimePaused;
case TimeMode.Gameplay:
return Time.time;
case TimeMode.Custom:
return m_customTime;
}
}
set
{
m_customTime = value;
GameTime.time = value;
}
}
///
/// The frame delta time based on the current time mode.
///
public static float deltaTime
{
get
{
switch (mode)
{
default:
case TimeMode.Realtime:
return m_isPaused ? 0 : Time.unscaledDeltaTime;
case TimeMode.Gameplay:
return Time.deltaTime;
case TimeMode.Custom:
return m_isPaused ? 0 : m_customDeltaTime;
}
}
set
{
m_customDeltaTime = value;
}
}
public static bool isPaused
{
get
{
switch (mode)
{
default:
case TimeMode.Realtime:
case TimeMode.Custom:
return m_isPaused;
case TimeMode.Gameplay:
return Tools.ApproximatelyZero(Time.timeScale);
}
}
set
{
switch (mode)
{
case TimeMode.Realtime:
if (!m_isPaused && value)
{
// Pausing, so record realtime at time of pause:
s_realtimeWhenPaused = Time.realtimeSinceStartup;
}
else if (m_isPaused && !value)
{
// Unpausing, so add to totalRealtimePaused:
s_totalRealtimePaused += Time.realtimeSinceStartup - s_realtimeWhenPaused;
}
break;
case TimeMode.Gameplay:
Time.timeScale = m_isPaused ? 0 : 1;
break;
case TimeMode.Custom:
break;
}
m_isPaused = value;
GameTime.isPaused = value;
}
}
/// @cond FOR_V1_COMPATIBILITY
public static TimeMode Mode { get { return mode; } set { mode = value; } }
public static bool IsPaused { get { return isPaused; } set { isPaused = value; } }
/// @endcond
private static float m_customTime = 0;
private static float m_customDeltaTime = 0;
private static bool m_isPaused = false;
private static float s_realtimeWhenPaused = 0;
private static float s_totalRealtimePaused = 0;
///
/// Initializes the class.
///
static DialogueTime()
{
mode = TimeMode.Realtime;
}
///
/// This version of WaitForSeconds respects DialogueTime.
///
///
///
public static IEnumerator WaitForSeconds(float seconds)
{
float start = DialogueTime.time;
while (DialogueTime.time < start + seconds)
{
yield return null;
}
}
}
}