Files
UmaViewer/Assets/Scripts/uGIF/CaptureToGIFCustom.cs

112 lines
3.0 KiB
C#

using UnityEngine;
using System.Collections;
using System.IO;
using System.Collections.Generic;
using System.Threading;
using System.Text;
using System;
namespace uGIF
{
public class CaptureToGIFCustom : MonoBehaviour
{
public static CaptureToGIFCustom Instance;
public List<Image> Frames = new List<Image>();
public bool stop = false;
public bool transparentBackground = false;
[System.NonSerialized]
public byte[] bytes = null;
private void Awake()
{
Instance = this;
}
public IEnumerator Encode (float fps, int quality)
{
bytes = null;
stop = false;
UmaViewerUI.Instance.ScreenshotSettings.GifButton.GetComponentInChildren<TMPro.TextMeshProUGUI>().text = "Recording...";
yield return new WaitForSeconds(0.1f);
yield return _Encode(fps, quality);
UmaViewerUI.Instance.ScreenshotSettings.GifButton.GetComponentInChildren<TMPro.TextMeshProUGUI>().text = "Saving gif...";
yield return new WaitForSeconds(0.1f);
yield return WaitForBytes();
}
IEnumerator WaitForBytes() {
while(bytes == null) yield return new WaitForEndOfFrame();
#if UNITY_ANDROID && !UNITY_EDITOR
string fileDirectory = Application.persistentDataPath + "/../Screenshots/";
#else
string fileDirectory = Application.dataPath + "/../Screenshots/";
#endif
string fileName = fileDirectory + string.Format("UmaViewer_{0}", DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss-fff"));
Directory.CreateDirectory(fileDirectory);
//fixes "/../" in path
var fullpath = Path.GetFullPath($"{fileName}.gif");
File.WriteAllBytes(fullpath, bytes);
bytes = null;
UmaViewerUI.Instance.ShowMessage($"GIF saved: {fullpath}", UIMessageType.Success);
Frames.Clear();
stop = false;
UmaViewerUI.Instance.ScreenshotSettings.GifButton.GetComponentInChildren<TMPro.TextMeshProUGUI>().text = "Record GIF";
}
public IEnumerator _Encode(float fps, int quality)
{
var ge = new GIFEncoder();
// 每帧使用自己的调色板,避免后续彩色帧变灰或偏色。
ge.useGlobalColorTable = false;
ge.repeat = 0;
ge.FPS = Mathf.Max(1f, fps);
ge.quality = Mathf.Clamp(quality, 1, 30);
if (transparentBackground)
{
// 这个颜色值只是通知编码器启用透明。
// 实际透明判断由像素 Alpha 完成。
ge.transparent = new Color32(0, 0, 0, 0);
// 恢复到透明背景,适合完整帧 GIF。
ge.dispose = 2;
}
else
{
ge.transparent = null;
ge.dispose = 0;
}
using (var stream = new MemoryStream())
{
ge.Start(stream);
while (!stop || Frames.Count > 0)
{
if (Frames.Count > 0)
{
Image frame = Frames[0];
Frames.RemoveAt(0);
if (frame != null)
{
// Flip is fused into the Burst quantization/mapping jobs, avoiding
// an additional full-frame copy before every encoded frame.
ge.AddFrame(frame, true);
}
}
yield return null;
}
ge.Finish();
bytes = stream.ToArray();
}
}
}
}