mirror of
https://github.com/Ellpeck/MLEM.git
synced 2024-11-25 14:08:34 +01:00
Construct images in UiParser.ParseImage on the main thread to support usage with KNI
This commit is contained in:
parent
73a02dfe19
commit
a6a34c3937
2 changed files with 42 additions and 27 deletions
|
@ -17,7 +17,9 @@ Jump to version:
|
||||||
|
|
||||||
## 7.1.1 (In Development)
|
## 7.1.1 (In Development)
|
||||||
|
|
||||||
No code changes
|
### MLEM.Ui
|
||||||
|
Improvements
|
||||||
|
- Construct images in UiParser.ParseImage on the main thread to support usage with KNI
|
||||||
|
|
||||||
## 7.1.0
|
## 7.1.0
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,6 @@ using MLEM.Ui.Style;
|
||||||
|
|
||||||
#if NETSTANDARD2_0_OR_GREATER || NET6_0_OR_GREATER
|
#if NETSTANDARD2_0_OR_GREATER || NET6_0_OR_GREATER
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
using System.Net;
|
using System.Net;
|
||||||
#endif
|
#endif
|
||||||
|
@ -139,43 +138,59 @@ namespace MLEM.Ui.Parsers {
|
||||||
/// This method invokes an asynchronouns action, meaning the <see cref="Image"/>'s <see cref="Image.Texture"/> will likely not have loaded in when this method returns.
|
/// This method invokes an asynchronouns action, meaning the <see cref="Image"/>'s <see cref="Image.Texture"/> will likely not have loaded in when this method returns.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="path">The absolute, relative or web path to the image.</param>
|
/// <param name="path">The absolute, relative or web path to the image.</param>
|
||||||
/// <param name="onImageFetched">An action that is invoked with the loaded image once it is fetched. Note that this action will be invoked asynchronously.</param>
|
/// <param name="onImageFetched">An action that is invoked with the loaded image once it is fetched. Note that this action will be invoked synchronously.</param>
|
||||||
/// <returns>The loaded image.</returns>
|
/// <returns>The loaded image.</returns>
|
||||||
/// <exception cref="NullReferenceException">Thrown if <see cref="GraphicsDevice"/> is null, or if there is an <see cref="Exception"/> loading the image and <see cref="ImageExceptionHandler"/> is unset.</exception>
|
/// <exception cref="NullReferenceException">Thrown if <see cref="GraphicsDevice"/> is null, or if there is an <see cref="Exception"/> loading the image and <see cref="ImageExceptionHandler"/> is unset.</exception>
|
||||||
protected Image ParseImage(string path, Action<TextureRegion> onImageFetched = null) {
|
protected Image ParseImage(string path, Action<TextureRegion> onImageFetched = null) {
|
||||||
if (this.GraphicsDevice == null)
|
if (this.GraphicsDevice == null)
|
||||||
throw new NullReferenceException("A UI parser requires a GraphicsDevice for parsing images");
|
throw new NullReferenceException("A UI parser requires a GraphicsDevice for parsing images");
|
||||||
|
|
||||||
var imageLock = new object();
|
var bytesLock = new object();
|
||||||
|
byte[] bytes = null;
|
||||||
TextureRegion image = null;
|
TextureRegion image = null;
|
||||||
return new Image(Anchor.AutoLeft, Vector2.One, _ => {
|
return new Image(Anchor.AutoLeft, Vector2.One, _ => {
|
||||||
lock (imageLock)
|
if (image == null) {
|
||||||
return image;
|
bool bytesNull;
|
||||||
|
lock (bytesLock)
|
||||||
|
bytesNull = bytes == null;
|
||||||
|
if (!bytesNull) {
|
||||||
|
Texture2D tex;
|
||||||
|
lock (bytesLock) {
|
||||||
|
using (var stream = new MemoryStream(bytes))
|
||||||
|
tex = Texture2D.FromStream(this.GraphicsDevice, stream);
|
||||||
|
bytes = null;
|
||||||
|
}
|
||||||
|
image = new TextureRegion(tex);
|
||||||
|
onImageFetched?.Invoke(image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return image;
|
||||||
}) {
|
}) {
|
||||||
SetHeightBasedOnAspect = true,
|
SetHeightBasedOnAspect = true,
|
||||||
OnAddedToUi = e => {
|
OnAddedToUi = e => {
|
||||||
bool imageNull;
|
if (image == null) {
|
||||||
lock (imageLock)
|
bool bytesNull;
|
||||||
imageNull = image == null;
|
lock (bytesLock)
|
||||||
if (imageNull)
|
bytesNull = bytes == null;
|
||||||
LoadImageAsync();
|
if (bytesNull)
|
||||||
|
LoadImageStream();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
OnRemovedFromUi = e => {
|
OnRemovedFromUi = e => {
|
||||||
lock (imageLock) {
|
lock (bytesLock)
|
||||||
image?.Texture.Dispose();
|
bytes = null;
|
||||||
image = null;
|
image?.Texture.Dispose();
|
||||||
}
|
image = null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
async void LoadImageAsync() {
|
async void LoadImageStream() {
|
||||||
// only apply the base path for relative files
|
// only apply the base path for relative files
|
||||||
if (this.ImageBasePath != null && !path.StartsWith("http") && !Path.IsPathRooted(path))
|
if (this.ImageBasePath != null && !path.StartsWith("http") && !Path.IsPathRooted(path))
|
||||||
path = $"{this.ImageBasePath}/{path}";
|
path = $"{this.ImageBasePath}/{path}";
|
||||||
try {
|
try {
|
||||||
Texture2D tex;
|
byte[] src;
|
||||||
if (path.StartsWith("http")) {
|
if (path.StartsWith("http")) {
|
||||||
byte[] src;
|
|
||||||
#if NETSTANDARD2_0_OR_GREATER || NET6_0_OR_GREATER
|
#if NETSTANDARD2_0_OR_GREATER || NET6_0_OR_GREATER
|
||||||
using (var client = new HttpClient())
|
using (var client = new HttpClient())
|
||||||
src = await client.GetByteArrayAsync(path);
|
src = await client.GetByteArrayAsync(path);
|
||||||
|
@ -183,18 +198,16 @@ namespace MLEM.Ui.Parsers {
|
||||||
using (var client = new WebClient())
|
using (var client = new WebClient())
|
||||||
src = await client.DownloadDataTaskAsync(path);
|
src = await client.DownloadDataTaskAsync(path);
|
||||||
#endif
|
#endif
|
||||||
using (var memory = new MemoryStream(src))
|
|
||||||
tex = Texture2D.FromStream(this.GraphicsDevice, memory);
|
|
||||||
} else {
|
} else {
|
||||||
using (var stream = Path.IsPathRooted(path) ? File.OpenRead(path) : TitleContainer.OpenStream(path))
|
using (var fileStream = Path.IsPathRooted(path) ? File.OpenRead(path) : TitleContainer.OpenStream(path)) {
|
||||||
tex = Texture2D.FromStream(this.GraphicsDevice, stream);
|
using (var memStream = new MemoryStream()) {
|
||||||
}
|
await fileStream.CopyToAsync(memStream);
|
||||||
lock (imageLock) {
|
src = memStream.ToArray();
|
||||||
if (image == null) {
|
}
|
||||||
image = new TextureRegion(tex);
|
|
||||||
onImageFetched?.Invoke(image);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
lock (bytesLock)
|
||||||
|
bytes = src;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (this.ImageExceptionHandler != null) {
|
if (this.ImageExceptionHandler != null) {
|
||||||
this.ImageExceptionHandler.Invoke(path, e);
|
this.ImageExceptionHandler.Invoke(path, e);
|
||||||
|
|
Loading…
Reference in a new issue