// Copyright (c) 2015 - 2023 Doozy Entertainment. All Rights Reserved.
// This code can only be used under the standard Unity Asset Store End User License Agreement
// A Copy of the EULA APPENDIX 1 is available at http://unity3d.com/company/legal/as_terms
using System;
using System.Collections.Generic;
using Doozy.Runtime.Common;
using Doozy.Runtime.Common.Utils;
using Doozy.Runtime.Mody;
using Doozy.Runtime.UIManager.Content.Internal;
using UnityEngine;
using UnityEngine.Events;
namespace Doozy.Runtime.UIManager.Content
{
///
/// The UIStopwatch component can be used to measure elapsed time and trigger events at specific intervals (laps).
/// It works like a stopwatch, and it can be paused and resumed at any time.
/// It works with both real time (unscaled time) and game time (scaled time).
///
[AddComponentMenu("Doozy/UI/DateTime/UI Stopwatch")]
public class UIStopwatch : DateTimeComponent
{
#if UNITY_EDITOR
[UnityEditor.MenuItem("GameObject/Doozy/UI/DateTime/UI Stopwatch", false, 8)]
private static void CreateComponent(UnityEditor.MenuCommand menuCommand)
{
GameObjectUtils.AddToScene("UIStopwatch", false, true);
}
#endif
[Serializable]
public struct Lap
{
public int lapNumber { get; private set; }
public TimeSpan lapTime { get; private set; }
public TimeSpan lapDuration { get; private set; }
public Lap(int lapNumber, TimeSpan lapTime, TimeSpan lapDuration)
{
this.lapNumber = lapNumber;
this.lapTime = lapTime;
this.lapDuration = lapDuration;
}
}
///
/// Current lap index (starts at 0 for the first lap)
///
public int currentLapIndex { get; protected set; }
///
/// Current lap number (starts at 1 for the first lap)
///
public int currentLapNumber => currentLapIndex + 1;
/// Keeps track of the added laps
public List laps { get; protected set; }
/// Callback triggered when a new lap is added
public ModyEvent OnLap = new ModyEvent();
///
/// Callback triggered when a new lap is added
/// This is a quick access to the OnLap ModyEvent
///
public UnityEvent onLapEvent => OnLap.Event;
/// Keeps track of the last time a lap was added
private TimeSpan previousLapTime { get; set; }
#if UNITY_EDITOR
protected override void Reset()
{
base.Reset();
if (labels.Count == 0) labels.Add(new FormattedLabel(null, @"mm\:ss\.f"));
}
#endif // UNITY_EDITOR
protected override void Awake()
{
base.Awake();
laps ??= new List();
}
protected override void OnEnable()
{
base.OnEnable();
StartTimer();
}
protected override void OnDisable()
{
base.OnDisable();
CancelTimer();
}
protected override void UpdateCurrentTime()
{
base.UpdateCurrentTime();
Years = elapsedTime.Days / 365;
Months = elapsedTime.Days / 30;
Days = elapsedTime.Days;
Hours = elapsedTime.Hours;
Minutes = elapsedTime.Minutes;
Seconds = elapsedTime.Seconds;
Milliseconds = elapsedTime.Milliseconds;
UpdateLabels();
}
public override void UpdateLabels()
{
for (int i = 0; i < labels.Count; i++)
{
if (labels[i].Label == null) continue;
labels[i].SetText(elapsedTime);
}
}
public override void ResetTimer()
{
base.ResetTimer();
ClearLaps();
UpdateLabels();
}
public override void StartTimer()
{
base.StartTimer();
ClearLaps();
UpdateLabels();
}
public override void StopTimer()
{
base.StopTimer();
UpdateLabels();
}
public override void PauseTimer()
{
base.PauseTimer();
UpdateLabels();
}
public override void ResumeTimer()
{
base.ResumeTimer();
UpdateLabels();
}
public override void FinishTimer()
{
StartUpdateCoroutine();
UpdateCurrentTime();
StopTimer();
OnFinish?.Execute();
UpdateLabels();
}
public override void CancelTimer()
{
base.CancelTimer();
UpdateLabels();
}
///
/// Add a new lap time and duration to the lapTimes and lapDurations dictionaries
///
public void AddLap()
{
laps.Add
(
new Lap
(
currentLapNumber, //lap number
elapsedTime, //lap time
elapsedTime - previousLapTime //lap duration
)
);
OnLap?.Execute(); //trigger the OnLap event
UpdateLabels(); //update the labels
currentLapIndex++; //increment the current lap index
previousLapTime = elapsedTime; //update the previous lap time
}
///
/// Get the lap time for the given lap number (starts at 1 for the first lap)
///
/// Lap number (starts at 1 for the first lap)
/// Lap time for the given lap number
public Lap GetLap(int lapNumber)
{
if (lapNumber < 1 || lapNumber > currentLapNumber) return new Lap();
return laps[lapNumber - 1];
}
/// Clear the laps list and reset the current lap index
public void ClearLaps()
{
laps.Clear();
currentLapIndex = 0;
previousLapTime = TimeSpan.Zero;
}
protected override void SetEndTime()
{
endTime =
startTime
.AddYears(100);
}
}
}