Add locks to async image loading, count how many have loaded, fix error log

This commit is contained in:
Nick 2022-09-13 19:06:50 -04:00
parent d20db7d211
commit d3e44d0e69
2 changed files with 58 additions and 33 deletions

View File

@ -95,7 +95,7 @@ namespace NewHorizons.Builder.Props
var slide = new Slide(); var slide = new Slide();
var slideInfo = info.slides[i]; var slideInfo = info.slides[i];
imageLoader.pathsToLoad.Add(mod.ModHelper.Manifest.ModFolderPath + slideInfo.imagePath); imageLoader.PathsToLoad.Add(mod.ModHelper.Manifest.ModFolderPath + slideInfo.imagePath);
AddModules(slideInfo, ref slide, mod); AddModules(slideInfo, ref slide, mod);
@ -197,7 +197,7 @@ namespace NewHorizons.Builder.Props
var slide = new Slide(); var slide = new Slide();
var slideInfo = info.slides[i]; var slideInfo = info.slides[i];
imageLoader.pathsToLoad.Add(mod.ModHelper.Manifest.ModFolderPath + slideInfo.imagePath); imageLoader.PathsToLoad.Add(mod.ModHelper.Manifest.ModFolderPath + slideInfo.imagePath);
AddModules(slideInfo, ref slide, mod); AddModules(slideInfo, ref slide, mod);
@ -263,7 +263,7 @@ namespace NewHorizons.Builder.Props
var slide = new Slide(); var slide = new Slide();
var slideInfo = slides[i]; var slideInfo = slides[i];
imageLoader.pathsToLoad.Add(mod.ModHelper.Manifest.ModFolderPath + slideInfo.imagePath); imageLoader.PathsToLoad.Add(mod.ModHelper.Manifest.ModFolderPath + slideInfo.imagePath);
AddModules(slideInfo, ref slide, mod); AddModules(slideInfo, ref slide, mod);
@ -336,7 +336,7 @@ namespace NewHorizons.Builder.Props
var slide = new Slide(); var slide = new Slide();
var slideInfo = slides[i]; var slideInfo = slides[i];
imageLoader.pathsToLoad.Add(mod.ModHelper.Manifest.ModFolderPath + slideInfo.imagePath); imageLoader.PathsToLoad.Add(mod.ModHelper.Manifest.ModFolderPath + slideInfo.imagePath);
AddModules(slideInfo, ref slide, mod); AddModules(slideInfo, ref slide, mod);

View File

