diff --git a/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs b/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs index a7f7978b2..90d51edf3 100644 --- a/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs +++ b/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs @@ -248,6 +248,19 @@ private struct ImageInfo public bool canBeExportedFromDisk; } + private struct FileInfo + { + public Stream stream; + public string uniqueFileName; + } + + public struct ExportFileResult + { + public string uri; + public string mimeType; + public BufferViewId bufferView; + } + public IReadOnlyList RootTransforms => _rootTransforms; private Transform[] _rootTransforms; @@ -255,12 +268,14 @@ private struct ImageInfo private BufferId _bufferId; private GLTFBuffer _buffer; private List _imageInfos; + private List _fileInfos; + private HashSet _fileNames; private List _textures; private Dictionary _exportedMaterials; #if ANIMATION_SUPPORTED private List<(Transform tr, AnimationClip clip)> _animationClips; #endif - private bool _shouldUseInternalBufferForImages; + private bool shouldUseInternalBuffer; private Dictionary _exportedTransforms; private List _animatedNodes; @@ -511,6 +526,8 @@ public GLTFSceneExporter(Transform[] rootTransforms, ExportOptions options) }; _imageInfos = new List(); + _fileInfos = new List(); + _fileNames = new HashSet(); _exportedMaterials = new Dictionary(); _textures = new List(); #if ANIMATION_SUPPORTED @@ -546,16 +563,17 @@ public void SaveGLB(string path, string fileName) var dirName = Path.GetDirectoryName(fullPath); if (dirName != null && !Directory.Exists(dirName)) Directory.CreateDirectory(dirName); - _shouldUseInternalBufferForImages = true; + shouldUseInternalBuffer = true; using (FileStream glbFile = new FileStream(fullPath, FileMode.Create)) { SaveGLBToStream(glbFile, fileName); } - if (!_shouldUseInternalBufferForImages) + if (!shouldUseInternalBuffer) { ExportImages(path); + ExportFiles(path); } } @@ -566,7 +584,7 @@ public void SaveGLB(string path, string fileName) /// public byte[] SaveGLBToByteArray(string sceneName) { - _shouldUseInternalBufferForImages = true; + shouldUseInternalBuffer = true; using (var stream = new MemoryStream()) { SaveGLBToStream(stream, sceneName); @@ -586,7 +604,7 @@ public void SaveGLBToStream(Stream stream, string sceneName) exportGltfInitMarker.Begin(); Stream binStream = new MemoryStream(); Stream jsonStream = new MemoryStream(); - _shouldUseInternalBufferForImages = true; + shouldUseInternalBuffer = true; _bufferWriter = new BinaryWriterWithLessAllocations(binStream); @@ -679,7 +697,7 @@ public void SaveGLTFandBin(string path, string fileName) exportGltfMarker.Begin(); exportGltfInitMarker.Begin(); - _shouldUseInternalBufferForImages = false; + shouldUseInternalBuffer = false; var toLower = fileName.ToLowerInvariant(); if (toLower.EndsWith(".gltf")) fileName = fileName.Substring(0, fileName.Length - 5); @@ -746,6 +764,7 @@ public void SaveGLTFandBin(string path, string fileName) binFile.Close(); #endif ExportImages(path); + ExportFiles(path); gltfWriteOutMarker.End(); exportGltfMarker.End(); @@ -1051,6 +1070,53 @@ private void FilterPrimitives(Transform transform, out GameObject[] primitives, // && ContainsValidRenderer(gameObject); // } + public ExportFileResult ExportFile(string fileName, string mimeType, Stream stream) { + if (shouldUseInternalBuffer) { + byte[] data = new byte[stream.Length]; + stream.Read(data, 0, (int)stream.Length); + stream.Close(); + + return new ExportFileResult { + bufferView = this.ExportBufferView(data), + mimeType = mimeType, + }; + } else { + var uniqueFileName = GetUniqueName(_fileNames, fileName); + + _fileNames.Add(uniqueFileName); + + _fileInfos.Add( + new FileInfo { + stream = stream, + uniqueFileName = uniqueFileName, + } + ); + + return new ExportFileResult { + uri = uniqueFileName, + }; + } + } + + private void ExportFiles(string outputPath) + { + for (int i = 0; i < _fileInfos.Count; ++i) + { + var fileInfo = _fileInfos[i]; + + var fileOutputPath = Path.Combine(outputPath, fileInfo.uniqueFileName); + + var dir = Path.GetDirectoryName(fileOutputPath); + if (!Directory.Exists(dir) && dir != null) + Directory.CreateDirectory(dir); + + var outputStream = File.Create(fileOutputPath); + fileInfo.stream.Seek(0, SeekOrigin.Begin); + fileInfo.stream.CopyTo(outputStream); + outputStream.Close(); + } + } + private void ExportAnimation() { for (int i = 0; i < _animatedNodes.Count; ++i) diff --git a/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/SceneExporter/ExporterAccessors.cs b/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/SceneExporter/ExporterAccessors.cs index 55909a3d2..41a0f4664 100644 --- a/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/SceneExporter/ExporterAccessors.cs +++ b/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/SceneExporter/ExporterAccessors.cs @@ -1119,6 +1119,14 @@ private AccessorId ExportAccessor(Color[] arr, bool exportAlphaChannel) return id; } + public BufferViewId ExportBufferView(byte[] bytes) { + AlignToBoundary(_bufferWriter.BaseStream, 0x00); + uint byteOffset = CalculateAlignment((uint)_bufferWriter.BaseStream.Position, 4); + _bufferWriter.Write(bytes); + uint byteLength = CalculateAlignment((uint)_bufferWriter.BaseStream.Position - byteOffset, 4); + return ExportBufferView((uint)byteOffset, (uint)byteLength); + } + private BufferViewId ExportBufferView(uint byteOffset, uint byteLength, uint byteStride = 0) { var bufferView = new BufferView diff --git a/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/SceneExporter/ExporterTextures.cs b/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/SceneExporter/ExporterTextures.cs index d3b17305a..48574fd28 100644 --- a/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/SceneExporter/ExporterTextures.cs +++ b/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/SceneExporter/ExporterTextures.cs @@ -173,7 +173,7 @@ public TextureId ExportTexture(Texture textureObj, string textureSlot, TextureEx texture.Name = textureObj.name; } - if (_shouldUseInternalBufferForImages) + if (shouldUseInternalBuffer) { texture.Source = ExportImageInternalBuffer(uniqueTexture, textureSlot); }