mirror of
https://github.com/Outer-Wilds-New-Horizons/new-horizons.git
synced 2025-12-11 20:15:44 +01:00
Merge branch 'dev' into globalMusicModule
This commit is contained in:
commit
4664ff59df
@ -121,6 +121,7 @@ namespace NewHorizons.Builder.Props.Audio
|
|||||||
|
|
||||||
public static string GetCustomFrequencyName(SignalFrequency frequencyName)
|
public static string GetCustomFrequencyName(SignalFrequency frequencyName)
|
||||||
{
|
{
|
||||||
|
if (_customFrequencyNames == null) return string.Empty;
|
||||||
_customFrequencyNames.TryGetValue(frequencyName, out string name);
|
_customFrequencyNames.TryGetValue(frequencyName, out string name);
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
@ -140,6 +141,7 @@ namespace NewHorizons.Builder.Props.Audio
|
|||||||
|
|
||||||
public static string GetCustomSignalName(SignalName signalName)
|
public static string GetCustomSignalName(SignalName signalName)
|
||||||
{
|
{
|
||||||
|
if (_customSignalNames == null) return string.Empty;
|
||||||
_customSignalNames.TryGetValue(signalName, out string name);
|
_customSignalNames.TryGetValue(signalName, out string name);
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
using HarmonyLib;
|
||||||
using NewHorizons.External.Modules.Props;
|
using NewHorizons.External.Modules.Props;
|
||||||
using NewHorizons.External.Modules.Props.EchoesOfTheEye;
|
using NewHorizons.External.Modules.Props.EchoesOfTheEye;
|
||||||
using NewHorizons.Handlers;
|
using NewHorizons.Handlers;
|
||||||
@ -8,14 +9,18 @@ using OWML.Common;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading;
|
using System.Linq;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityEngine.InputSystem;
|
||||||
using static NewHorizons.Main;
|
using static NewHorizons.Main;
|
||||||
|
|
||||||
namespace NewHorizons.Builder.Props
|
namespace NewHorizons.Builder.Props
|
||||||
{
|
{
|
||||||
public static class ProjectionBuilder
|
public static class ProjectionBuilder
|
||||||
{
|
{
|
||||||
|
public const string INVERTED_SLIDE_CACHE_FOLDER = "SlideReelCache/Inverted";
|
||||||
|
public const string ATLAS_SLIDE_CACHE_FOLDER = "SlideReelCache/Atlas";
|
||||||
|
|
||||||
public static GameObject SlideReelWholePrefab { get; private set; }
|
public static GameObject SlideReelWholePrefab { get; private set; }
|
||||||
public static GameObject SlideReelWholePristinePrefab { get; private set; }
|
public static GameObject SlideReelWholePristinePrefab { get; private set; }
|
||||||
public static GameObject SlideReelWholeRustedPrefab { get; private set; }
|
public static GameObject SlideReelWholeRustedPrefab { get; private set; }
|
||||||
@ -113,6 +118,8 @@ namespace NewHorizons.Builder.Props
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string GetUniqueSlideReelID(IModBehaviour mod, SlideInfo[] slides) => $"{mod.ModHelper.Manifest.UniqueName}{slides.Join(x => x.imagePath)}".GetHashCode().ToString();
|
||||||
|
|
||||||
private static GameObject MakeSlideReel(GameObject planetGO, Sector sector, ProjectionInfo info, IModBehaviour mod)
|
private static GameObject MakeSlideReel(GameObject planetGO, Sector sector, ProjectionInfo info, IModBehaviour mod)
|
||||||
{
|
{
|
||||||
InitPrefabs();
|
InitPrefabs();
|
||||||
@ -139,33 +146,67 @@ 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 (invImageLoader, atlasImageLoader, imageLoader) = StartAsyncLoader(mod, info.slides, ref slideCollection, true, true);
|
||||||
|
|
||||||
// this variable just lets us track how many of the first 15 slides have been loaded.
|
var key = GetUniqueSlideReelID(mod, info.slides);
|
||||||
// this way as soon as the last one is loaded (due to async loading, this may be
|
|
||||||
// slide 7, or slide 3, or whatever), we can build the slide reel texture. This allows us
|
if (invImageLoader != null && atlasImageLoader != null)
|
||||||
// to avoid doing a "is every element in the array `textures` not null" check every time a texture finishes loading
|
{
|
||||||
int displaySlidesLoaded = 0;
|
// Loading directly from cache
|
||||||
imageLoader.imageLoadedEvent.AddListener(
|
invImageLoader.imageLoadedEvent.AddListener(
|
||||||
(Texture2D tex, int index) =>
|
(Texture2D tex, int index, string originalPath) =>
|
||||||
|
{
|
||||||
|
slideCollection.slides[index]._image = tex;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
atlasImageLoader.imageLoadedEvent.AddListener(
|
||||||
|
(Texture2D tex, int _, string originalPath) =>
|
||||||
|
{
|
||||||
|
// all textures required to build the reel's textures have been loaded
|
||||||
|
var slidesBack = slideReelObj.GetComponentInChildren<TransformAnimator>().transform.Find("Slides_Back").GetComponent<MeshRenderer>();
|
||||||
|
var slidesFront = slideReelObj.GetComponentInChildren<TransformAnimator>().transform.Find("Slides_Front").GetComponent<MeshRenderer>();
|
||||||
|
|
||||||
|
// Now put together the textures into a 4x4 thing for the materials
|
||||||
|
var reelTexture = tex;
|
||||||
|
slidesBack.material.mainTexture = reelTexture;
|
||||||
|
slidesBack.material.SetTexture(EmissionMap, reelTexture);
|
||||||
|
slidesBack.material.name = reelTexture.name;
|
||||||
|
slidesFront.material.mainTexture = reelTexture;
|
||||||
|
slidesFront.material.SetTexture(EmissionMap, reelTexture);
|
||||||
|
slidesFront.material.name = reelTexture.name;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// this variable just lets us track how many of the first 15 slides have been loaded.
|
||||||
|
// this way as soon as the last one is loaded (due to async loading, this may be
|
||||||
|
// slide 7, or slide 3, or whatever), we can build the slide reel texture. This allows us
|
||||||
|
// to avoid doing a "is every element in the array `textures` not null" check every time a texture finishes loading
|
||||||
|
int displaySlidesLoaded = 0;
|
||||||
|
imageLoader.imageLoadedEvent.AddListener(
|
||||||
|
(Texture2D tex, int index, string originalPath) =>
|
||||||
{
|
{
|
||||||
slideCollection.slides[index]._image = ImageUtilities.Invert(tex);
|
var time = DateTime.Now;
|
||||||
|
|
||||||
// Track the first 15 to put on the slide reel object
|
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 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>();
|
||||||
var slidesFront = slideReelObj.GetComponentInChildren<TransformAnimator>().transform.Find("Slides_Front").GetComponent<MeshRenderer>();
|
var slidesFront = slideReelObj.GetComponentInChildren<TransformAnimator>().transform.Find("Slides_Front").GetComponent<MeshRenderer>();
|
||||||
|
|
||||||
// Now put together the textures into a 4x4 thing for the materials
|
// Now put together the textures into a 4x4 thing for the materials
|
||||||
var reelTexture = ImageUtilities.MakeReelTexture(textures);
|
var reelTexture = ImageUtilities.MakeReelTexture(mod, textures, key);
|
||||||
slidesBack.material.mainTexture = reelTexture;
|
slidesBack.material.mainTexture = reelTexture;
|
||||||
slidesBack.material.SetTexture(EmissionMap, reelTexture);
|
slidesBack.material.SetTexture(EmissionMap, reelTexture);
|
||||||
slidesBack.material.name = reelTexture.name;
|
slidesBack.material.name = reelTexture.name;
|
||||||
@ -174,8 +215,11 @@ namespace NewHorizons.Builder.Props
|
|||||||
slidesFront.material.name = reelTexture.name;
|
slidesFront.material.name = reelTexture.name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
);
|
NHLogger.LogVerbose($"Slide reel make reel texture {(DateTime.Now - time).TotalMilliseconds}ms");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Else when you put them down you can't pick them back up
|
// Else when you put them down you can't pick them back up
|
||||||
slideReelObj.GetComponent<OWCollider>()._physicsRemoved = false;
|
slideReelObj.GetComponent<OWCollider>()._physicsRemoved = false;
|
||||||
@ -196,58 +240,58 @@ namespace NewHorizons.Builder.Props
|
|||||||
switch (model)
|
switch (model)
|
||||||
{
|
{
|
||||||
case ProjectionInfo.SlideReelType.SixSlides:
|
case ProjectionInfo.SlideReelType.SixSlides:
|
||||||
{
|
|
||||||
switch (condition)
|
|
||||||
{
|
{
|
||||||
case ProjectionInfo.SlideReelCondition.Antique:
|
switch (condition)
|
||||||
default:
|
{
|
||||||
return SlideReel6Prefab;
|
case ProjectionInfo.SlideReelCondition.Antique:
|
||||||
case ProjectionInfo.SlideReelCondition.Pristine:
|
default:
|
||||||
return SlideReel6PristinePrefab;
|
return SlideReel6Prefab;
|
||||||
case ProjectionInfo.SlideReelCondition.Rusted:
|
case ProjectionInfo.SlideReelCondition.Pristine:
|
||||||
return SlideReel6RustedPrefab;
|
return SlideReel6PristinePrefab;
|
||||||
|
case ProjectionInfo.SlideReelCondition.Rusted:
|
||||||
|
return SlideReel6RustedPrefab;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
case ProjectionInfo.SlideReelType.SevenSlides:
|
case ProjectionInfo.SlideReelType.SevenSlides:
|
||||||
default:
|
default:
|
||||||
{
|
|
||||||
switch (condition)
|
|
||||||
{
|
{
|
||||||
case ProjectionInfo.SlideReelCondition.Antique:
|
switch (condition)
|
||||||
default:
|
{
|
||||||
return SlideReel7Prefab;
|
case ProjectionInfo.SlideReelCondition.Antique:
|
||||||
case ProjectionInfo.SlideReelCondition.Pristine:
|
default:
|
||||||
return SlideReel7PristinePrefab;
|
return SlideReel7Prefab;
|
||||||
case ProjectionInfo.SlideReelCondition.Rusted:
|
case ProjectionInfo.SlideReelCondition.Pristine:
|
||||||
return SlideReel7RustedPrefab;
|
return SlideReel7PristinePrefab;
|
||||||
|
case ProjectionInfo.SlideReelCondition.Rusted:
|
||||||
|
return SlideReel7RustedPrefab;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
case ProjectionInfo.SlideReelType.EightSlides:
|
case ProjectionInfo.SlideReelType.EightSlides:
|
||||||
{
|
|
||||||
switch (condition)
|
|
||||||
{
|
{
|
||||||
case ProjectionInfo.SlideReelCondition.Antique:
|
switch (condition)
|
||||||
default:
|
{
|
||||||
return SlideReel8Prefab;
|
case ProjectionInfo.SlideReelCondition.Antique:
|
||||||
case ProjectionInfo.SlideReelCondition.Pristine:
|
default:
|
||||||
return SlideReel8PristinePrefab;
|
return SlideReel8Prefab;
|
||||||
case ProjectionInfo.SlideReelCondition.Rusted:
|
case ProjectionInfo.SlideReelCondition.Pristine:
|
||||||
return SlideReel8RustedPrefab;
|
return SlideReel8PristinePrefab;
|
||||||
|
case ProjectionInfo.SlideReelCondition.Rusted:
|
||||||
|
return SlideReel8RustedPrefab;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
case ProjectionInfo.SlideReelType.Whole:
|
case ProjectionInfo.SlideReelType.Whole:
|
||||||
{
|
|
||||||
switch (condition)
|
|
||||||
{
|
{
|
||||||
case ProjectionInfo.SlideReelCondition.Antique:
|
switch (condition)
|
||||||
default:
|
{
|
||||||
return SlideReelWholePrefab;
|
case ProjectionInfo.SlideReelCondition.Antique:
|
||||||
case ProjectionInfo.SlideReelCondition.Pristine:
|
default:
|
||||||
return SlideReelWholePristinePrefab;
|
return SlideReelWholePrefab;
|
||||||
case ProjectionInfo.SlideReelCondition.Rusted:
|
case ProjectionInfo.SlideReelCondition.Pristine:
|
||||||
return SlideReelWholeRustedPrefab;
|
return SlideReelWholePristinePrefab;
|
||||||
|
case ProjectionInfo.SlideReelCondition.Rusted:
|
||||||
|
return SlideReelWholeRustedPrefab;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,8 +344,25 @@ 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 (invImageLoader, _, imageLoader) = StartAsyncLoader(mod, info.slides, ref slideCollection, true, false);
|
||||||
imageLoader.imageLoadedEvent.AddListener((Texture2D tex, int index) => { slideCollection.slides[index]._image = ImageUtilities.Invert(tex); });
|
if (invImageLoader != null)
|
||||||
|
{
|
||||||
|
// Loaded directly from cache
|
||||||
|
invImageLoader.imageLoadedEvent.AddListener((Texture2D tex, int index, string originalPath) =>
|
||||||
|
{
|
||||||
|
slideCollection.slides[index]._image = tex;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Create the inverted cache from existing images
|
||||||
|
imageLoader.imageLoadedEvent.AddListener((Texture2D tex, int index, string originalPath) =>
|
||||||
|
{
|
||||||
|
var time = DateTime.Now;
|
||||||
|
slideCollection.slides[index]._image = ImageUtilities.InvertSlideReel(mod, tex, originalPath);
|
||||||
|
NHLogger.LogVerbose($"Slide reel invert time {(DateTime.Now - time).TotalMilliseconds}ms");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
slideCollectionContainer.slideCollection = slideCollection;
|
slideCollectionContainer.slideCollection = slideCollection;
|
||||||
|
|
||||||
@ -339,8 +400,13 @@ 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, false, false);
|
||||||
imageLoader.imageLoadedEvent.AddListener((Texture2D tex, int index) => { slideCollection.slides[index]._image = tex; });
|
imageLoader.imageLoadedEvent.AddListener((Texture2D tex, int index, string originalPath) =>
|
||||||
|
{
|
||||||
|
var time = DateTime.Now;
|
||||||
|
slideCollection.slides[index]._image = tex;
|
||||||
|
NHLogger.LogVerbose($"Slide reel set time {(DateTime.Now - time).TotalMilliseconds}ms");
|
||||||
|
});
|
||||||
|
|
||||||
// attach a component to store all the data for the slides that play when a vision torch scans this target
|
// attach a component to store all the data for the slides that play when a vision torch scans this target
|
||||||
var target = g.AddComponent<VisionTorchTarget>();
|
var target = g.AddComponent<VisionTorchTarget>();
|
||||||
@ -381,13 +447,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, false, false);
|
||||||
|
|
||||||
// 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
|
||||||
@ -395,15 +461,18 @@ namespace NewHorizons.Builder.Props
|
|||||||
// to avoid doing a "is every element in the array `slideCollection.slides` not null" check every time a texture finishes loading
|
// to avoid doing a "is every element in the array `slideCollection.slides` not null" check every time a texture finishes loading
|
||||||
int displaySlidesLoaded = 0;
|
int displaySlidesLoaded = 0;
|
||||||
imageLoader.imageLoadedEvent.AddListener(
|
imageLoader.imageLoadedEvent.AddListener(
|
||||||
(Texture2D tex, int index) =>
|
(Texture2D tex, int index, string originalPath) =>
|
||||||
{
|
{
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
NHLogger.LogVerbose($"Slide reel another set time {(DateTime.Now - time).TotalMilliseconds}ms");
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -427,9 +496,25 @@ namespace NewHorizons.Builder.Props
|
|||||||
return standingTorch;
|
return standingTorch;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ImageUtilities.AsyncImageLoader AddAsyncLoader(GameObject gameObject, IModBehaviour mod, SlideInfo[] slides, ref SlideCollection slideCollection)
|
private static (SlideReelAsyncImageLoader inverted, SlideReelAsyncImageLoader atlas, SlideReelAsyncImageLoader slides)
|
||||||
|
StartAsyncLoader(IModBehaviour mod, SlideInfo[] slides, ref SlideCollection slideCollection, bool useInvertedCache, bool useAtlasCache)
|
||||||
{
|
{
|
||||||
var imageLoader = gameObject.AddComponent<ImageUtilities.AsyncImageLoader>();
|
var invertedImageLoader = new SlideReelAsyncImageLoader();
|
||||||
|
var atlasImageLoader = new SlideReelAsyncImageLoader();
|
||||||
|
var imageLoader = new SlideReelAsyncImageLoader();
|
||||||
|
|
||||||
|
var atlasKey = GetUniqueSlideReelID(mod, slides);
|
||||||
|
|
||||||
|
var cacheExists = Directory.Exists(Path.Combine(mod.ModHelper.Manifest.ModFolderPath, ATLAS_SLIDE_CACHE_FOLDER));
|
||||||
|
|
||||||
|
NHLogger.Log($"Does cache exist for slide reels? {cacheExists}");
|
||||||
|
|
||||||
|
if (useAtlasCache && cacheExists)
|
||||||
|
{
|
||||||
|
// Load the atlas texture used to draw onto the physical slide reel object
|
||||||
|
atlasImageLoader.PathsToLoad.Add((0, Path.Combine(mod.ModHelper.Manifest.ModFolderPath, ATLAS_SLIDE_CACHE_FOLDER, $"{atlasKey}.png")));
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < slides.Length; i++)
|
for (int i = 0; i < slides.Length; i++)
|
||||||
{
|
{
|
||||||
var slide = new Slide();
|
var slide = new Slide();
|
||||||
@ -438,10 +523,15 @@ namespace NewHorizons.Builder.Props
|
|||||||
|
|
||||||
if (string.IsNullOrEmpty(slideInfo.imagePath))
|
if (string.IsNullOrEmpty(slideInfo.imagePath))
|
||||||
{
|
{
|
||||||
imageLoader.imageLoadedEvent?.Invoke(Texture2D.blackTexture, i);
|
imageLoader.imageLoadedEvent?.Invoke(Texture2D.blackTexture, i, null);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (useInvertedCache && cacheExists)
|
||||||
|
{
|
||||||
|
// Load the inverted images used when displaying slide reels to a screen
|
||||||
|
invertedImageLoader.PathsToLoad.Add((i, Path.Combine(mod.ModHelper.Manifest.ModFolderPath, INVERTED_SLIDE_CACHE_FOLDER, slideInfo.imagePath)));
|
||||||
|
}
|
||||||
imageLoader.PathsToLoad.Add((i, Path.Combine(mod.ModHelper.Manifest.ModFolderPath, slideInfo.imagePath)));
|
imageLoader.PathsToLoad.Add((i, Path.Combine(mod.ModHelper.Manifest.ModFolderPath, slideInfo.imagePath)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -450,7 +540,30 @@ namespace NewHorizons.Builder.Props
|
|||||||
slideCollection.slides[i] = slide;
|
slideCollection.slides[i] = slide;
|
||||||
}
|
}
|
||||||
|
|
||||||
return imageLoader;
|
if (cacheExists)
|
||||||
|
{
|
||||||
|
// This code will execute in order to create the cache
|
||||||
|
// Loaders go sequentually - Load the inverted textures to the cache so that ImageUtilities will reuse them later
|
||||||
|
if (useInvertedCache)
|
||||||
|
{
|
||||||
|
invertedImageLoader.Start(true);
|
||||||
|
}
|
||||||
|
// Atlas texture next so that the normal iamgeLoader knows not to regenerate them unless they were missing
|
||||||
|
if (useAtlasCache)
|
||||||
|
{
|
||||||
|
atlasImageLoader.Start(false);
|
||||||
|
}
|
||||||
|
imageLoader.Start(true);
|
||||||
|
|
||||||
|
return (invertedImageLoader, atlasImageLoader, imageLoader);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Will be slow and create the cache if needed
|
||||||
|
imageLoader.Start(true);
|
||||||
|
|
||||||
|
return (null, null, imageLoader);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AddModules(SlideInfo slideInfo, ref Slide slide, IModBehaviour mod)
|
private static void AddModules(SlideInfo slideInfo, ref Slide slide, IModBehaviour mod)
|
||||||
|
|||||||
@ -471,7 +471,7 @@ namespace NewHorizons.Builder.Props.TranslatorText
|
|||||||
|
|
||||||
if (info.arcInfo != null && info.arcInfo.Count() != dict.Values.Count())
|
if (info.arcInfo != null && info.arcInfo.Count() != dict.Values.Count())
|
||||||
{
|
{
|
||||||
NHLogger.LogError($"Can't make NomaiWallText, arcInfo length [{info.arcInfo.Count()}] doesn't equal text entries [{dict.Values.Count()}]");
|
NHLogger.LogError($"Can't make NomaiWallText, arcInfo length [{info.arcInfo.Count()}] doesn't equal number of TextBlocks [{dict.Values.Count()}] in the xml");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -22,6 +22,16 @@ namespace NewHorizons.Components.Quantum
|
|||||||
private OWRigidbody _rb;
|
private OWRigidbody _rb;
|
||||||
private OrbitLine _orbitLine;
|
private OrbitLine _orbitLine;
|
||||||
|
|
||||||
|
public NHAstroObject astroObject
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_astroObject == null)
|
||||||
|
_astroObject = GetComponent<NHAstroObject>();
|
||||||
|
return _astroObject;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public int CurrentIndex { get; private set; }
|
public int CurrentIndex { get; private set; }
|
||||||
|
|
||||||
public override void Awake()
|
public override void Awake()
|
||||||
@ -97,7 +107,7 @@ namespace NewHorizons.Components.Quantum
|
|||||||
|
|
||||||
primaryBody = AstroObjectLocator.GetAstroObject(newOrbit.primaryBody);
|
primaryBody = AstroObjectLocator.GetAstroObject(newOrbit.primaryBody);
|
||||||
var primaryGravity = new Gravity(primaryBody.GetGravityVolume());
|
var primaryGravity = new Gravity(primaryBody.GetGravityVolume());
|
||||||
var secondaryGravity = new Gravity(_astroObject.GetGravityVolume());
|
var secondaryGravity = new Gravity(astroObject.GetGravityVolume());
|
||||||
orbitalParams = newOrbit.GetOrbitalParameters(primaryGravity, secondaryGravity);
|
orbitalParams = newOrbit.GetOrbitalParameters(primaryGravity, secondaryGravity);
|
||||||
|
|
||||||
var pos = primaryBody.transform.position + orbitalParams.InitialPosition;
|
var pos = primaryBody.transform.position + orbitalParams.InitialPosition;
|
||||||
@ -139,15 +149,16 @@ namespace NewHorizons.Components.Quantum
|
|||||||
|
|
||||||
private void SetNewOrbit(AstroObject primaryBody, OrbitalParameters orbitalParameters)
|
private void SetNewOrbit(AstroObject primaryBody, OrbitalParameters orbitalParameters)
|
||||||
{
|
{
|
||||||
_astroObject._primaryBody = primaryBody;
|
astroObject._primaryBody = primaryBody;
|
||||||
DetectorBuilder.SetDetector(primaryBody, _astroObject, _detector);
|
DetectorBuilder.SetDetector(primaryBody, astroObject, _detector);
|
||||||
_detector._activeInheritedDetector = primaryBody.GetComponentInChildren<ForceDetector>();
|
_detector._activeInheritedDetector = primaryBody.GetComponentInChildren<ForceDetector>();
|
||||||
_detector._activeVolumes = new List<EffectVolume>() { primaryBody.GetGravityVolume() };
|
_detector._activeVolumes = new List<EffectVolume>() { primaryBody.GetGravityVolume() };
|
||||||
if (_alignment != null) _alignment.SetTargetBody(primaryBody.GetComponent<OWRigidbody>());
|
if (_alignment != null) _alignment.SetTargetBody(primaryBody.GetComponent<OWRigidbody>());
|
||||||
|
|
||||||
_astroObject.SetOrbitalParametersFromTrueAnomaly(orbitalParameters.eccentricity, orbitalParameters.semiMajorAxis, orbitalParameters.inclination, orbitalParameters.argumentOfPeriapsis, orbitalParameters.longitudeOfAscendingNode, orbitalParameters.trueAnomaly);
|
astroObject.SetOrbitalParametersFromTrueAnomaly(orbitalParameters.eccentricity, orbitalParameters.semiMajorAxis, orbitalParameters.inclination, orbitalParameters.argumentOfPeriapsis, orbitalParameters.longitudeOfAscendingNode, orbitalParameters.trueAnomaly);
|
||||||
|
|
||||||
PlanetCreationHandler.UpdatePosition(gameObject, orbitalParameters, primaryBody, _astroObject);
|
PlanetCreationHandler.UpdatePosition(gameObject, orbitalParameters, primaryBody, astroObject);
|
||||||
|
gameObject.transform.parent = null;
|
||||||
|
|
||||||
if (!Physics.autoSyncTransforms)
|
if (!Physics.autoSyncTransforms)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -137,30 +137,39 @@ namespace NewHorizons.Handlers
|
|||||||
|
|
||||||
private static IEnumerator SpawnCoroutine(int length)
|
private static IEnumerator SpawnCoroutine(int length)
|
||||||
{
|
{
|
||||||
|
FixPlayerVelocity();
|
||||||
for(int i = 0; i < length; i++)
|
for(int i = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
FixPlayerVelocity();
|
FixPlayerVelocity(false); // dont recenter universe here or else it spams and lags game
|
||||||
yield return new WaitForEndOfFrame();
|
yield return new WaitForEndOfFrame();
|
||||||
}
|
}
|
||||||
|
FixPlayerVelocity();
|
||||||
|
|
||||||
InvulnerabilityHandler.MakeInvulnerable(false);
|
InvulnerabilityHandler.MakeInvulnerable(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void FixPlayerVelocity()
|
private static void FixPlayerVelocity(bool recenter = true)
|
||||||
{
|
{
|
||||||
var playerBody = SearchUtilities.Find("Player_Body").GetAttachedOWRigidbody();
|
var playerBody = SearchUtilities.Find("Player_Body").GetAttachedOWRigidbody();
|
||||||
var resources = playerBody.GetComponent<PlayerResources>();
|
var resources = playerBody.GetComponent<PlayerResources>();
|
||||||
|
|
||||||
SpawnBody(playerBody, GetDefaultSpawn());
|
SpawnBody(playerBody, GetDefaultSpawn(), recenter: recenter);
|
||||||
|
|
||||||
resources._currentHealth = 100f;
|
resources._currentHealth = 100f;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SpawnBody(OWRigidbody body, SpawnPoint spawn, Vector3? positionOverride = null)
|
public static void SpawnBody(OWRigidbody body, SpawnPoint spawn, Vector3? positionOverride = null, bool recenter = true)
|
||||||
{
|
{
|
||||||
var pos = positionOverride ?? spawn.transform.position;
|
var pos = positionOverride ?? spawn.transform.position;
|
||||||
|
|
||||||
body.WarpToPositionRotation(pos, spawn.transform.rotation);
|
if (recenter)
|
||||||
|
{
|
||||||
|
body.WarpToPositionRotation(pos, spawn.transform.rotation);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
body.transform.SetPositionAndRotation(pos, spawn.transform.rotation);
|
||||||
|
}
|
||||||
|
|
||||||
var spawnVelocity = spawn._attachedBody.GetVelocity();
|
var spawnVelocity = spawn._attachedBody.GetVelocity();
|
||||||
var spawnAngularVelocity = spawn._attachedBody.GetPointTangentialVelocity(pos);
|
var spawnAngularVelocity = spawn._attachedBody.GetPointTangentialVelocity(pos);
|
||||||
|
|||||||
@ -1,14 +1,10 @@
|
|||||||
using HarmonyLib;
|
using NewHorizons.Builder.Props;
|
||||||
using NewHorizons.Utility.OWML;
|
using NewHorizons.Utility.OWML;
|
||||||
using OWML.Common;
|
using OWML.Common;
|
||||||
using System;
|
using System;
|
||||||
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.Networking;
|
|
||||||
|
|
||||||
namespace NewHorizons.Utility.Files
|
namespace NewHorizons.Utility.Files
|
||||||
{
|
{
|
||||||
@ -17,9 +13,10 @@ namespace NewHorizons.Utility.Files
|
|||||||
// key is path + applied effects
|
// key is path + applied effects
|
||||||
private static readonly Dictionary<string, Texture> _textureCache = new();
|
private static readonly Dictionary<string, Texture> _textureCache = new();
|
||||||
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.Add(key, texture);
|
public static void TrackCachedTexture(string key, Texture texture) => _textureCache[key] = texture;
|
||||||
|
|
||||||
private 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)
|
||||||
{
|
{
|
||||||
@ -99,7 +96,7 @@ namespace NewHorizons.Utility.Files
|
|||||||
/// used specifically for projected slides.
|
/// used specifically for projected slides.
|
||||||
/// also adds a border (to prevent weird visual bug) and makes the texture linear (otherwise the projected image is too bright).
|
/// also adds a border (to prevent weird visual bug) and makes the texture linear (otherwise the projected image is too bright).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static Texture2D Invert(Texture2D texture)
|
public static Texture2D InvertSlideReel(IModBehaviour mod, Texture2D texture, string originalPath)
|
||||||
{
|
{
|
||||||
var key = $"{texture.name} > invert";
|
var key = $"{texture.name} > invert";
|
||||||
if (_textureCache.TryGetValue(key, out var existingTexture)) return (Texture2D)existingTexture;
|
if (_textureCache.TryGetValue(key, out var existingTexture)) return (Texture2D)existingTexture;
|
||||||
@ -135,18 +132,27 @@ namespace NewHorizons.Utility.Files
|
|||||||
|
|
||||||
_textureCache.Add(key, newTexture);
|
_textureCache.Add(key, newTexture);
|
||||||
|
|
||||||
|
// Since doing this is expensive we cache the results to the disk
|
||||||
|
// Preloading cached values is done in ProjectionBuilder
|
||||||
|
if (!string.IsNullOrEmpty(originalPath))
|
||||||
|
{
|
||||||
|
var path = Path.Combine(mod.ModHelper.Manifest.ModFolderPath, ProjectionBuilder.INVERTED_SLIDE_CACHE_FOLDER, originalPath.Replace(mod.ModHelper.Manifest.ModFolderPath, ""));
|
||||||
|
NHLogger.LogVerbose($"Caching inverted image to {path}");
|
||||||
|
Directory.CreateDirectory(Path.GetDirectoryName(path));
|
||||||
|
File.WriteAllBytes(path, newTexture.EncodeToPNG());
|
||||||
|
}
|
||||||
|
|
||||||
return newTexture;
|
return newTexture;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Texture2D MakeReelTexture(Texture2D[] textures)
|
public static Texture2D MakeReelTexture(IModBehaviour mod, Texture2D[] textures, string uniqueSlideReelID)
|
||||||
{
|
{
|
||||||
var key = $"SlideReelAtlas of {textures.Join(x => x.name)}";
|
if (_textureCache.TryGetValue(uniqueSlideReelID, out var existingTexture)) return (Texture2D)existingTexture;
|
||||||
if (_textureCache.TryGetValue(key, out var existingTexture)) return (Texture2D)existingTexture;
|
|
||||||
|
|
||||||
var size = 256;
|
var size = 256;
|
||||||
|
|
||||||
var texture = new Texture2D(size * 4, size * 4, TextureFormat.ARGB32, false);
|
var texture = new Texture2D(size * 4, size * 4, TextureFormat.ARGB32, false);
|
||||||
texture.name = key;
|
texture.name = uniqueSlideReelID;
|
||||||
|
|
||||||
var 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++)
|
||||||
@ -188,7 +194,14 @@ namespace NewHorizons.Utility.Files
|
|||||||
texture.SetPixels(fillPixels);
|
texture.SetPixels(fillPixels);
|
||||||
texture.Apply();
|
texture.Apply();
|
||||||
|
|
||||||
_textureCache.Add(key, texture);
|
_textureCache.Add(uniqueSlideReelID, texture);
|
||||||
|
|
||||||
|
// Since doing this is expensive we cache the results to the disk
|
||||||
|
// Preloading cached values is done in ProjectionBuilder
|
||||||
|
var path = Path.Combine(mod.ModHelper.Manifest.ModFolderPath, ProjectionBuilder.ATLAS_SLIDE_CACHE_FOLDER, $"{uniqueSlideReelID}.png");
|
||||||
|
NHLogger.LogVerbose($"Caching atlas image to {path}");
|
||||||
|
Directory.CreateDirectory(Path.GetDirectoryName(path));
|
||||||
|
File.WriteAllBytes(path, texture.EncodeToPNG());
|
||||||
|
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
@ -429,96 +442,5 @@ namespace NewHorizons.Utility.Files
|
|||||||
sprite.name = texture.name;
|
sprite.name = texture.name;
|
||||||
return sprite;
|
return sprite;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Modified from https://stackoverflow.com/a/69141085/9643841
|
|
||||||
public class AsyncImageLoader : MonoBehaviour
|
|
||||||
{
|
|
||||||
public List<(int index, string path)> PathsToLoad { get; private set; } = new();
|
|
||||||
|
|
||||||
public class ImageLoadedEvent : UnityEvent<Texture2D, int> { }
|
|
||||||
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)
|
|
||||||
|
|
||||||
void Start()
|
|
||||||
{
|
|
||||||
imageLoadedEvent.AddListener(OnImageLoaded);
|
|
||||||
foreach (var (index, path) in PathsToLoad)
|
|
||||||
{
|
|
||||||
StartCoroutine(DownloadTexture(path, index));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnImageLoaded(Texture texture, int index)
|
|
||||||
{
|
|
||||||
lock (_lockObj)
|
|
||||||
{
|
|
||||||
_loadedCount++;
|
|
||||||
|
|
||||||
if (_loadedCount >= PathsToLoad.Count)
|
|
||||||
{
|
|
||||||
NHLogger.LogVerbose($"Finished loading all textures for {gameObject.name} (one was {PathsToLoad.FirstOrDefault()}");
|
|
||||||
FinishedLoading = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IEnumerator DownloadTexture(string url, int index)
|
|
||||||
{
|
|
||||||
var key = GetKey(url);
|
|
||||||
lock (_textureCache)
|
|
||||||
{
|
|
||||||
if (_textureCache.TryGetValue(key, out var existingTexture))
|
|
||||||
{
|
|
||||||
NHLogger.LogVerbose($"Already loaded image {index}:{url}");
|
|
||||||
imageLoadedEvent?.Invoke((Texture2D)existingTexture, index);
|
|
||||||
yield break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
using UnityWebRequest uwr = UnityWebRequestTexture.GetTexture(url);
|
|
||||||
|
|
||||||
yield return uwr.SendWebRequest();
|
|
||||||
|
|
||||||
var hasError = uwr.error != null && uwr.error != "";
|
|
||||||
|
|
||||||
if (hasError)
|
|
||||||
{
|
|
||||||
NHLogger.LogError($"Failed to load {index}:{url} - {uwr.error}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var texture = new Texture2D(2, 2, TextureFormat.RGBA32, false);
|
|
||||||
texture.name = key;
|
|
||||||
texture.wrapMode = TextureWrapMode.Clamp;
|
|
||||||
|
|
||||||
var handler = (DownloadHandlerTexture)uwr.downloadHandler;
|
|
||||||
texture.LoadImage(handler.data);
|
|
||||||
|
|
||||||
lock (_textureCache)
|
|
||||||
{
|
|
||||||
if (_textureCache.TryGetValue(key, out var existingTexture))
|
|
||||||
{
|
|
||||||
NHLogger.LogVerbose($"Already loaded image {index}:{url}");
|
|
||||||
Destroy(texture);
|
|
||||||
texture = (Texture2D)existingTexture;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_textureCache.Add(key, texture);
|
|
||||||
}
|
|
||||||
|
|
||||||
imageLoadedEvent?.Invoke(texture, index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
139
NewHorizons/Utility/Files/SlideReelAsyncImageLoader.cs
Normal file
139
NewHorizons/Utility/Files/SlideReelAsyncImageLoader.cs
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
using NewHorizons.Utility.OWML;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.Events;
|
||||||
|
using UnityEngine.Networking;
|
||||||
|
using UnityEngine.SceneManagement;
|
||||||
|
|
||||||
|
namespace NewHorizons.Utility.Files;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Modified from https://stackoverflow.com/a/69141085/9643841
|
||||||
|
/// </summary>
|
||||||
|
public class SlideReelAsyncImageLoader
|
||||||
|
{
|
||||||
|
public List<(int index, string path)> PathsToLoad { get; private set; } = new();
|
||||||
|
|
||||||
|
public class ImageLoadedEvent : UnityEvent<Texture2D, int, string> { }
|
||||||
|
public ImageLoadedEvent imageLoadedEvent = 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;
|
||||||
|
|
||||||
|
public void Start(bool clamp)
|
||||||
|
{
|
||||||
|
if (_started) return;
|
||||||
|
|
||||||
|
_clamp = clamp;
|
||||||
|
|
||||||
|
_started = true;
|
||||||
|
|
||||||
|
if (SingletonSlideReelAsyncImageLoader.Instance == null)
|
||||||
|
{
|
||||||
|
Main.Instance.gameObject.AddComponent<SingletonSlideReelAsyncImageLoader>();
|
||||||
|
}
|
||||||
|
|
||||||
|
NHLogger.LogVerbose("Loading new slide reel");
|
||||||
|
imageLoadedEvent.AddListener(OnImageLoaded);
|
||||||
|
SingletonSlideReelAsyncImageLoader.Instance.Load(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnImageLoaded(Texture texture, int index, string originalPath)
|
||||||
|
{
|
||||||
|
_loadedCount++;
|
||||||
|
|
||||||
|
if (_loadedCount >= PathsToLoad.Count)
|
||||||
|
{
|
||||||
|
NHLogger.LogVerbose($"Finished loading all textures for a slide reel (one was {PathsToLoad.FirstOrDefault()}");
|
||||||
|
FinishedLoading = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerator DownloadTexture(string url, int index)
|
||||||
|
{
|
||||||
|
var key = ImageUtilities.GetKey(url);
|
||||||
|
if (ImageUtilities.CheckCachedTexture(key, out var existingTexture))
|
||||||
|
{
|
||||||
|
NHLogger.LogVerbose($"Already loaded image {index}:{url} with key {key}");
|
||||||
|
imageLoadedEvent?.Invoke((Texture2D)existingTexture, index, url);
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
|
using UnityWebRequest uwr = UnityWebRequestTexture.GetTexture(url);
|
||||||
|
|
||||||
|
yield return uwr.SendWebRequest();
|
||||||
|
|
||||||
|
var hasError = uwr.error != null && uwr.error != "";
|
||||||
|
|
||||||
|
if (hasError)
|
||||||
|
{
|
||||||
|
NHLogger.LogError($"Failed to load {index}:{url} - {uwr.error}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var texture = DownloadHandlerTexture.GetContent(uwr);
|
||||||
|
texture.name = key;
|
||||||
|
if (_clamp)
|
||||||
|
{
|
||||||
|
texture.wrapMode = TextureWrapMode.Clamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ImageUtilities.TrackCachedTexture(key, texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
var time = DateTime.Now;
|
||||||
|
imageLoadedEvent?.Invoke(texture, index, url);
|
||||||
|
NHLogger.LogVerbose($"Slide reel event took: {(DateTime.Now - time).TotalMilliseconds}ms");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class SingletonSlideReelAsyncImageLoader : MonoBehaviour
|
||||||
|
{
|
||||||
|
public static SingletonSlideReelAsyncImageLoader Instance { get; private set; }
|
||||||
|
|
||||||
|
public void Awake()
|
||||||
|
{
|
||||||
|
Instance = this;
|
||||||
|
SceneManager.sceneUnloaded += OnSceneUnloaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSceneUnloaded(Scene _)
|
||||||
|
{
|
||||||
|
StopAllCoroutines();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Load(SlideReelAsyncImageLoader loader)
|
||||||
|
{
|
||||||
|
// Delay at least one frame to let things subscribe to the event before it fires
|
||||||
|
Delay.FireOnNextUpdate(() =>
|
||||||
|
{
|
||||||
|
foreach (var (index, path) in loader.PathsToLoad)
|
||||||
|
{
|
||||||
|
NHLogger.LogVerbose($"Loaded slide reel {index} of {loader.PathsToLoad.Count}");
|
||||||
|
|
||||||
|
StartCoroutine(loader.DownloadTexture(path, index));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,7 +4,7 @@
|
|||||||
"author": "xen, Bwc9876, JohnCorby, MegaPiggy, Clay, Trifid, and friends",
|
"author": "xen, Bwc9876, JohnCorby, MegaPiggy, Clay, Trifid, and friends",
|
||||||
"name": "New Horizons",
|
"name": "New Horizons",
|
||||||
"uniqueName": "xen.NewHorizons",
|
"uniqueName": "xen.NewHorizons",
|
||||||
"version": "1.21.2",
|
"version": "1.21.3",
|
||||||
"owmlVersion": "2.12.1",
|
"owmlVersion": "2.12.1",
|
||||||
"dependencies": [ "JohnCorby.VanillaFix", "xen.CommonCameraUtility", "dgarro.CustomShipLogModes" ],
|
"dependencies": [ "JohnCorby.VanillaFix", "xen.CommonCameraUtility", "dgarro.CustomShipLogModes" ],
|
||||||
"conflicts": [ "PacificEngine.OW_CommonResources" ],
|
"conflicts": [ "PacificEngine.OW_CommonResources" ],
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user