|
|
|
|
|
|
using System; |
|
|
|
using System.Collections; |
|
|
|
using System.Collections.Generic; |
|
|
|
using Unity.UIWidgets.async; |
|
|
|
using Unity.UIWidgets.foundation; |
|
|
|
using UnityEngine; |
|
|
|
|
|
|
|
|
|
|
public GifDecoder.GifFrame gifFrame; |
|
|
|
} |
|
|
|
|
|
|
|
readonly List<Promise<FrameData>> _frames; |
|
|
|
volatile byte[] _bytes; |
|
|
|
volatile int _width; |
|
|
|
volatile int _height; |
|
|
|
volatile int _frameCount; |
|
|
|
|
|
|
volatile Texture2D _texture; |
|
|
|
readonly UIWidgetsCoroutine _coroutine; |
|
|
|
volatile FrameData _frameData; |
|
|
|
volatile Image _image; |
|
|
|
IEnumerator _coroutine; |
|
|
|
this._frames = new List<Promise<FrameData>>(); |
|
|
|
this._width = 0; |
|
|
|
this._height = 0; |
|
|
|
this._bytes = bytes; |
|
|
|
this._coroutine = this._startDecoding(); |
|
|
|
this._init(); |
|
|
|
this._texture = new Texture2D(this._width, this._height, TextureFormat.BGRA32, false); |
|
|
|
this._texture.hideFlags = HideFlags.HideAndDontSave; |
|
|
|
this._image = new Image(this._texture); |
|
|
|
} |
|
|
|
|
|
|
|
void _init() { |
|
|
|
var bytesStream = new MemoryStream(this._bytes); |
|
|
|
this._coroutine = Window.instance.startBackgroundCoroutine( |
|
|
|
this._startDecoding(bytes, Window.instance)); |
|
|
|
var gifDecoder = new GifDecoder(); |
|
|
|
if (gifDecoder.read(bytesStream) != GifDecoder.STATUS_OK) { |
|
|
|
throw new Exception("Failed to decode gif."); |
|
|
|
} |
|
|
|
|
|
|
|
this._width = gifDecoder.frameWidth; |
|
|
|
this._height = gifDecoder.frameHeight; |
|
|
|
IEnumerator _startDecoding(byte[] bytes, Window window) { |
|
|
|
var bytesStream = new MemoryStream(bytes); |
|
|
|
IEnumerator _startDecoding() { |
|
|
|
var bytesStream = new MemoryStream(this._bytes); |
|
|
|
|
|
|
|
var gifDecoder = new GifDecoder(); |
|
|
|
if (gifDecoder.read(bytesStream) != GifDecoder.STATUS_OK) { |
|
|
|
|
|
|
|
|
|
|
int i = 0; |
|
|
|
while (true) { |
|
|
|
yield return null; |
|
|
|
|
|
|
|
if (gifDecoder.nextFrame() != GifDecoder.STATUS_OK) { |
|
|
|
throw new Exception("Failed to decode gif."); |
|
|
|
} |
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
var frameData = new FrameData { |
|
|
|
gifFrame = gifDecoder.currentFrame, |
|
|
|
gifFrame = gifDecoder.currentFrame |
|
|
|
Promise<FrameData> frame; |
|
|
|
this._frameData = frameData; |
|
|
|
lock (this._frames) { |
|
|
|
if (i < this._frames.Count) { |
|
|
|
} |
|
|
|
else { |
|
|
|
D.assert(this._frames.Count == i); |
|
|
|
this._frames.Add(new Promise<FrameData>()); |
|
|
|
} |
|
|
|
i++; |
|
|
|
frame = this._frames[i]; |
|
|
|
} |
|
|
|
|
|
|
|
window.runInMain(() => { frame.Resolve(frameData); }); |
|
|
|
|
|
|
|
i++; |
|
|
|
yield return null; |
|
|
|
} |
|
|
|
|
|
|
|
D.assert(gifDecoder.frameCount == i); |
|
|
|
|
|
|
void _nextFrame() { |
|
|
|
this._frameIndex++; |
|
|
|
|
|
|
|
this._coroutine.MoveNext(); |
|
|
|
|
|
|
|
this._isDone = false; |
|
|
|
this._coroutine = this._startDecoding(); |
|
|
|
this._coroutine.MoveNext(); |
|
|
|
Promise<FrameData> frame; |
|
|
|
|
|
|
|
lock (this._frames) { |
|
|
|
if (this._frameIndex == this._frames.Count) { |
|
|
|
this._frames.Add(new Promise<FrameData>()); |
|
|
|
} |
|
|
|
else { |
|
|
|
D.assert(this._frameIndex < this._frames.Count); |
|
|
|
} |
|
|
|
|
|
|
|
frame = this._frames[this._frameIndex]; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return frame.Then(frameData => { |
|
|
|
this._nextFrame(); |
|
|
|
|
|
|
|
if (this._texture == null) { |
|
|
|
this._texture = new Texture2D(this._width, this._height, TextureFormat.BGRA32, false); |
|
|
|
this._texture.hideFlags = HideFlags.HideAndDontSave; |
|
|
|
} |
|
|
|
|
|
|
|
var tex = this._texture; |
|
|
|
tex.LoadRawTextureData(frameData.gifFrame.bytes); |
|
|
|
tex.Apply(); |
|
|
|
|
|
|
|
if (frameData.frameInfo != null) { |
|
|
|
return frameData.frameInfo; |
|
|
|
} |
|
|
|
|
|
|
|
frameData.frameInfo = new FrameInfo { |
|
|
|
image = new Image(tex), |
|
|
|
duration = TimeSpan.FromMilliseconds(frameData.gifFrame.delay) |
|
|
|
}; |
|
|
|
// frameData.gifFrame = null; // dispose gifFrame
|
|
|
|
|
|
|
|
return frameData.frameInfo; |
|
|
|
}); |
|
|
|
this._nextFrame(); |
|
|
|
this._texture.LoadRawTextureData(this._frameData.gifFrame.bytes); |
|
|
|
this._texture.Apply(); |
|
|
|
this._frameData.frameInfo = new FrameInfo() { |
|
|
|
image = this._image, |
|
|
|
duration = TimeSpan.FromMilliseconds(this._frameData.gifFrame.delay) |
|
|
|
}; |
|
|
|
return Promise<FrameInfo>.Resolved(this._frameData.frameInfo); |
|
|
|
this._coroutine.stop(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |