Files

235 lines
7.5 KiB
C#

using System.Collections;
using SepCore.Event;
using GameFramework.Event;
using SepCore.EnemyManager;
using UnityEngine;
using Unity.Profiling;
namespace SepCore.UI
{
public partial class HudForm : UGuiForm
{
[SerializeField] private float _sliderFadeDuration = 0.5f;
private float _currentHpPercent = 0;
private Coroutine _hpSliderFadeCoroutine;
private float _currentExpPercent = 0;
private Coroutine _expSliderFadeCoroutine;
private int _playerCurrentLevel = 1;
private int _currentCoin = 0;
private int _currentTimeLeft = 0;
private EnemyManagerComponent _enemy;
[SerializeField] private float _performanceStatsRefreshInterval = 0.2f;
private ProfilerRecorder _cpuTimeRecorder;
private float _performanceStatsRefreshTimer;
private Coroutine _performanceStatsCoroutine;
public void RefreshUI(HudContext hudContext)
{
RefreshMovePrompt(hudContext.MovePrompt);
}
public void RefreshMovePrompt(string prompt)
{
bool visible = !string.IsNullOrEmpty(prompt);
View.inputPromptObject.gameObject.SetActive(visible);
View.inputPromptText.text = prompt;
}
#region FSM
protected override void OnInit(object userData)
{
base.OnInit(userData);
GameEntry.Event.Subscribe(PlayerHealthChangeEventArgs.EventId, PlayerHpChange);
GameEntry.Event.Subscribe(PlayerExpChangeEventArgs.EventId, PlayerExpChange);
GameEntry.Event.Subscribe(PlayerCoinChangeEventArgs.EventId, PlayerCoinChange);
GameEntry.Event.Subscribe(PlayerLevelUpEventArgs.EventId, PlayerLevelUp);
GameEntry.Event.Subscribe(LevelProcessEventArgs.EventId, LevelProcess);
_enemy = GameEntry.EnemyManager;
}
protected override void OnOpen(object userData)
{
base.OnOpen(userData);
StartPerformanceStatsCollection();
}
protected override void OnPause()
{
StopPerformanceStatsCoroutine();
base.OnPause();
}
protected override void OnResume()
{
base.OnResume();
StartPerformanceStatsCoroutine();
}
private void StartPerformanceStatsCollection()
{
DisposePerformanceStatsRecorders();
_cpuTimeRecorder = ProfilerRecorder.StartNew(ProfilerCategory.Internal, "Main Thread", 15);
StartPerformanceStatsCoroutine();
}
private void StartPerformanceStatsCoroutine()
{
StopPerformanceStatsCoroutine();
_performanceStatsRefreshTimer = 0f;
_performanceStatsCoroutine = StartCoroutine(RefreshPerformanceStatsAtEndOfFrame());
}
protected override void OnClose(bool isShutdown, object userData)
{
GameEntry.Event.Unsubscribe(PlayerLevelUpEventArgs.EventId, PlayerLevelUp);
GameEntry.Event.Unsubscribe(PlayerHealthChangeEventArgs.EventId, PlayerHpChange);
GameEntry.Event.Unsubscribe(PlayerExpChangeEventArgs.EventId, PlayerExpChange);
GameEntry.Event.Unsubscribe(PlayerCoinChangeEventArgs.EventId, PlayerCoinChange);
GameEntry.Event.Unsubscribe(PlayerLevelUpEventArgs.EventId, PlayerLevelUp);
StopPerformanceStatsCoroutine();
DisposePerformanceStatsRecorders();
base.OnClose(isShutdown, userData);
}
private void StopPerformanceStatsCoroutine()
{
if (_performanceStatsCoroutine != null)
{
StopCoroutine(_performanceStatsCoroutine);
_performanceStatsCoroutine = null;
}
}
private void DisposePerformanceStatsRecorders()
{
if (_cpuTimeRecorder.Valid)
{
_cpuTimeRecorder.Dispose();
}
}
protected override void OnUpdate(float elapseSeconds, float realElapseSeconds)
{
base.OnUpdate(elapseSeconds, realElapseSeconds);
View.enemyCountFormatText.Set(_enemy.CurrentEnemyCount);
}
#endregion
private IEnumerator RefreshPerformanceStatsAtEndOfFrame()
{
WaitForEndOfFrame waitForEndOfFrame = new WaitForEndOfFrame();
while (true)
{
yield return waitForEndOfFrame;
_performanceStatsRefreshTimer -= Time.unscaledDeltaTime;
if (_performanceStatsRefreshTimer > 0f) continue;
_performanceStatsRefreshTimer = Mathf.Max(0.05f, _performanceStatsRefreshInterval);
RefreshPerformanceStats();
}
}
private void RefreshPerformanceStats()
{
bool hasCpuFrame = TryGetLastValue(_cpuTimeRecorder, out long cpuFrameNanoseconds);
if (!hasCpuFrame)
{
View.cpuTimeCostFormatText.Set(-1);
return;
}
float cpuFrameMilliseconds = cpuFrameNanoseconds / 1_000_000f;
View.cpuTimeCostFormatText.Set(cpuFrameMilliseconds);
}
private static bool TryGetLastValue(ProfilerRecorder recorder, out long value)
{
if (recorder.Valid && recorder.Count > 0)
{
value = recorder.LastValue;
return true;
}
value = 0;
return false;
}
#region Event Handlers
private void PlayerHpChange(object sender, GameEventArgs e)
{
if (!(e is PlayerHealthChangeEventArgs args)) return;
View.hpFormatText.Set(args.CurrentHealth, args.MaxHealth);
float percent = (float)args.CurrentHealth / args.MaxHealth;
if (Mathf.Approximately(_currentHpPercent, percent)) return;
_currentHpPercent = percent;
if (_hpSliderFadeCoroutine != null) StopCoroutine(_hpSliderFadeCoroutine);
_hpSliderFadeCoroutine = StartCoroutine(View.hpSlider.SmoothValue(percent, _sliderFadeDuration));
}
private void PlayerExpChange(object sender, GameEventArgs e)
{
if (!(e is PlayerExpChangeEventArgs args)) return;
float percent = (float)args.CurrentExp / args.MaxExp;
if (Mathf.Approximately(_currentExpPercent, percent)) return;
_currentExpPercent = percent;
if (_expSliderFadeCoroutine != null) StopCoroutine(_expSliderFadeCoroutine);
_expSliderFadeCoroutine = StartCoroutine(View.expSlider.SmoothValue(percent, _sliderFadeDuration));
}
private void PlayerLevelUp(object sender, GameEventArgs e)
{
if (!(e is PlayerLevelUpEventArgs)) return;
_playerCurrentLevel++;
View.expFormatText.Set(_playerCurrentLevel);
}
private void PlayerCoinChange(object sender, GameEventArgs e)
{
if (!(e is PlayerCoinChangeEventArgs args)) return;
if (_currentCoin == args.CoinCount) return;
View.coinFormatText.Set(args.CoinCount);
_currentCoin = args.CoinCount;
}
private void LevelProcess(object sender, GameEventArgs e)
{
if (!(e is LevelProcessEventArgs args)) return;
if (_currentTimeLeft == args.LevelTimeLeft) return;
_currentTimeLeft = args.LevelTimeLeft;
View.countdownText.text = _currentTimeLeft.ToString();
}
#endregion
}
}