@ -3,10 +3,10 @@ using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using UnityEngine; using UnityEngine;
using UnityEngine.Events; using UnityEngine.Events;
using UnityEngine.Networking; using UnityEngine.Networking;
using UnityEngine.UIElements;
namespace NewHorizons.Utility namespace NewHorizons.Utility
{ {
@ -128,7 +128,7 @@ namespace NewHorizons.Utility
var texture = (new Texture2D(size * 4, size * 4, TextureFormat.ARGB32, false)); var texture = (new Texture2D(size * 4, size * 4, TextureFormat.ARGB32, false));
texture.name = "SlideReelAtlas"; texture.name = "SlideReelAtlas";
Color[] fillPixels = new Color[size * size * 4 * 4]; var fillPixels = new Color[size * size * 4 * 4];
for (int xIndex = 0; xIndex < 4; xIndex++) for (int xIndex = 0; xIndex < 4; xIndex++)
{ {
for (int yIndex = 0; yIndex < 4; yIndex++) for (int yIndex = 0; yIndex < 4; yIndex++)
@ -276,8 +276,8 @@ namespace NewHorizons.Utility
{ {
var tex = (new Texture2D(1, 1, TextureFormat.ARGB32, false)); var tex = (new Texture2D(1, 1, TextureFormat.ARGB32, false));
tex.name = "Clear"; tex.name = "Clear";
Color fillColor = Color.clear; var fillColor = Color.clear;
Color[] fillPixels = new Color[tex.width * tex.height]; var fillPixels = new Color[tex.width * tex.height];
for (int i = 0; i < fillPixels.Length; i++) for (int i = 0; i < fillPixels.Length; i++)
{ {
fillPixels[i] = fillColor; fillPixels[i] = fillColor;
@ -296,7 +296,7 @@ namespace NewHorizons.Utility
{ {
var tex = (new Texture2D(width, height, TextureFormat.ARGB32, false)); var tex = (new Texture2D(width, height, TextureFormat.ARGB32, false));
tex.name = src.name + "CanvasScaled"; tex.name = src.name + "CanvasScaled";
Color[] fillPixels = new Color[tex.width * tex.height]; var fillPixels = new Color[tex.width * tex.height];
for (int i = 0; i < tex.width; i++) for (int i = 0; i < tex.width; i++)
{ {
for (int j = 0; j < tex.height; j++) for (int j = 0; j < tex.height; j++)
@ -339,14 +339,14 @@ namespace NewHorizons.Utility
} }
public static Texture2D MakeSolidColorTexture(int width, int height, Color color) public static Texture2D MakeSolidColorTexture(int width, int height, Color color)
{ {
Color[] pixels = new Color[width*height]; var pixels = new Color[width*height];
for(int i = 0; i < pixels.Length; i++) for(int i = 0; i < pixels.Length; i++)
{ {
pixels[i] = color; pixels[i] = color;
} }
Texture2D newTexture = new Texture2D(width, height); var newTexture = new Texture2D(width, height);
newTexture.SetPixels(pixels); newTexture.SetPixels(pixels);
newTexture.Apply(); newTexture.Apply();
return newTexture; return newTexture;
@ -364,10 +364,15 @@ namespace NewHorizons.Utility
// Modified from https://stackoverflow.com/a/69141085/9643841 // Modified from https://stackoverflow.com/a/69141085/9643841
public class AsyncImageLoader : MonoBehaviour public class AsyncImageLoader : MonoBehaviour
{ {
public List<string> pathsToLoad = new List<string>(); public List<string> PathsToLoad { get; private set; } = new ();
public class ImageLoadedEvent : UnityEvent<Texture2D, int> { } public class ImageLoadedEvent : UnityEvent<Texture2D, int> { }
public ImageLoadedEvent imageLoadedEvent = new ImageLoadedEvent(); 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, // 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
@ -375,39 +380,59 @@ namespace NewHorizons.Utility
void Start() void Start()
{ {
for (int i = 0; i < pathsToLoad.Count; i++) imageLoadedEvent.AddListener(OnImageLoaded);
for (int i = 0; i < PathsToLoad.Count; i++)
{ {
StartCoroutine(DownloadTexture(pathsToLoad[i], i)); StartCoroutine(DownloadTexture(PathsToLoad[i], i));
}
}
private void OnImageLoaded(Texture texture, int index)
{
lock (_lockObj)
{
_loadedCount++;
if (_loadedCount >= PathsToLoad.Count)
{
Logger.LogVerbose($"Finished loading all textures for {gameObject.name} (one was {PathsToLoad.FirstOrDefault()}");
FinishedLoading = true;
}
} }
} }
IEnumerator DownloadTexture(string url, int index) IEnumerator DownloadTexture(string url, int index)
{ {
if (_loadedTextures.ContainsKey(url)) lock(_loadedTextures)
{ {
Logger.LogVerbose($"Already loaded image at path: {url}"); if (_loadedTextures.ContainsKey(url))
var texture = _loadedTextures[url]; {
imageLoadedEvent.Invoke(texture, index); Logger.LogVerbose($"Already loaded image {index}:{url}");
yield break; var texture = _loadedTextures[url];
imageLoadedEvent?.Invoke(texture, index);
yield break;
}
} }
using (UnityWebRequest uwr = UnityWebRequestTexture.GetTexture(url)) using UnityWebRequest uwr = UnityWebRequestTexture.GetTexture(url);
yield return uwr.SendWebRequest();
var hasError = uwr.error != null && uwr.error != "";
if (hasError)
{ {
yield return uwr.SendWebRequest(); Logger.LogError($"Failed to load {index}:{url} - {uwr.error}");
}
else
{
var texture = DownloadHandlerTexture.GetContent(uwr);
var hasError = uwr.error != null && uwr.error != ""; lock(_loadedTextures)
if (hasError) // (uwr.result != UnityWebRequest.Result.Success)
{ {
Debug.Log(uwr.error);
}
else
{
var texture = DownloadHandlerTexture.GetContent(uwr);
if (_loadedTextures.ContainsKey(url)) if (_loadedTextures.ContainsKey(url))
{ {
Logger.LogVerbose($"Already loaded image at path: {url}"); Logger.LogVerbose($"Already loaded image {index}:{url}");
Destroy(texture); Destroy(texture);
texture = _loadedTextures[url]; texture = _loadedTextures[url];
} }
@ -416,7 +441,7 @@ namespace NewHorizons.Utility
_loadedTextures.Add(url, texture); _loadedTextures.Add(url, texture);
} }
imageLoadedEvent.Invoke(texture, index); imageLoadedEvent?.Invoke(texture, index);
} }
} }
} }