Skip to content

Commit ae7317a

Browse files
committed
Added Shop Loading and Error Overlays
1 parent c0ac2c9 commit ae7317a

7 files changed

Lines changed: 189 additions & 19 deletions

File tree

12.1 KB
Binary file not shown.

LevelImposter/LevelImposter.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ public override void Load()
7777
ClassInjector.RegisterTypeInIl2Cpp<AssetDB>();
7878

7979
ClassInjector.RegisterTypeInIl2Cpp<Shop.ProgressBar>();
80+
ClassInjector.RegisterTypeInIl2Cpp<ConnectionAnimation>();
81+
ClassInjector.RegisterTypeInIl2Cpp<PulseAnimation>();
8082
ClassInjector.RegisterTypeInIl2Cpp<RandomOverlay>();
8183
ClassInjector.RegisterTypeInIl2Cpp<MapBanner>();
8284
ClassInjector.RegisterTypeInIl2Cpp<GameObjectGrid>();

LevelImposter/Networking/API/HTTPHandler.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Threading.Tasks;
88
using LevelImposter.Core;
99
using Reactor.Utilities;
10+
using UnityEngine;
1011
using UnityEngine.Networking;
1112

1213
using DownloadResult = LevelImposter.Networking.API.HTTPHandler.HTTPResult<LevelImposter.Core.FileStore>;
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using BepInEx.Unity.IL2CPP.Utils.Collections;
5+
using Il2CppInterop.Runtime.Attributes;
6+
using Il2CppInterop.Runtime.InteropTypes.Fields;
7+
using UnityEngine;
8+
9+
namespace LevelImposter.Shop;
10+
11+
public class ConnectionAnimation(IntPtr intPtr) : MonoBehaviour(intPtr)
12+
{
13+
public Il2CppValueField<Vector3> startPosition;
14+
public Il2CppValueField<Vector3> endPosition;
15+
public Il2CppValueField<int> dotCount;
16+
public Il2CppReferenceField<SpriteRenderer> dotPrefab;
17+
public Il2CppValueField<float> fadePercentage;
18+
public Il2CppValueField<float> animationDuration;
19+
20+
private readonly List<SpriteRenderer> _dots = [];
21+
22+
public void Start()
23+
{
24+
for (var i = 0; i < dotCount; i++)
25+
_dots.Add(Instantiate(dotPrefab.Value, transform));
26+
}
27+
public void OnEnable()
28+
{
29+
StartCoroutine(CoAnimateDots().WrapToIl2Cpp());
30+
}
31+
32+
[HideFromIl2Cpp]
33+
private IEnumerator CoAnimateDots()
34+
{
35+
var t = 0.0f;
36+
while (true)
37+
{
38+
var durationPerDot = animationDuration / dotCount;
39+
t += Time.deltaTime;
40+
41+
// Update each dot
42+
for (var i = 0; i < _dots.Count; i++)
43+
{
44+
// Calculate progress with offset
45+
var dotTimeOffset = t + (i * durationPerDot);
46+
var progress = (dotTimeOffset % animationDuration) / animationDuration;
47+
48+
// Position
49+
_dots[i].transform.localPosition = Vector3.Lerp(startPosition, endPosition, progress);
50+
51+
// Opacity
52+
float opacity;
53+
if (progress - fadePercentage < 0)
54+
opacity = progress / fadePercentage;
55+
else if (progress > 1.0f - fadePercentage)
56+
opacity = (1.0f - progress) / fadePercentage;
57+
else
58+
opacity = 1.0f;
59+
60+
_dots[i].color = new Color(
61+
_dots[i].color.r,
62+
_dots[i].color.g,
63+
_dots[i].color.b,
64+
opacity);
65+
66+
}
67+
68+
// Wait a frame
69+
yield return null;
70+
}
71+
}
72+
}

