// 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(); } } }