// zlib/libpng License
//
// Copyright (c) 2019 Sinoa
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
namespace IceMilkTeaEditor.Common
{
///
/// IEnumerable の拡張関数実装用クラスです
///
public static class ImtEnumerableExtensions
{
///
/// DisplayProgress を実行した際にダイアログに表示するパラメータを持つクラスです
///
///
public class ProgressWindowParameter
{
///
/// 要素の最大値
///
public int Max { get; set; }
///
/// 処理した数
///
public int Count { get; set; }
///
/// 列挙されたオブジェクト
///
public TSource Item { get; set; }
///
/// プログレスダイアログに表示するタイトル
///
public string Title { get; set; }
///
/// プログレスダイアログに表示するテキスト
///
public string Text { get; set; }
}
///
/// sources から要素数を取得できる場合は要素数を取得します
///
/// 要素の型
/// 要素数を取得する元になる Enumerable
/// 要素数を取得できた場合は要素数を返しますが、取得できなかった場合は -1 を返します
private static int GetCount(IEnumerable sources)
{
// 配列なら
if (sources is Array)
{
// 長さを返す
return ((Array)sources).Length;
}
else if (sources is IList)
{
// リストなら数を返す
return ((IList)sources).Count;
}
else if (sources is IList)
{
// リストなら数を返す
return ((IList)sources).Count;
}
// どれもすぐに長さを取得できないなら-1を返す
return -1;
}
///
/// 列挙しながらプログレスダイアログを表示します
///
/// 列挙する要素の型
/// 列挙できるオブジェクトを持っている Enumerable
/// プログレスダイアログに表示するべき内容を設定するためのコールバック
/// 列挙中の列挙可能オブジェクトを返します
/// sources が null です
/// callback が null です
public static IEnumerable DisplayProgress(this IEnumerable sources, Action> callback)
{
// 必要な変数を宣言
var parameter = new ProgressWindowParameter();
var max = GetCount(sources);
var count = 0;
// コールバックが null なら
if (callback == null)
{
// 何をするのか
throw new ArgumentNullException(nameof(callback));
}
// 要素をすべて回るための
using (var enumerator = (sources ?? throw new ArgumentNullException(nameof(sources))).GetEnumerator())
{
// すべて回る
while (enumerator.MoveNext())
{
// パラメータを設定してコールバックを呼ぶ
parameter.Max = max;
parameter.Count = ++count;
parameter.Title = string.Empty;
parameter.Text = string.Empty;
parameter.Item = enumerator.Current;
callback(parameter);
// ダイアログを表示
var title = parameter.Title ?? string.Empty;
var text = parameter.Text ?? string.Empty;
var progress = parameter.Max < 0 ? 1.0f : parameter.Count / (float)parameter.Max;
var cancel = EditorUtility.DisplayCancelableProgressBar(title, text, progress);
// キャンセルされたらループから抜ける
if (cancel) break;
// 要素を一時返却
yield return enumerator.Current;
}
}
// プログレスダイアログを非表示
EditorUtility.ClearProgressBar();
}
}
}