LevelImposter/Shop/Components/MapBanner.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ public void OnDownloadClick()
108108
OnMapDownloaded,
109109
LILogger.Error);
110110
}
111+
[HideFromIl2Cpp]
111112
private void OnMapDownloaded(FileStore _)
112113
{
113114
// ShopManager.Instance?.SetOverlayEnabled(false);
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using BepInEx.Unity.IL2CPP.Utils.Collections;
5+
using Il2CppInterop.Runtime.Attributes;
6+
using Il2CppInterop.Runtime.InteropTypes.Fields;
7+
using UnityEngine;
8+
9+
namespace LevelImposter.Shop;
10+
11+
public class PulseAnimation(IntPtr intPtr) : MonoBehaviour(intPtr)
12+
{
13+
public Il2CppValueField<float> pulseSpeed;
14+
public Il2CppValueField<float> minOpacity;
15+
public Il2CppValueField<float> maxOpacity;
16+
17+
private SpriteRenderer? _spriteRenderer;
18+
19+
public void Awake()
20+
{
21+
_spriteRenderer = GetComponent<SpriteRenderer>();
22+
}
23+
public void Update()
24+
{
25+
var t = (Mathf.Sin(Time.time * pulseSpeed) + 1f) / 2f; // Normalized to [0, 1]
26+
27+
_spriteRenderer?.color = new Color(
28+
_spriteRenderer.color.r,
29+
_spriteRenderer.color.g,
30+
_spriteRenderer.color.b,
31+
Mathf.Lerp(minOpacity, maxOpacity, t)
32+
);
33+
}
34+
}

LevelImposter/Shop/Components/ShopManager.cs

Lines changed: 79 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using LevelImposter.DB;
1010
using LevelImposter.FileIO;
1111
using LevelImposter.Networking.API;
12+
using TMPro;
1213
using UnityEngine;
1314

1415
namespace LevelImposter.Shop;
@@ -37,16 +38,31 @@ public class ShopManager(IntPtr intPtr) : MonoBehaviour(intPtr)
3738
public Il2CppReferenceField<GameObjectGrid> mapBannerGrid;
3839
public Il2CppReferenceField<PassiveButton> exitButton;
3940
public Il2CppReferenceField<PassiveButton> openMapsFolderButton;
41+
public Il2CppReferenceField<GameObject> loadingOverlay;
42+
public Il2CppReferenceField<TextMeshPro> loadingText;
43+
public Il2CppReferenceField<GameObject> errorOverlay;
44+
public Il2CppReferenceField<TextMeshPro> errorText;
4045

4146
public static ShopManager? Instance { get; private set; }
4247

4348
private const string CONTROLLER_OVERLAY_ID = "LIShop";
4449

4550
/// If true, re-runs the map randomization when the shop is closed
4651
private bool _randomizeMapsOnClose;
47-
4852
private ShopTab _currentTab = ShopTab.None;
4953
private ShopTabButton[]? _shopTabButtons;
54+
private readonly string[] _funLoadingTexts =
55+
[
56+
"Searching dropship...",
57+
"Calibrating engines...",
58+
"Searching for habitable planets...",
59+
"Stabilizing reactor...",
60+
"Scanning for planetary systems...",
61+
"Aligning telescope...",
62+
"Navigating asteroids...",
63+
"Diverting power...",
64+
"Doing card swipe..."
65+
];
5066

5167
public void Awake()
5268
{
@@ -131,13 +147,22 @@ public void SetTab(ShopTab tab, Sprite? titleSprite = null)
131147
SetMaps(lobbyMaps);
132148
break;
133149
case ShopTab.FeaturedWorkshopMaps:
134-
LevelImposterAPI.GetFeatured(m => OnWorkshopLoaded(m, tab), LILogger.Error);
150+
SetLoadingVisible(true);
151+
LevelImposterAPI.GetFeatured(
152+
m => OnWorkshopLoaded(m, tab),
153+
error => OnError(tab, error));
135154
break;
136155
case ShopTab.TopWorkshopMaps:
137-
LevelImposterAPI.GetTop(m => OnWorkshopLoaded(m, tab), LILogger.Error);
156+
SetLoadingVisible(true);
157+
LevelImposterAPI.GetTop(
158+
m => OnWorkshopLoaded(m, tab),
159+
error => OnError(tab, error));
138160
break;
139161
case ShopTab.RecentWorkshopMaps:
140-
LevelImposterAPI.GetRecent(m => OnWorkshopLoaded(m, tab), LILogger.Error);
162+
SetLoadingVisible(true);
163+
LevelImposterAPI.GetRecent(
164+
m => OnWorkshopLoaded(m, tab),
165+
error => OnError(tab, error));
141166
break;
142167
case ShopTab.None:
143168
break;
@@ -146,6 +171,33 @@ public void SetTab(ShopTab tab, Sprite? titleSprite = null)
146171
}
147172
}
148173

