diff --git a/OpenAI/Packages/com.openai.unity/Runtime/Extensions/TextureExtensions.cs b/OpenAI/Packages/com.openai.unity/Runtime/Extensions/TextureExtensions.cs
index 6ccbf2b8..2657c377 100644
--- a/OpenAI/Packages/com.openai.unity/Runtime/Extensions/TextureExtensions.cs
+++ b/OpenAI/Packages/com.openai.unity/Runtime/Extensions/TextureExtensions.cs
@@ -1,27 +1,39 @@
// Licensed under the MIT License. See LICENSE in the project root for license information.
-using System;
-using System.IO;
using System.Threading;
using System.Threading.Tasks;
+using Unity.Collections;
using UnityEngine;
+using Utilities.Extensions;
+using OpenAI.Images;
+using Utilities.Async;
+using System;
+
+#if !PLATFORM_WEBGL
+using System.IO;
using Utilities.WebRequestRest;
+#endif
namespace OpenAI.Extensions
{
- internal static class TextureExtensions
+ public static class TextureExtensions
{
- public static async Task<(Texture2D, string)> ConvertFromBase64Async(string b64, bool debug, CancellationToken cancellationToken)
+ internal static async Task<(Texture2D, string)> ConvertFromBase64Async(string b64, bool debug, CancellationToken cancellationToken)
{
- var imageData = Convert.FromBase64String(b64);
+ using var imageData = NativeArrayExtensions.FromBase64String(b64, Allocator.Persistent);
#if PLATFORM_WEBGL
var texture = new Texture2D(2, 2);
+#if UNITY_6000_0_OR_NEWER
texture.LoadImage(imageData);
+#else
+ texture.LoadImage(imageData.ToArray());
+#endif
return await Task.FromResult((texture, string.Empty));
#else
if (!Rest.TryGetDownloadCacheItem(b64, out var localFilePath))
{
- await File.WriteAllBytesAsync(localFilePath, imageData, cancellationToken).ConfigureAwait(true);
+ await using var fs = new FileStream(localFilePath, FileMode.Create, FileAccess.Write);
+ await fs.WriteAsync(imageData, cancellationToken: cancellationToken);
localFilePath = $"file://{localFilePath}";
}
@@ -30,5 +42,54 @@ internal static class TextureExtensions
return (texture, cachedPath);
#endif
}
+
+ ///
+ /// Loads a Texture2D from an ImageResult, handling base64, cached path, or URL.
+ ///
+ /// The to load the texture for.
+ /// Optional, debug flag.
+ /// Optional, .
+ ///
+ /// A tuple containing the converted and the cached file path as a string.
+ ///
+ public static async Task<(Texture2D, Uri)> LoadTextureAsync(this ImageResult imageResult, bool debug = false, CancellationToken cancellationToken = default)
+ {
+ await Awaiters.UnityMainThread;
+
+ if (imageResult.Texture.IsNull())
+ {
+ if (!string.IsNullOrWhiteSpace(imageResult.B64_Json))
+ {
+ var (texture, cachedPath) = await ConvertFromBase64Async(imageResult.B64_Json, debug, cancellationToken);
+ imageResult.Texture = texture;
+ imageResult.CachedPathUri = new Uri(cachedPath);
+ }
+ else
+ {
+ Texture2D texture;
+ Uri cachedPath;
+
+ if (imageResult.CachedPathUri != null)
+ {
+ texture = await Rest.DownloadTextureAsync(imageResult.CachedPathUri, parameters: new RestParameters(debug: debug), cancellationToken: cancellationToken);
+ cachedPath = imageResult.CachedPathUri;
+ }
+ else if (!string.IsNullOrWhiteSpace(imageResult.Url))
+ {
+ texture = await Rest.DownloadTextureAsync(imageResult.Url, parameters: new RestParameters(debug: debug), cancellationToken: cancellationToken);
+ cachedPath = Rest.TryGetDownloadCacheItem(imageResult.Url, out var path) ? new Uri(path) : null;
+ }
+ else
+ {
+ throw new System.Exception("ImageResult does not contain valid image data.");
+ }
+
+ imageResult.Texture = texture;
+ imageResult.CachedPathUri = cachedPath;
+ }
+ }
+
+ return (imageResult.Texture, imageResult.CachedPathUri);
+ }
}
}
diff --git a/OpenAI/Packages/com.openai.unity/Runtime/Images/ImageResult.cs b/OpenAI/Packages/com.openai.unity/Runtime/Images/ImageResult.cs
index 255df3cd..3a3395cd 100644
--- a/OpenAI/Packages/com.openai.unity/Runtime/Images/ImageResult.cs
+++ b/OpenAI/Packages/com.openai.unity/Runtime/Images/ImageResult.cs
@@ -56,7 +56,12 @@ internal ImageResult(
[Preserve]
[JsonIgnore]
- public string CachedPath { get; internal set; }
+ [Obsolete("use CachedPathUri")]
+ public string CachedPath => CachedPathUri?.ToString();
+
+ [Preserve]
+ [JsonIgnore]
+ public Uri CachedPathUri { get; internal set; }
[Preserve]
[JsonIgnore]
@@ -75,9 +80,9 @@ internal ImageResult(
[Preserve]
public override string ToString()
{
- if (!string.IsNullOrWhiteSpace(CachedPath))
+ if (CachedPathUri != null)
{
- return CachedPath;
+ return CachedPathUri.ToString();
}
if (!string.IsNullOrWhiteSpace(B64_Json))
diff --git a/OpenAI/Packages/com.openai.unity/Runtime/Images/ImagesEndpoint.cs b/OpenAI/Packages/com.openai.unity/Runtime/Images/ImagesEndpoint.cs
index 156b459a..1ffa6645 100644
--- a/OpenAI/Packages/com.openai.unity/Runtime/Images/ImagesEndpoint.cs
+++ b/OpenAI/Packages/com.openai.unity/Runtime/Images/ImagesEndpoint.cs
@@ -9,7 +9,6 @@
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
-using Utilities.Async;
using Utilities.WebRequestRest;
namespace OpenAI.Images
@@ -180,33 +179,15 @@ private async Task> DeserializeResponseAsync(Response
}
await Rest.ValidateCacheDirectoryAsync();
- var downloads = imagesResponse.Results.Select(DownloadAsync).ToList();
- async Task DownloadAsync(ImageResult result)
- {
- await Awaiters.UnityMainThread;
-
- if (string.IsNullOrWhiteSpace(result.Url))
- {
- var (texture, cachePath) = await TextureExtensions.ConvertFromBase64Async(result.B64_Json, EnableDebug, cancellationToken);
- result.Texture = texture;
- result.CachedPath = cachePath;
- }
- else
- {
- result.Texture = await Rest.DownloadTextureAsync(result.Url, parameters: new RestParameters(debug: EnableDebug), cancellationToken: cancellationToken);
-
- if (Rest.TryGetDownloadCacheItem(result.Url, out var cachedPath))
- {
- result.CachedPath = cachedPath;
- }
- }
- }
+ Task<(Texture2D, Uri)> DownloadAsync(ImageResult result)
+ => result.LoadTextureAsync(debug: EnableDebug, cancellationToken);
- await Task.WhenAll(downloads).ConfigureAwait(true);
+ await Task.WhenAll(imagesResponse.Results.Select(DownloadAsync).ToList()).ConfigureAwait(true);
- foreach (var result in imagesResponse.Results)
+ for (var i = 0; i < imagesResponse.Results.Count; i++)
{
+ var result = imagesResponse.Results[i];
result.CreatedAt = DateTimeOffset.FromUnixTimeSeconds(imagesResponse.CreatedAtUnixSeconds).UtcDateTime;
result.Background = imagesResponse.Background;
result.OutputFormat = imagesResponse.OutputFormat;
diff --git a/OpenAI/Packages/com.openai.unity/Runtime/Responses/Message.cs b/OpenAI/Packages/com.openai.unity/Runtime/Responses/Message.cs
index 19870a4d..1c5e8b3b 100644
--- a/OpenAI/Packages/com.openai.unity/Runtime/Responses/Message.cs
+++ b/OpenAI/Packages/com.openai.unity/Runtime/Responses/Message.cs
@@ -41,7 +41,7 @@ internal Message(
[Preserve]
public Message(Role role, string text)
- : this(role, new TextContent(text))
+ : this(role, new TextContent(text, role == Role.Assistant ? ResponseContentType.OutputText : ResponseContentType.InputText))
{
}
diff --git a/OpenAI/Packages/com.openai.unity/Runtime/Responses/TextContent.cs b/OpenAI/Packages/com.openai.unity/Runtime/Responses/TextContent.cs
index 4d83acd2..66de38a3 100644
--- a/OpenAI/Packages/com.openai.unity/Runtime/Responses/TextContent.cs
+++ b/OpenAI/Packages/com.openai.unity/Runtime/Responses/TextContent.cs
@@ -29,9 +29,9 @@ internal TextContent(
}
[Preserve]
- public TextContent(string text)
+ public TextContent(string text, ResponseContentType type = ResponseContentType.InputText)
{
- Type = ResponseContentType.InputText;
+ Type = type;
Text = text;
}
diff --git a/OpenAI/Packages/com.openai.unity/Samples~/Chat/ChatBehaviour.cs b/OpenAI/Packages/com.openai.unity/Samples~/Chat/ChatBehaviour.cs
index e9cd8f4e..574bfddb 100644
--- a/OpenAI/Packages/com.openai.unity/Samples~/Chat/ChatBehaviour.cs
+++ b/OpenAI/Packages/com.openai.unity/Samples~/Chat/ChatBehaviour.cs
@@ -11,7 +11,6 @@
using System.Threading;
using System.Threading.Tasks;
using TMPro;
-using Unity.Collections;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
diff --git a/OpenAI/Packages/com.openai.unity/Tests/TestFixture_05_Images.cs b/OpenAI/Packages/com.openai.unity/Tests/TestFixture_05_Images.cs
index 3c1914d1..7967d63f 100644
--- a/OpenAI/Packages/com.openai.unity/Tests/TestFixture_05_Images.cs
+++ b/OpenAI/Packages/com.openai.unity/Tests/TestFixture_05_Images.cs
@@ -44,12 +44,10 @@ public async Task Test_01_01_GenerateImages()
var result = imageResults[i];
Assert.IsNotNull(result);
Assert.IsNotNull(result.Texture);
+ Assert.IsNotNull(result.CachedPathUri);
Assert.IsFalse(string.IsNullOrWhiteSpace(result.B64_Json));
- var imageBytes = Convert.FromBase64String(result.B64_Json);
- Assert.IsNotNull(imageBytes);
var path = Path.Combine(testDirectory, $"{nameof(Test_01_01_GenerateImages)}-{i}-{DateTime.UtcNow:yyyyMMddHHmmss}.jpeg");
- await using var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write);
- await fileStream.WriteAsync(imageBytes, 0, imageBytes.Length);
+ File.Copy(result.CachedPathUri.LocalPath, path, true);
}
}
catch (Exception e)
@@ -82,12 +80,9 @@ public async Task Test_02_01_CreateImageEdit_Path()
var result = imageResults[i];
Assert.IsNotNull(result);
Assert.IsNotNull(result.Texture);
- Assert.IsFalse(string.IsNullOrWhiteSpace(result.B64_Json));
- var imageBytes = Convert.FromBase64String(result.B64_Json);
- Assert.IsNotNull(imageBytes);
+ Assert.IsNotNull(result.CachedPathUri);
var path = Path.Combine(testDirectory, $"{nameof(Test_02_01_CreateImageEdit_Path)}-{i}-{DateTime.UtcNow:yyyyMMddHHmmss}.png");
- await using var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write);
- await fileStream.WriteAsync(imageBytes, 0, imageBytes.Length);
+ File.Copy(result.CachedPathUri.LocalPath, path, true);
}
}
catch (Exception e)
@@ -122,12 +117,10 @@ public async Task Test_02_02_CreateImageEdit_Texture()
var result = imageResults[i];
Assert.IsNotNull(result);
Assert.IsNotNull(result.Texture);
+ Assert.IsNotNull(result.CachedPathUri);
Assert.IsFalse(string.IsNullOrWhiteSpace(result.B64_Json));
- var imageBytes = Convert.FromBase64String(result.B64_Json);
- Assert.IsNotNull(imageBytes);
var path = Path.Combine(testDirectory, $"{nameof(Test_02_02_CreateImageEdit_Texture)}-{i}-{DateTime.UtcNow:yyyyMMddHHmmss}.png");
- await using var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write);
- await fileStream.WriteAsync(imageBytes, 0, imageBytes.Length);
+ File.Copy(result.CachedPathUri.LocalPath, path, true);
}
}
catch (Exception e)
@@ -159,12 +152,10 @@ public async Task Test_02_03_CreateImageEdit_MaskAsTransparency()
var result = imageResults[i];
Assert.IsNotNull(result);
Assert.IsNotNull(result.Texture);
+ Assert.IsNotNull(result.CachedPathUri);
Assert.IsFalse(string.IsNullOrWhiteSpace(result.B64_Json));
- var imageBytes = Convert.FromBase64String(result.B64_Json);
- Assert.IsNotNull(imageBytes);
var path = Path.Combine(testDirectory, $"{nameof(Test_02_03_CreateImageEdit_MaskAsTransparency)}-{i}-{DateTime.UtcNow:yyyyMMddHHmmss}.png");
- await using var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write);
- await fileStream.WriteAsync(imageBytes, 0, imageBytes.Length);
+ File.Copy(result.CachedPathUri.LocalPath, path, true);
}
}
catch (Exception e)
@@ -202,12 +193,10 @@ public async Task Test_02_04_CreateImageEdit_MultipleFiles()
var result = imageResults[i];
Assert.IsNotNull(result);
Assert.IsNotNull(result.Texture);
+ Assert.IsNotNull(result.CachedPathUri);
Assert.IsFalse(string.IsNullOrWhiteSpace(result.B64_Json));
- var imageBytes = Convert.FromBase64String(result.B64_Json);
- Assert.IsNotNull(imageBytes);
var path = Path.Combine(testDirectory, $"{nameof(Test_02_04_CreateImageEdit_MultipleFiles)}-{i}-{DateTime.UtcNow:yyyyMMddHHmmss}.png");
- await using var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write);
- await fileStream.WriteAsync(imageBytes, 0, imageBytes.Length);
+ File.Copy(result.CachedPathUri.LocalPath, path, true);
}
}
catch (Exception e)
@@ -232,8 +221,9 @@ public async Task Test_03_01_CreateImageVariation_Path()
foreach (var result in imageResults)
{
- Assert.IsNotNull(result.Texture);
Debug.Log(result.ToString());
+ Assert.IsNotNull(result.Texture);
+ Assert.IsNull(result.CachedPathUri);
}
}
catch (Exception e)
@@ -261,6 +251,7 @@ public async Task Test_03_02_CreateImageVariation_Texture()
{
Debug.Log(result.ToString());
Assert.IsNotNull(result.Texture);
+ Assert.IsNull(result.CachedPathUri);
}
}
catch (Exception e)
@@ -289,12 +280,10 @@ public async Task Test_03_03_CreateImageVariation_Texture_B64_Json()
var result = imageResults[i];
Assert.IsNotNull(result);
Assert.IsNotNull(result.Texture);
+ Assert.IsNotNull(result.CachedPathUri);
Assert.IsFalse(string.IsNullOrWhiteSpace(result.B64_Json));
- var imageBytes = Convert.FromBase64String(result.B64_Json);
- Assert.IsNotNull(imageBytes);
var path = Path.Combine(testDirectory, $"{nameof(Test_03_03_CreateImageVariation_Texture_B64_Json)}-{i}-{DateTime.UtcNow:yyyyMMddHHmmss}.png");
- await using var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write);
- await fileStream.WriteAsync(imageBytes, 0, imageBytes.Length);
+ File.Copy(result.CachedPathUri.LocalPath, path, true);
}
}
catch (Exception e)
diff --git a/OpenAI/Packages/com.openai.unity/package.json b/OpenAI/Packages/com.openai.unity/package.json
index 28de899e..7bfc8e30 100644
--- a/OpenAI/Packages/com.openai.unity/package.json
+++ b/OpenAI/Packages/com.openai.unity/package.json
@@ -3,7 +3,7 @@
"displayName": "OpenAI",
"description": "A OpenAI package for the Unity to use though their RESTful API.\n\nIndependently developed, this is not an official library and I am not affiliated with OpenAI.\n\nAn OpenAI API account is required.",
"keywords": [],
- "version": "8.8.7",
+ "version": "8.8.8",
"unity": "2021.3",
"documentationUrl": "https://github.com/RageAgainstThePixel/com.openai.unity#documentation",
"changelogUrl": "https://github.com/RageAgainstThePixel/com.openai.unity/releases",
@@ -18,7 +18,7 @@
},
"dependencies": {
"com.utilities.encoder.wav": "3.0.2",
- "com.utilities.rest": "5.0.4",
+ "com.utilities.rest": "5.1.0",
"com.utilities.websockets": "2.0.0"
},
"samples": [