using System;
using System.Collections.Generic;
using UnityEngine;
namespace Chronos
{
///
/// A global singleton tasked with keeping track of global clocks in the scene. One and only one Timekeeper is required per scene.
///
[DisallowMultipleComponent]
[HelpURL("http://ludiq.io/chronos/documentation#Timekeeper")]
public class Timekeeper : Singleton
{
public const int DefaultMaxParticleLoops = 10;
public Timekeeper()
: base(false, false)
{
_clocks = new Dictionary();
}
protected virtual void Awake()
{
foreach (GlobalClock globalClock in GetComponents())
{
_clocks.Add(globalClock.key, globalClock);
}
}
#region Properties
[SerializeField]
private bool _debug = false;
///
/// Determines whether Chronos should display debug messages and gizmos in the editor.
///
public bool debug
{
get { return _debug; }
set { _debug = value; }
}
[SerializeField]
private int _maxParticleLoops = DefaultMaxParticleLoops;
///
/// The maximum loops during which particle systems should be allowed to run before resetting.
///
public int maxParticleLoops
{
get { return _maxParticleLoops; }
set { _maxParticleLoops = value; }
}
#endregion
#region Clocks
protected Dictionary _clocks;
///
/// An enumeration of all the global clocks on the timekeeper.
///
public IEnumerable clocks
{
get { return _clocks.Values; }
}
///
/// Determines whether the timekeeper has a global clock with the specified key.
///
public virtual bool HasClock(string key)
{
if (key == null) throw new ArgumentNullException("key");
return _clocks.ContainsKey(key);
}
///
/// Returns the global clock with the specified key.
///
public virtual GlobalClock Clock(string key)
{
if (key == null) throw new ArgumentNullException("key");
if (!HasClock(key))
{
throw new ChronosException(string.Format("Unknown global clock '{0}'.", key));
}
return _clocks[key];
}
///
/// Adds a global clock with the specified key and returns it.
///
public virtual GlobalClock AddClock(string key)
{
if (key == null) throw new ArgumentNullException("key");
if (HasClock(key))
{
throw new ChronosException(string.Format("Global clock '{0}' already exists.", key));
}
GlobalClock clock = gameObject.AddComponent();
clock.key = key;
_clocks.Add(key, clock);
return clock;
}
///
/// Removes the global clock with the specified key.
///
public virtual void RemoveClock(string key)
{
if (key == null) throw new ArgumentNullException("key");
if (!HasClock(key))
{
throw new ChronosException(string.Format("Unknown global clock '{0}'.", key));
}
_clocks.Remove(key);
}
#endregion
internal static TimeState GetTimeState(float timeScale)
{
if (timeScale < 0)
{
return TimeState.Reversed;
}
else if (timeScale == 0)
{
return TimeState.Paused;
}
else if (timeScale < 1)
{
return TimeState.Slowed;
}
else if (timeScale == 1)
{
return TimeState.Normal;
}
else // if (timeScale > 1)
{
return TimeState.Accelerated;
}
}
// Unscaled delta time does not automatically behave like delta time.
// Hacky workaround for now, fixing 2 / 3 issues
// See: http://forum.unity3d.com/threads/138432/#post-2251561
internal static float unscaledDeltaTime
{
get
{
if (Time.frameCount <= 2)
{
return 0.02f;
}
else
{
return Mathf.Min(Time.unscaledDeltaTime, Time.maximumDeltaTime);
}
}
}
}
}