using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xna.Framework.Graphics;
namespace SharpGLTF.Runtime.Pipeline
{
///
/// Factory used to convert images into objects.
///
///
/// By default, this factory is only able to read images using ;
/// In order to add support for more formats, create a derived class and register it at
///
public class TextureFactory
{
#region lifecycle
///
/// Register here your own derived class to override texture creation
///
public static Func InstanceBuilder { get; set; }
public static TextureFactory Create(GraphicsDevice device, GraphicsResourceTracker disposables)
{
ArgumentNullException.ThrowIfNull(device);
ArgumentNullException.ThrowIfNull(disposables);
var tf = InstanceBuilder?.Invoke(device, disposables);
tf ??= new TextureFactory(device, disposables);
return tf;
}
protected TextureFactory(GraphicsDevice device, GraphicsResourceTracker disposables)
{
_Device = device;
_Disposables = disposables;
}
#endregion
#region data
private readonly GraphicsDevice _Device;
private readonly GraphicsResourceTracker _Disposables;
// temporary cache to prevent creating the same texture multiple times
private readonly Dictionary _Textures = new Dictionary();
#endregion
#region API
///
/// Some effects require a white texture
///
///
public Texture2D UseWhiteImage()
{
var tex = _Disposables
.Disposables
.OfType()
.FirstOrDefault(item => item.Name == "_InternalSolidWhite");
if (tex != null) return tex;
const string solidWhitePNg = "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAFHpUWHRUaXRsZQAACJkrz8gsSQUABoACIippo0oAAAAoelRYdEF1dGhvcgAACJkLy0xOzStJVQhIzUtMSS1WcCzKTc1Lzy8BAG89CQyAoFAQAAAAGklEQVQoz2P8//8/AymAiYFEMKphVMPQ0QAAVW0DHZ8uFaIAAAAASUVORK5CYII=";
var toBytes = Convert.FromBase64String(solidWhitePNg);
return UseTexture(new ArraySegment(toBytes), "_InternalSolidWhite");
}
public Texture2D UseTexture(Memory.MemoryImage image, string name = null)
{
if (_Device == null) throw new InvalidOperationException();
if (!image.IsValid) return null;
if (image.MimeType == "image/webp") return UseWhiteImage();
if (image.MimeType == "image/ktx2") return UseWhiteImage();
if (_Textures.TryGetValue(image, out Texture2D tex)) return tex;
using (var m = image.Open())
{
tex = LoadTexture(_Device, m, image.MimeType);
_Disposables.AddDisposable(tex);
tex.Name = name;
_Textures[image] = tex;
return tex;
}
}
#endregion
#region Overridable API
///
/// Override this method to support loading images not supported by MonoGame (KTX2, WebP)
///
protected virtual Texture2D LoadTexture(GraphicsDevice device, System.IO.Stream image, string imageMimeType)
{
if (imageMimeType == "image/webp") throw new NotSupportedException("webp images not supported");
if (imageMimeType == "image/ktx2") throw new NotSupportedException("ktx2 images not supported");
return Texture2D.FromStream(device, image);
}
#endregion
}
}