174+
[HideFromIl2Cpp]
175+
private void OnWorkshopLoaded(LIMetadata[] maps, ShopTab targetTab)
176+
{
177+
if (_currentTab != targetTab)
178+
return;
179+
180+
SetMaps(maps);
181+
}
182+
[HideFromIl2Cpp]
183+
private void OnError(ShopTab tab, string message)
184+
{
185+
if (_currentTab != tab)
186+
return;
187+
188+
SetErrorVisible(true, message);
189+
}
190+
private void SetErrorVisible(bool isVisible, string message = "")
191+
{
192+
errorOverlay.Value.SetActive(isVisible);
193+
errorText.Value.text = message;
194+
if (!isVisible)
195+
return;
196+
197+
// Disable loading overlay
198+
SetLoadingVisible(false);
199+
}
200+
149201
/// <summary>
150202
/// Updates the visual state of the tab buttons
151203
/// </summary>
@@ -157,29 +209,19 @@ private void UpdateTabButtonState()
157209
foreach (var tabButton in _shopTabButtons)
158210
tabButton.SetTabSelected(tabButton.TabType == _currentTab);
159211
}
160-
161-
/// <summary>
162-
/// Called when workshop maps are loaded.
163-
/// Just checks if the current tab is still the target tab before setting the maps.
164-
/// </summary>
165-
/// <param name="maps">The loaded maps</param>
166-
/// <param name="targetTab">The target tab</param>
167-
[HideFromIl2Cpp]
168-
private void OnWorkshopLoaded(LIMetadata[] maps, ShopTab targetTab)
169-
{
170-
if (_currentTab != targetTab)
171-
return;
172-
173-
SetMaps(maps);
174-
}
175212

213+
176214
/// <summary>
177215
/// Sets the maps to display in the shop
178216
/// </summary>
179217
/// <param name="maps">The maps to display</param>
180218
[HideFromIl2Cpp]
181219
private void SetMaps(LIMetadata[] maps)
182220
{
221+
// Hide Overlays
222+
SetLoadingVisible(false);
223+
SetErrorVisible(false);
224+
183225
// Clear Existing Banners
184226
mapBannerGrid.Value.DestroyAll();
185227

@@ -204,6 +246,24 @@ public void RandomizeMapOnClose()
204246
{
205247
_randomizeMapsOnClose = true;
206248
}
249+
250+
/// <summary>
251+
/// Shows or hides the loading overlay
252+
/// </summary>
253+
/// <param name="isVisible">Whether the loading overlay should be visible</param>
254+
public void SetLoadingVisible(bool isVisible)
255+
{
256+
loadingOverlay.Value.SetActive(isVisible);
257+
if (!isVisible)
258+
return;
259+
260+
// Disable error overlay
261+
SetErrorVisible(false);
262+
263+
// Randomize loading text
264+
var randomIndex = UnityEngine.Random.Range(0, _funLoadingTexts.Length);
265+
loadingText.Value.text = _funLoadingTexts[randomIndex];
266+
}
207267

208268
private void AddStarField()
209269
{

0 commit comments

Comments
 (0)