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);
|
var slideCollection = new SlideCollection(slidesCount);
|
||||||
slideCollection.streamingAssetIdentifier = string.Empty; // NREs if null
|
slideCollection.streamingAssetIdentifier = string.Empty; // NREs if null
|
||||||
|
|
||||||
// The base game ones only have 15 slides max
|
// We can fit 16 slides max into an atlas
|
||||||
var textures = new Texture2D[slidesCount >= 15 ? 15 : slidesCount];
|
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);
|
var key = GetUniqueSlideReelID(mod, info.slides);
|
||||||
|
|
||||||
@ -167,11 +167,12 @@ namespace NewHorizons.Builder.Props
|
|||||||
|
|
||||||
slideCollection.slides[index]._image = ImageUtilities.InvertSlideReel(mod, tex, originalPath);
|
slideCollection.slides[index]._image = ImageUtilities.InvertSlideReel(mod, tex, originalPath);
|
||||||
NHLogger.LogVerbose($"Slide reel make reel invert texture {(DateTime.Now - time).TotalMilliseconds}ms");
|
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)
|
if (index < textures.Length)
|
||||||
{
|
{
|
||||||
textures[index] = tex;
|
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
|
// all textures required to build the reel's textures have been loaded
|
||||||
var slidesBack = slideReelObj.GetComponentInChildren<TransformAnimator>().transform.Find("Slides_Back").GetComponent<MeshRenderer>();
|
var slidesBack = slideReelObj.GetComponentInChildren<TransformAnimator>().transform.Find("Slides_Back").GetComponent<MeshRenderer>();
|
||||||
@ -315,7 +316,7 @@ namespace NewHorizons.Builder.Props
|
|||||||
var slideCollection = new SlideCollection(slidesCount);
|
var slideCollection = new SlideCollection(slidesCount);
|
||||||
slideCollection.streamingAssetIdentifier = string.Empty; // NREs if null
|
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) =>
|
imageLoader.imageLoadedEvent.AddListener((Texture2D tex, int index, string originalPath) =>
|
||||||
{
|
{
|
||||||
var time = DateTime.Now;
|
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
|
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
|
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) =>
|
imageLoader.imageLoadedEvent.AddListener((Texture2D tex, int index, string originalPath) =>
|
||||||
{
|
{
|
||||||
var time = DateTime.Now;
|
var time = DateTime.Now;
|
||||||
@ -406,13 +407,13 @@ namespace NewHorizons.Builder.Props
|
|||||||
visionBeamEffect.SetActive(false);
|
visionBeamEffect.SetActive(false);
|
||||||
|
|
||||||
// Set up slides
|
// 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 slides = info.slides;
|
||||||
var slidesCount = slides.Length;
|
var slidesCount = slides.Length;
|
||||||
var slideCollection = new SlideCollection(slidesCount);
|
var slideCollection = new SlideCollection(slidesCount);
|
||||||
slideCollection.streamingAssetIdentifier = string.Empty; // NREs if null
|
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 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
|
// 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;
|
var time = DateTime.Now;
|
||||||
slideCollection.slides[index]._image = tex;
|
slideCollection.slides[index]._image = tex;
|
||||||
|
|
||||||
if (Interlocked.Increment(ref displaySlidesLoaded) == slides.Length)
|
displaySlidesLoaded++;
|
||||||
|
if (displaySlidesLoaded == slides.Length)
|
||||||
{
|
{
|
||||||
mindSlideProjector.enabled = true;
|
mindSlideProjector.enabled = true;
|
||||||
visionBeamEffect.SetActive(true);
|
visionBeamEffect.SetActive(true);
|
||||||
@ -454,21 +456,22 @@ namespace NewHorizons.Builder.Props
|
|||||||
return standingTorch;
|
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 invertedImageLoader = new SlideReelAsyncImageLoader();
|
||||||
var atlasImageLoader = new SlideReelAsyncImageLoader();
|
var atlasImageLoader = new SlideReelAsyncImageLoader();
|
||||||
var imageLoader = new SlideReelAsyncImageLoader();
|
var imageLoader = new SlideReelAsyncImageLoader();
|
||||||
|
|
||||||
var textureNames = slides.Select(x => Path.GetFileNameWithoutExtension(x.imagePath)).ToArray();
|
|
||||||
var atlasKey = GetUniqueSlideReelID(mod, slides);
|
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.PathsToLoad.Add((0, Path.Combine(mod.ModHelper.Manifest.ModFolderPath, ATLAS_SLIDE_CACHE_FOLDER, $"{atlasKey}.png")));
|
||||||
atlasImageLoader.imageLoadedEvent.AddListener((Texture2D t, int i, string s) =>
|
atlasImageLoader.imageLoadedEvent.AddListener((Texture2D t, int i, string s) =>
|
||||||
{
|
{
|
||||||
NHLogger.Log($"SLIDE REEL ATLAS from {slides.First().imagePath}: {s}");
|
NHLogger.Log($"SLIDE REEL ATLAS from {slides.First().imagePath}: {s}");
|
||||||
ImageUtilities.TrackCachedTexture(atlasKey, t);
|
ImageUtilities.TrackCachedTexture(atlasKey, t);
|
||||||
});
|
});
|
||||||
|
|
||||||
for (int i = 0; i < slides.Length; i++)
|
for (int i = 0; i < slides.Length; i++)
|
||||||
{
|
{
|
||||||
var slide = new Slide();
|
var slide = new Slide();
|
||||||
@ -481,12 +484,15 @@ namespace NewHorizons.Builder.Props
|
|||||||
}
|
}
|
||||||
else
|
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.PathsToLoad.Add((i, Path.Combine(mod.ModHelper.Manifest.ModFolderPath, INVERTED_SLIDE_CACHE_FOLDER, slideInfo.imagePath)));
|
||||||
invertedImageLoader.imageLoadedEvent.AddListener((Texture2D t, int i, string s) =>
|
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";
|
var path = Path.Combine(mod.ModHelper.Manifest.ModFolderPath, slides[i].imagePath);
|
||||||
ImageUtilities.TrackCachedTexture(path, t);
|
var key = $"{ImageUtilities.GetKey(path)} > invert";
|
||||||
|
ImageUtilities.TrackCachedTexture(key, t);
|
||||||
});
|
});
|
||||||
|
|
||||||
imageLoader.PathsToLoad.Add((i, Path.Combine(mod.ModHelper.Manifest.ModFolderPath, slideInfo.imagePath)));
|
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 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 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)
|
public static bool IsTextureLoaded(IModBehaviour mod, string filename)
|
||||||
{
|
{
|
||||||
var path = Path.Combine(mod.ModHelper.Manifest.ModFolderPath, filename);
|
var path = Path.Combine(mod.ModHelper.Manifest.ModFolderPath, filename);
|
||||||
var key = GetKey(path).Replace('\\', '/');
|
var key = GetKey(path);
|
||||||
return _textureCache.ContainsKey(key);
|
return _textureCache.ContainsKey(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -10,10 +10,12 @@ using UnityEngine.SceneManagement;
|
|||||||
|
|
||||||
namespace NewHorizons.Utility.Files;
|
namespace NewHorizons.Utility.Files;
|
||||||
|
|
||||||
// Modified from https://stackoverflow.com/a/69141085/9643841
|
/// <summary>
|
||||||
// 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!
|
/// Modified from https://stackoverflow.com/a/69141085/9643841
|
||||||
// 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
|
/// 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!
|
||||||
// This is why we do it sequentially using SingletonAsyncImageLoader
|
/// 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 class SlideReelAsyncImageLoader
|
||||||
{
|
{
|
||||||
public List<(int index, string path)> PathsToLoad { get; private set; } = new();
|
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 class ImageLoadedEvent : UnityEvent<Texture2D, int, string> { }
|
||||||
public ImageLoadedEvent imageLoadedEvent = new();
|
public ImageLoadedEvent imageLoadedEvent = new();
|
||||||
|
|
||||||
private readonly object _lockObj = new();
|
|
||||||
|
|
||||||
public bool FinishedLoading { get; private set; }
|
public bool FinishedLoading { get; private set; }
|
||||||
private int _loadedCount = 0;
|
private int _loadedCount = 0;
|
||||||
|
|
||||||
// TODO: set up an optional “StartLoading” and “StartUnloading” condition on AsyncTextureLoader,
|
// 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
|
// 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)
|
// for them to start loading, and unload when the player leaves)
|
||||||
|
// also remember this for ship logs!!! lol
|
||||||
|
|
||||||
private bool _started;
|
private bool _started;
|
||||||
private bool _clamp;
|
private bool _clamp;
|
||||||
@ -52,8 +53,6 @@ public class SlideReelAsyncImageLoader
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void OnImageLoaded(Texture texture, int index, string originalPath)
|
private void OnImageLoaded(Texture texture, int index, string originalPath)
|
||||||
{
|
|
||||||
lock (_lockObj)
|
|
||||||
{
|
{
|
||||||
_loadedCount++;
|
_loadedCount++;
|
||||||
|
|
||||||
@ -63,9 +62,8 @@ public class SlideReelAsyncImageLoader
|
|||||||
FinishedLoading = true;
|
FinishedLoading = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
internal IEnumerator DownloadTextures()
|
private IEnumerator DownloadTextures()
|
||||||
{
|
{
|
||||||
foreach (var (index, path) in PathsToLoad)
|
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);
|
var key = ImageUtilities.GetKey(url);
|
||||||
if (ImageUtilities.CheckCachedTexture(key, out var existingTexture))
|
if (ImageUtilities.CheckCachedTexture(key, out var existingTexture))
|
||||||
@ -97,8 +95,6 @@ public class SlideReelAsyncImageLoader
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var handler = (DownloadHandlerTexture)uwr.downloadHandler;
|
|
||||||
|
|
||||||
var texture = DownloadHandlerTexture.GetContent(uwr);
|
var texture = DownloadHandlerTexture.GetContent(uwr);
|
||||||
texture.name = key;
|
texture.name = key;
|
||||||
if (_clamp)
|
if (_clamp)
|
||||||
@ -108,6 +104,7 @@ public class SlideReelAsyncImageLoader
|
|||||||
|
|
||||||
if (ImageUtilities.CheckCachedTexture(key, out existingTexture))
|
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}");
|
NHLogger.LogVerbose($"Already loaded image {index}:{url}");
|
||||||
GameObject.Destroy(texture);
|
GameObject.Destroy(texture);
|
||||||
texture = (Texture2D)existingTexture;
|
texture = (Texture2D)existingTexture;
|
||||||
@ -117,7 +114,6 @@ public class SlideReelAsyncImageLoader
|
|||||||
ImageUtilities.TrackCachedTexture(key, texture);
|
ImageUtilities.TrackCachedTexture(key, texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
yield return null;
|
|
||||||
var time = DateTime.Now;
|
var time = DateTime.Now;
|
||||||
imageLoadedEvent?.Invoke(texture, index, url);
|
imageLoadedEvent?.Invoke(texture, index, url);
|
||||||
NHLogger.LogVerbose($"Slide reel event took: {(DateTime.Now - time).TotalMilliseconds}ms");
|
NHLogger.LogVerbose($"Slide reel event took: {(DateTime.Now - time).TotalMilliseconds}ms");
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user