using System; using System.Collections; using System.IO; using UnityEngine; using UnityEngine.Networking; #if UNITY_EDITOR using UnityEditor; #endif namespace UniGLTF { public interface ITextureLoader : IDisposable { Texture2D Texture { get; } /// /// Call from any thread /// /// /// void ProcessOnAnyThread(glTF gltf, IStorage storage); /// /// Call from unity main thread /// /// /// IEnumerator ProcessOnMainThread(bool isLinear); } #if UNITY_EDITOR public class AssetTextureLoader : ITextureLoader { public Texture2D Texture { private set; get; } private string m_textureName; UnityPath m_assetPath; public AssetTextureLoader(UnityPath assetPath, string textureName) { m_assetPath = assetPath; m_textureName = textureName; } public void Dispose() { } public void ProcessOnAnyThread(glTF gltf, IStorage storage) { } public IEnumerator ProcessOnMainThread(bool isLinear) { // // texture from assets // m_assetPath.ImportAsset(); var importer = m_assetPath.GetImporter(); if (importer == null) { Debug.LogWarningFormat("fail to get TextureImporter: {0}", m_assetPath); } importer.sRGBTexture = !isLinear; importer.SaveAndReimport(); Texture = m_assetPath.LoadAsset(); //Texture.name = m_textureName; if (Texture == null) { Debug.LogWarningFormat("fail to Load Texture2D: {0}", m_assetPath); } yield break; } } #endif public class TextureLoader : ITextureLoader { int m_textureIndex; public TextureLoader(int textureIndex) { m_textureIndex = textureIndex; } public Texture2D Texture { private set; get; } public void Dispose() { } static Byte[] ToArray(ArraySegment bytes) { if (bytes.Array == null) { return new byte[] { }; } else if (bytes.Offset == 0 && bytes.Count == bytes.Array.Length) { return bytes.Array; } else { Byte[] result = new byte[bytes.Count]; Buffer.BlockCopy(bytes.Array, bytes.Offset, result, 0, result.Length); return result; } } Byte[] m_imageBytes; string m_textureName; public void ProcessOnAnyThread(glTF gltf, IStorage storage) { var imageIndex = gltf.GetImageIndexFromTextureIndex(m_textureIndex); var segments = gltf.GetImageBytes(storage, imageIndex, out m_textureName); m_imageBytes = ToArray(segments); } public IEnumerator ProcessOnMainThread(bool isLinear) { // // texture from image(png etc) bytes // Texture = new Texture2D(2, 2, TextureFormat.ARGB32, false, isLinear); Texture.name = m_textureName; if (m_imageBytes != null) { Texture.LoadImage(m_imageBytes); } yield break; } } public class UnityWebRequestTextureLoader : ITextureLoader { public Texture2D Texture { private set; get; } int m_textureIndex; public UnityWebRequestTextureLoader(int textureIndex) { m_textureIndex = textureIndex; } UnityWebRequest m_uwr; public void Dispose() { if (m_uwr != null) { m_uwr.Dispose(); m_uwr = null; } } ArraySegment m_segments; string m_textureName; public void ProcessOnAnyThread(glTF gltf, IStorage storage) { var imageIndex = gltf.GetImageIndexFromTextureIndex(m_textureIndex); m_segments = gltf.GetImageBytes(storage, imageIndex, out m_textureName); } #if false HttpHost m_http; class HttpHost : IDisposable { TcpListener m_listener; Socket m_connection; public HttpHost(int port) { m_listener = new TcpListener(IPAddress.Loopback, port); m_listener.Start(); m_listener.BeginAcceptSocket(OnAccepted, m_listener); } void OnAccepted(IAsyncResult ar) { var l = ar.AsyncState as TcpListener; if (l == null) return; m_connection = l.EndAcceptSocket(ar); // 次の接続受付はしない BeginRead(m_connection, new byte[8192]); } void BeginRead(Socket c, byte[] buffer) { AsyncCallback callback = ar => { var s = ar.AsyncState as Socket; if (s == null) return; var size = s.EndReceive(ar); if (size > 0) { OnRead(buffer, size); } BeginRead(s, buffer); }; m_connection.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, callback, m_connection); } List m_buffer = new List(); void OnRead(byte[] buffer, int len) { m_buffer.AddRange(buffer.Take(len)); } public string Url { get { } } public void Dispose() { if (m_connection != null) { m_connection.Dispose(); m_connection = null; } if(m_listener != null) { m_listener.Stop(); m_listener = null; } } } #endif class Deleter : IDisposable { string m_path; public Deleter(string path) { m_path = path; } public void Dispose() { if (File.Exists(m_path)) { File.Delete(m_path); } } } public IEnumerator ProcessOnMainThread(bool isLinear) { // tmp file var tmp = Path.GetTempFileName(); using (var f = new FileStream(tmp, FileMode.Create)) { f.Write(m_segments.Array, m_segments.Offset, m_segments.Count); } using (var d = new Deleter(tmp)) { var url = "file:///" + tmp.Replace("\\", "/"); Debug.LogFormat("UnityWebRequest: {0}", url); using (var m_uwr = new WWW(url)) { yield return m_uwr; // wait for request while (!m_uwr.isDone) { yield return null; } if (!string.IsNullOrEmpty(m_uwr.error)) { Debug.Log(m_uwr.error); yield break; } // Get downloaded asset bundle Texture = m_uwr.textureNonReadable; Texture.name = m_textureName; } } } } }