Loading Done

This commit is contained in:
Savya Bikram Shah
2026-05-28 16:08:57 +05:45
parent 0e50fa5e55
commit d239dbd9b5
26 changed files with 60002 additions and 2461 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 09a530ea6231c44aeb08c880de69eeda
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7b3ba9e51a74d4a0f8673b21a9124298
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,17 @@
# Loading Feature
## Purpose
- Owns the passive loading-screen presenter/view pair shared by boot and scene transitions.
- Centralizes progress and status updates for the user-facing loading UI.
## Public Entry Points
- `LoadingPresenter`
- `LoadingScreenView`
## Dependencies
- Consumed from App/loading orchestration via the loading contracts.
- Should remain presentation-only and avoid feature-specific gameplay logic.
## Extension Notes
- Add new UI affordances here only if they are generic to every loading flow.
- Keep orchestration decisions in App/GameFlow/MainMenu sequences, not in the presenter or view.

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 14e78c2457d7941859fa8192ae052e72
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,21 @@
{
"name": "Features.Loading",
"rootNamespace": "Darkmatter.Features.Loading",
"references": [
"GUID:6a0a834eb41764f12ba55c3fb04a40cb",
"GUID:c1c03c0e5b2f4412b9f2be1c20d6a9b1",
"GUID:f51ebe6a0ceec4240a699833d6309b23",
"GUID:b0214a6008ed146ff8f122a6a9c2f6cc",
"GUID:6055be8ebefd69e48b49212b09b47b2f",
"GUID:80ecb87cae9c44d19824e70ea7229748"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: b6b16414554114d0b971c01ee2f137fb
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,110 @@
using Cysharp.Threading.Tasks;
using Darkmatter.Core.Contracts.Features.Loading;
using UnityEngine;
namespace Darkmatter.Features.Loading
{
public class LoadingPresenter : ILoadingScreen
{
private const float SnapToCompleteThreshold = 0.9999f;
private const float ProgressEpsilon = 0.0001f;
private readonly LoadingScreenView _view;
private float _reportedProgress;
private float _displayedProgress;
private bool _isVisible;
private bool _isAnimating;
public float CurrentProgress => _reportedProgress;
public LoadingPresenter(LoadingScreenView view)
{
_view = view;
}
public void Show()
{
if (_isVisible)
{
_view.Show();
return;
}
_reportedProgress = 0f;
_displayedProgress = 0f;
_view.SetProgress(0f);
_view.Show();
_isVisible = true;
}
public void Hide()
{
if (_reportedProgress >= SnapToCompleteThreshold)
{
SnapDisplayedProgress(1f);
}
_isVisible = false;
_view.Hide();
}
public void SetProgress(float progress)
{
progress = Mathf.Clamp01(progress);
progress = Mathf.Max(_reportedProgress, progress);
if (progress >= SnapToCompleteThreshold)
{
_reportedProgress = 1f;
SnapDisplayedProgress(1f);
return;
}
_reportedProgress = progress;
if (!_isVisible)
{
SnapDisplayedProgress(progress);
return;
}
if (_displayedProgress + ProgressEpsilon >= _reportedProgress || _isAnimating)
{
return;
}
AnimateProgressAsync().Forget();
}
private async UniTaskVoid AnimateProgressAsync()
{
_isAnimating = true;
try
{
while (_isVisible && _displayedProgress + ProgressEpsilon < _reportedProgress)
{
var deltaTime = Mathf.Max(Time.unscaledDeltaTime, 1f / 60f);
var smoothing = 1f - Mathf.Exp(-_view.LoadingSmoothTime * deltaTime);
_displayedProgress = Mathf.Lerp(_displayedProgress, _reportedProgress, smoothing);
if (_reportedProgress - _displayedProgress <= 0.001f)
{
_displayedProgress = _reportedProgress;
}
_view.SetProgress(_displayedProgress);
await UniTask.Yield(PlayerLoopTiming.Update);
}
}
finally
{
_isAnimating = false;
}
}
private void SnapDisplayedProgress(float progress)
{
_displayedProgress = progress;
_view.SetProgress(progress);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 00b0a1507e1d4b27b44e77c4967aed99
timeCreated: 1771494975

View File

@@ -0,0 +1,85 @@
using PrimeTween;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace Darkmatter.Features.Loading
{
public class LoadingScreenView : MonoBehaviour
{
[SerializeField] private Slider loadingSlider;
[SerializeField] private TMP_Text statusText;
[SerializeField] private float loadingSmoothTime = 10f;
[SerializeField] private float messageHoldDuration = 2f;
[SerializeField] private float messageFadeDuration = 0.4f;
public float LoadingSmoothTime => loadingSmoothTime;
private static readonly string[] StatusLines = {
"Blue is arguing with red...",
"The crayons are dancing...",
"Yellow spilled everywhere...",
"Chasing escaped paint drops...",
"Untying rainbow knots...",
"Cleaning glitter explosions...",
"The color monsters are hungry...",
"Mixing mystery colors...",
"Someone ate the purple paint...",
"Teaching green to behave..."
};
private Sequence _statusSequence;
private int _statusIndex;
public void Show()
{
gameObject.SetActive(true);
StartStatusCycle();
}
public void Hide()
{
StopStatusCycle();
gameObject.SetActive(false);
}
public void SetProgress(float progress)
{
if (loadingSlider != null) loadingSlider.value = progress;
}
private void StartStatusCycle()
{
if (statusText == null || StatusLines.Length == 0) return;
StopStatusCycle();
_statusIndex = Random.Range(0, StatusLines.Length);
statusText.text = StatusLines[_statusIndex];
statusText.alpha = 0f;
_statusSequence = Sequence.Create(useUnscaledTime: true, cycles: -1)
.Chain(Tween.Alpha(statusText, 1f, messageFadeDuration, Ease.OutQuad))
.ChainDelay(messageHoldDuration)
.Chain(Tween.Alpha(statusText, 0f, messageFadeDuration, Ease.InQuad))
.ChainCallback(AdvanceStatusLine);
}
private void StopStatusCycle()
{
if (_statusSequence.isAlive) _statusSequence.Stop();
_statusSequence = default;
}
private void AdvanceStatusLine()
{
if (statusText == null) return;
_statusIndex = (_statusIndex + 1) % StatusLines.Length;
statusText.text = StatusLines[_statusIndex];
}
private void OnDisable()
{
StopStatusCycle();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 48d729b720c548e685793cc0348ae1c5
timeCreated: 1771494930