mirror of
https://github.com/Outer-Wilds-New-Horizons/new-horizons.git
synced 2025-12-11 20:15:44 +01:00
comment all the async stuff, STOP USING LOCKS AND ATOMICS
This commit is contained in:
parent
c9d4125f95
commit
de8470e595
@ -148,10 +148,10 @@ namespace NewHorizons.Builder.Props
|
||||
var slideCollection = new SlideCollection(slidesCount);
|
||||
slideCollection.streamingAssetIdentifier = string.Empty; // NREs if null
|
||||
|
||||
// The base game ones only have 15 slides max
|
||||
var textures = new Texture2D[slidesCount >= 15 ? 15 : slidesCount];
|
||||
// We can fit 16 slides max into an atlas
|
||||
var textures = new Texture2D[slidesCount > 16 ? 16 : slidesCount];
|
||||
|
||||
var imageLoader = AddAsyncLoader(slideReelObj, mod, info.slides, ref slideCollection);
|
||||
var imageLoader = StartAsyncLoader(mod, info.slides, ref slideCollection);
|
||||
|
||||
var key = GetUniqueSlideReelID(mod, info.slides);
|
||||
|
||||
@ -167,11 +167,12 @@ namespace NewHorizons.Builder.Props
|
||||
|
||||
slideCollection.slides[index]._image = ImageUtilities.InvertSlideReel(mod, tex, originalPath);
|
||||
NHLogger.LogVerbose($"Slide reel make reel invert texture {(DateTime.Now - time).TotalMilliseconds}ms");
|
||||
// Track the first 15 to put on the slide reel object
|
||||
// Track the first 16 to put on the slide reel object
|
||||
if (index < textures.Length)
|
||||
{
|
||||
textures[index] = tex;
|
||||
if (Interlocked.Increment(ref displaySlidesLoaded) >= textures.Length)
|
||||
displaySlidesLoaded++;
|
||||
if (displaySlidesLoaded == textures.Length)
|
||||
{
|
||||
// all textures required to build the reel's textures have been loaded
|
||||
var slidesBack = slideReelObj.GetComponentInChildren<TransformAnimator>().transform.Find("Slides_Back").GetComponent<MeshRenderer>();
|
||||
@ -315,7 +316,7 @@ namespace NewHorizons.Builder.Props
|
||||
var slideCollection = new SlideCollection(slidesCount);
|
||||
slideCollection.streamingAssetIdentifier = string.Empty; // NREs if null
|
||||
|
||||
var imageLoader = AddAsyncLoader(projectorObj, mod, info.slides, ref slideCollection);
|
||||
var imageLoader = StartAsyncLoader(mod, info.slides, ref slideCollection);
|
||||
imageLoader.imageLoadedEvent.AddListener((Texture2D tex, int index, string originalPath) =>
|
||||
{
|
||||
var time = DateTime.Now;
|
||||
@ -359,7 +360,7 @@ namespace NewHorizons.Builder.Props
|
||||
var slideCollection = new SlideCollection(slidesCount); // TODO: uh I think that info.slides[i].playTimeDuration is not being read here... note to self for when I implement support for that: 0.7 is what to default to if playTimeDuration turns out to be 0
|
||||
slideCollection.streamingAssetIdentifier = string.Empty; // NREs if null
|
||||
|
||||
var imageLoader = AddAsyncLoader(g, mod, info.slides, ref slideCollection);
|
||||
var imageLoader = StartAsyncLoader(mod, info.slides, ref slideCollection);
|
||||
imageLoader.imageLoadedEvent.AddListener((Texture2D tex, int index, string originalPath) =>
|
||||
{
|
||||
var time = DateTime.Now;
|
||||
@ -406,13 +407,13 @@ namespace NewHorizons.Builder.Props
|
||||
visionBeamEffect.SetActive(false);
|
||||
|
||||
// Set up slides
|
||||
// The number of slides is unlimited, 15 is only for texturing the actual slide reel item. This is not a slide reel item
|
||||
// The number of slides is unlimited, 16 is only for texturing the actual slide reel item. This is not a slide reel item
|
||||
var slides = info.slides;
|
||||
var slidesCount = slides.Length;
|
||||
var slideCollection = new SlideCollection(slidesCount);
|
||||
slideCollection.streamingAssetIdentifier = string.Empty; // NREs if null
|
||||
|
||||
var imageLoader = AddAsyncLoader(standingTorch, mod, slides, ref slideCollection);
|
||||
var imageLoader = StartAsyncLoader(mod, slides, ref slideCollection);
|
||||
|
||||
// This variable just lets us track how many of the slides have been loaded.
|
||||
// This way as soon as the last one is loaded (due to async loading, this may be
|
||||
@ -425,7 +426,8 @@ namespace NewHorizons.Builder.Props
|
||||
var time = DateTime.Now;
|
||||
slideCollection.slides[index]._image = tex;
|
||||
|
||||
if (Interlocked.Increment(ref displaySlidesLoaded) == slides.Length)
|
||||
displaySlidesLoaded++;
|
||||
if (displaySlidesLoaded == slides.Length)
|
||||
{
|
||||
mindSlideProjector.enabled = true;
|
||||
visionBeamEffect.SetActive(true);
|
||||
@ -454,21 +456,22 @@ namespace NewHorizons.Builder.Props
|
||||
return standingTorch;
|
||||
}
|
||||
|
||||
private static SlideReelAsyncImageLoader AddAsyncLoader(GameObject gameObject, IModBehaviour mod, SlideInfo[] slides, ref SlideCollection slideCollection)
|
||||
private static SlideReelAsyncImageLoader StartAsyncLoader(IModBehaviour mod, SlideInfo[] slides, ref SlideCollection slideCollection)
|
||||
{
|
||||
var invertedImageLoader = new SlideReelAsyncImageLoader();
|
||||
var atlasImageLoader = new SlideReelAsyncImageLoader();
|
||||
var imageLoader = new SlideReelAsyncImageLoader();
|
||||
|
||||
var textureNames = slides.Select(x => Path.GetFileNameWithoutExtension(x.imagePath)).ToArray();
|
||||
var atlasKey = GetUniqueSlideReelID(mod, slides);
|
||||
|
||||
// attempt to load atlas guy from disk and precache so theres a cache hit when using ImageUtilities
|
||||
atlasImageLoader.PathsToLoad.Add((0, Path.Combine(mod.ModHelper.Manifest.ModFolderPath, ATLAS_SLIDE_CACHE_FOLDER, $"{atlasKey}.png")));
|
||||
atlasImageLoader.imageLoadedEvent.AddListener((Texture2D t, int i, string s) =>
|
||||
{
|
||||
NHLogger.Log($"SLIDE REEL ATLAS from {slides.First().imagePath}: {s}");
|
||||
ImageUtilities.TrackCachedTexture(atlasKey, t);
|
||||
});
|
||||
|
||||
for (int i = 0; i < slides.Length; i++)
|
||||
{
|
||||
var slide = new Slide();
|
||||
@ -481,12 +484,15 @@ namespace NewHorizons.Builder.Props
|
||||
}
|
||||
else
|
||||
{
|
||||
// attempt to load inverted guy from disk and precache so theres a cache hit when using ImageUtilities
|
||||
invertedImageLoader.PathsToLoad.Add((i, Path.Combine(mod.ModHelper.Manifest.ModFolderPath, INVERTED_SLIDE_CACHE_FOLDER, slideInfo.imagePath)));
|
||||
invertedImageLoader.imageLoadedEvent.AddListener((Texture2D t, int i, string s) =>
|
||||
{
|
||||
var path = "\\" + Path.Combine(Path.GetFileName(Path.GetDirectoryName(mod.ModHelper.Manifest.ModFolderPath)), slides[i].imagePath) + " > invert";
|
||||
ImageUtilities.TrackCachedTexture(path, t);
|
||||
var path = Path.Combine(mod.ModHelper.Manifest.ModFolderPath, slides[i].imagePath);
|
||||
var key = $"{ImageUtilities.GetKey(path)} > invert";
|
||||
ImageUtilities.TrackCachedTexture(key, t);
|
||||
});
|
||||
|
||||
imageLoader.PathsToLoad.Add((i, Path.Combine(mod.ModHelper.Manifest.ModFolderPath, slideInfo.imagePath)));
|
||||
}
|
||||
|
||||
|
||||
@ -17,12 +17,13 @@ namespace NewHorizons.Utility.Files
|
||||
public static bool CheckCachedTexture(string key, out Texture existingTexture) => _textureCache.TryGetValue(key, out existingTexture);
|
||||
public static void TrackCachedTexture(string key, Texture texture) => _textureCache[key] = texture;
|
||||
|
||||
public static string GetKey(string path) => path.Substring(Main.Instance.ModHelper.OwmlConfig.ModsPath.Length);
|
||||
public static string GetKey(string path) =>
|
||||
path.Substring(Main.Instance.ModHelper.OwmlConfig.ModsPath.Length + 1).Replace('\\', '/');
|
||||
|
||||
public static bool IsTextureLoaded(IModBehaviour mod, string filename)
|
||||
{
|
||||
var path = Path.Combine(mod.ModHelper.Manifest.ModFolderPath, filename);
|
||||
var key = GetKey(path).Replace('\\', '/');
|
||||
var key = GetKey(path);
|
||||
return _textureCache.ContainsKey(key);
|
||||
}
|
||||
|
||||
|
||||
@ -10,10 +10,12 @@ using UnityEngine.SceneManagement;
|
||||
|
||||
namespace NewHorizons.Utility.Files;
|
||||
|
||||
// Modified from https://stackoverflow.com/a/69141085/9643841
|
||||
// Having more than one SlideReelAsyncImageLoader running at the same time is LAGGY. While loading the image data from the disk is async, nothing else is!
|
||||
// It will load the images async and then do tens to hundreds of callbacks to imageLoadedEvent all running at around the same time and lagging out the game
|
||||
// This is why we do it sequentially using SingletonAsyncImageLoader
|
||||
/// <summary>
|
||||
/// Modified from https://stackoverflow.com/a/69141085/9643841
|
||||
/// Having more than one SlideReelAsyncImageLoader running at the same time is LAGGY. While loading the image data from the disk is async, nothing else is!
|
||||
/// It will load the images async and then do tens to hundreds of callbacks to imageLoadedEvent all running at around the same time and lagging out the game
|
||||
/// This is why we do it sequentially using SingletonAsyncImageLoader
|
||||
/// </summary>
|
||||
public class SlideReelAsyncImageLoader
|
||||
{
|
||||
public List<(int index, string path)> PathsToLoad { get; private set; } = new();
|
||||
@ -21,14 +23,13 @@ public class SlideReelAsyncImageLoader
|
||||
public class ImageLoadedEvent : UnityEvent<Texture2D, int, string> { }
|
||||
public ImageLoadedEvent imageLoadedEvent = new();
|
||||
|
||||
private readonly object _lockObj = new();
|
||||
|
||||
public bool FinishedLoading { get; private set; }
|
||||
private int _loadedCount = 0;
|
||||
|
||||
// TODO: set up an optional “StartLoading” and “StartUnloading” condition on AsyncTextureLoader,
|
||||
// and make use of that for at least for projector stuff (require player to be in the same sector as the slides
|
||||
// for them to start loading, and unload when the player leaves)
|
||||
// also remember this for ship logs!!! lol
|
||||
|
||||
private bool _started;
|
||||
private bool _clamp;
|
||||
@ -53,19 +54,16 @@ public class SlideReelAsyncImageLoader
|
||||
|
||||
private void OnImageLoaded(Texture texture, int index, string originalPath)
|
||||
{
|
||||
lock (_lockObj)
|
||||
{
|
||||
_loadedCount++;
|
||||
_loadedCount++;
|
||||
|
||||
if (_loadedCount >= PathsToLoad.Count)
|
||||
{
|
||||
NHLogger.LogVerbose($"Finished loading all textures for a slide reel (one was {PathsToLoad.FirstOrDefault()}");
|
||||
FinishedLoading = true;
|
||||
}
|
||||
if (_loadedCount >= PathsToLoad.Count)
|
||||
{
|
||||
NHLogger.LogVerbose($"Finished loading all textures for a slide reel (one was {PathsToLoad.FirstOrDefault()}");
|
||||
FinishedLoading = true;
|
||||
}
|
||||
}
|
||||
|
||||
internal IEnumerator DownloadTextures()
|
||||
private IEnumerator DownloadTextures()
|
||||
{
|
||||
foreach (var (index, path) in PathsToLoad)
|
||||
{
|
||||
@ -75,7 +73,7 @@ public class SlideReelAsyncImageLoader
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator DownloadTexture(string url, int index)
|
||||
private IEnumerator DownloadTexture(string url, int index)
|
||||
{
|
||||
var key = ImageUtilities.GetKey(url);
|
||||
if (ImageUtilities.CheckCachedTexture(key, out var existingTexture))
|
||||
@ -97,8 +95,6 @@ public class SlideReelAsyncImageLoader
|
||||
}
|
||||
else
|
||||
{
|
||||
var handler = (DownloadHandlerTexture)uwr.downloadHandler;
|
||||
|
||||
var texture = DownloadHandlerTexture.GetContent(uwr);
|
||||
texture.name = key;
|
||||
if (_clamp)
|
||||
@ -108,6 +104,7 @@ public class SlideReelAsyncImageLoader
|
||||
|
||||
if (ImageUtilities.CheckCachedTexture(key, out existingTexture))
|
||||
{
|
||||
// the image could be loaded by something else by the time we're done doing async stuff
|
||||
NHLogger.LogVerbose($"Already loaded image {index}:{url}");
|
||||
GameObject.Destroy(texture);
|
||||
texture = (Texture2D)existingTexture;
|
||||
@ -117,7 +114,6 @@ public class SlideReelAsyncImageLoader
|
||||
ImageUtilities.TrackCachedTexture(key, texture);
|
||||
}
|
||||
|
||||
yield return null;
|
||||
var time = DateTime.Now;
|
||||
imageLoadedEvent?.Invoke(texture, index, url);
|
||||
NHLogger.LogVerbose($"Slide reel event took: {(DateTime.Now - time).TotalMilliseconds}ms");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user