// SPDX-FileCopyrightText: 2023 Unity Technologies and the glTFast authors
// SPDX-License-Identifier: Apache-2.0
using System;
using System.Threading.Tasks;
using Unity.Collections;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.Profiling;
namespace GLTFast.Loading
{
///
/// Default implementation
///
public class DefaultDownloadProvider : IDownloadProvider
{
///
/// Sends a URI request and waits for its completion.
///
/// URI to request
/// Object representing the request
public async Task Request(Uri url)
{
var req = new AwaitableDownload(url);
await req.WaitAsync();
return req;
}
///
/// Sends a URI request to load a texture
///
/// URI to request
/// If true, resulting texture is not CPU readable (uses less memory)
/// Object representing the request
#pragma warning disable CS1998
public async Task RequestTexture(Uri url, bool nonReadable)
{
#pragma warning restore CS1998
#if UNITY_WEBREQUEST_TEXTURE
var req = new AwaitableTextureDownload(url,nonReadable);
await req.WaitAsync();
return req;
#else
return null;
#endif
}
}
///
/// Default implementation that loads URIs via
///
public class AwaitableDownload :
IDownload
#if UNITY_2021_3_OR_NEWER
,INativeDownload
#endif
{
const string k_MimeTypeGltfBinary = "model/gltf-binary";
const string k_MimeTypeGltf = "model/gltf+json";
///
/// that is used for the download
///
protected UnityWebRequest m_Request;
///
/// The download's
///
protected UnityWebRequestAsyncOperation m_AsyncOperation;
///
/// Empty constructor
///
protected AwaitableDownload() { }
///
/// Creates a download of a URI
///
/// URI to request
public AwaitableDownload(Uri url)
{
Init(url);
}
void Init(Uri url)
{
m_Request = UnityWebRequest.Get(url);
m_AsyncOperation = m_Request.SendWebRequest();
}
///
/// Waits until the URI request is completed.
///
/// A task that represents the completion of the download
public async Task WaitAsync()
{
while (!m_AsyncOperation.isDone)
{
await Task.Yield();
}
}
///
/// True if the download finished and was successful
///
public bool Success => m_Request != null && m_Request.isDone && m_Request.result == UnityWebRequest.Result.Success;
///
/// If the download failed, error description
///
public string Error => m_Request == null ? "Request disposed" : m_Request.error;
///
/// Downloaded data as byte array
///
public byte[] Data
{
get
{
Profiler.BeginSample("AwaitableDownload.Data");
var result = m_Request?.downloadHandler.data;
Profiler.EndSample();
return result;
}
}
#if UNITY_2021_3_OR_NEWER
///
public NativeArray.ReadOnly NativeData => m_Request?.downloadHandler.nativeData ?? default;
#endif
///
/// Downloaded data as string
///
public string Text => m_Request?.downloadHandler.text;
///
/// True if the requested download is a glTF-Binary file.
/// False if it is a regular JSON-based glTF file.
/// Null if the type could not be determined.
///
public bool? IsBinary
{
get
{
if (Success)
{
string contentType = m_Request.GetResponseHeader("Content-Type");
if (contentType == k_MimeTypeGltfBinary)
return true;
if (contentType == k_MimeTypeGltf)
return false;
}
#if UNITY_2021_3_OR_NEWER
return GltfGlobals.IsGltfBinary(NativeData);
#else
return null;
#endif
}
}
///
/// Releases previously allocated resources.
///
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
///
/// Releases previously allocated resources.
///
/// Indicates whether the method call comes from a Dispose method (its value is true)
/// or from a finalizer (its value is false).
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
m_Request.Dispose();
m_Request = null;
}
}
}
#if UNITY_WEBREQUEST_TEXTURE
///
/// Default implementation that loads
/// texture URIs via .
///
public class AwaitableTextureDownload : AwaitableDownload, ITextureDownload {
///
/// Parameter-less constructor, required for inheritance.
///
protected AwaitableTextureDownload() {}
///
/// Default constructor.
///
/// Texture URI to request
/// If true, resulting texture is not CPU readable (uses less memory)
public AwaitableTextureDownload(Uri url, bool nonReadable) {
Init(url,nonReadable);
}
///
/// Generates the UnityWebRequest used for sending the request.
///
/// Texture URI to request
/// If true, resulting texture is not CPU readable (uses less memory)
/// UnityWebRequest used for sending the request
protected static UnityWebRequest CreateRequest(Uri url, bool nonReadable) {
return UnityWebRequestTexture.GetTexture(url,nonReadable);
}
void Init(Uri url, bool nonReadable) {
m_Request = CreateRequest(url,nonReadable);
m_AsyncOperation = m_Request.SendWebRequest();
}
///
public Texture2D Texture => (m_Request?.downloadHandler as DownloadHandlerTexture )?.texture;
}
#endif
}