Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
ai.fluctio.fluctio-sim / EditorUtils / EditorGeneral / EditorUpdateEvents.cs
Size: Mime:
using System;
using System.Threading;
using System.Threading.Tasks;
using UnityEditor;
using CallbackFunction = UnityEditor.EditorApplication.CallbackFunction;
// ReSharper disable AccessToModifiedClosure

namespace Fluctio.FluctioSim.EditorUtils.EditorGeneral
{
	public static class EditorUpdateEvents
	{
		
		/**
		 * Uses <see cref="EditorApplication.update"/>, but allows to unsubscribe from inside the handler
		 */
		public static event Action<Action> UpdateWithUnsubscribe
		{
			add
			{
				CallbackFunction handler = null;
				Action unsubscribe = () => EditorApplication.update -= handler;
				handler = () =>
				{
					value(unsubscribe);
				};
				EditorApplication.update += handler;
			}
			remove => ThrowRemoveException(nameof(UpdateWithUnsubscribe), value);
		}
		
		/**
		 * Uses <see cref="EditorApplication.update"/>, stops execution if function returns true
		 */
		public static event Func<bool> UpdateUntil
		{
			add => UpdateWithUnsubscribe += (unsubscribe) =>
			{
				var isFinished = value();
				if (isFinished)
				{
					unsubscribe();
				}
			};
			remove => ThrowRemoveException(nameof(UpdateWhile), value);
		}
		
		/**
		 * Uses <see cref="EditorApplication.update"/>, stops execution if function returns false
		 */
		public static event Func<bool> UpdateWhile
		{
			add => UpdateUntil += () => !value();
			remove => ThrowRemoveException(nameof(UpdateWhile), value);
		}
		
		/**
		 * Uses <see cref="EditorApplication.update"/>, but unsubscribes immediately after one execution.
		 * Works almost like <see cref="EditorApplication.delayCall"/>, but <see cref="EditorApplication.delayCall"/>
		 * may cause long delays if Unity Editor is in background, and this will execute on the earlist tick possible.
		 */
		public static event Action UpdateOnce
		{
			add => UpdateWithUnsubscribe += (unsubscribe) =>
			{
				value();
				unsubscribe();
			};
			remove => ThrowRemoveException(nameof(UpdateOnce), value);
		}
		
		/**
		 * Ensures code is executed on main thread. If we are already on main thread, executes immediately.
		 * If we are on another thread, uses <see cref="UpdateOnce"/>.
		 */
		public static event Action MainThread
		{
			add
			{
				if (Thread.CurrentThread == EditorUtil.MainThread)
				{
					value();
				}
				else
				{
					UpdateOnce += value;
				}
			}
			remove => ThrowRemoveException(nameof(MainThread), value);
		}

		private static void ThrowRemoveException(string eventName, object _)
		{
			throw new NotSupportedException($"Removing from {eventName} event is not supported (yet?)");
		}

		public static async Task WaitNextUpdate()
		{
			var completionSource = new TaskCompletionSource<object>();
			UpdateOnce += () => completionSource.SetResult(null);
			await completionSource.Task;
		}

		public static async Task WaitDelayCall()
		{
			var completionSource = new TaskCompletionSource<object>();
			EditorApplication.delayCall += () => completionSource.SetResult(null);
			await completionSource.Task;
		}
	}
}