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 / Core / Components / Base / EditorComponent.cs
Size: Mime:
using System;
using UnityEngine;

#if UNITY_EDITOR
using UnityEditor;
#endif

namespace Fluctio.FluctioSim.Core.Components.Base
{
	/// <summary>
	/// Base class for editor components with convenient functions
	/// </summary>
	[ExecuteAlways]
	public abstract class EditorComponent : MonoBehaviour
	{
		
		#region Fields

		[NonSerialized] private bool _hasInitializeHappened = false;
		[SerializeField, HideInInspector] private bool hasInitializeOnceHappened = false;

		private void InitializeOnceWithChecks()
		{
			if (!hasInitializeOnceHappened)
			{
				InitializeOnce();
				hasInitializeOnceHappened = true;
			}
		}

		private void InitializeWithChecks()
		{
			if (!_hasInitializeHappened)
			{
				Initialize();
				_hasInitializeHappened = true;
			}
		}

		private void InitializePrefabWithChecks()
		{
			#if UNITY_EDITOR
			if (PrefabUtility.IsPartOfAnyPrefab(gameObject))
			{
				return;
			}
			#endif
			InitializePrefab();
		}

		#endregion
		
		#region Virtual functions
		
		/**
		 * This function is executed in editor and in runtime.
		 * It is intended for retrieving and filling non-serialized references,
		 * which depend on other components, and needs to happen on assembly reload.
		 */
		protected virtual void Initialize() {}

		/**
		 * This function is executed once when component is added in the editor.
		 * It is intended for creation of other objects/components
		 * and filling serialized references with default values.
		 */
		protected virtual void InitializeOnce()
		{
			#if UNITY_EDITOR
				Undo.SetCurrentGroupName($"Add {GetType().Name}");
			#endif
			InitializePrefabWithChecks();
		}

		/**
		 * This function is executed for each component in prefab
		 * when player creates object via CreateMenu.
		 */
		public virtual void InitializePrefab() {}
		
		public virtual void OnAnyChanged() {}
		public virtual void OnSelfChanged() => OnAnyChanged();
		public virtual void OnOtherChanged() => OnAnyChanged();
		
		#endregion

		#region Unity event functions

		protected bool ShouldExecute(bool skipInitializedCheck = false, bool allowInPlayMode = false)
		{
			var initializedCheck = _hasInitializeHappened || skipInitializedCheck;
			var runningCheck = !Application.isPlaying || allowInPlayMode;
			var sceneCheck = gameObject.scene.IsValid();
			return initializedCheck && runningCheck && sceneCheck;
		}
		
		protected virtual void Awake()
		{
			if (!ShouldExecute(skipInitializedCheck: true, allowInPlayMode: true))
			{
				return;
			}
			
			if (Application.isPlaying)
			{
				InitializeWithChecks();
			}
			else
			{
				InitializeOnceWithChecks();
				InitializeWithChecks();
			}
		}

		protected virtual void Reset()
		{
			if (!ShouldExecute(allowInPlayMode: true))
			{
				return;
			}
			InitializeOnceWithChecks();
			InitializeWithChecks();
			OnSelfChanged();
		}

		protected virtual void OnValidate()
		{
			if (!ShouldExecute(skipInitializedCheck: true, allowInPlayMode: true))
			{
				return;
			}
			InitializeWithChecks();
			OnSelfChanged();
		}

		// ReSharper disable Unity.PerformanceAnalysis
		protected virtual void Update()
		{
			if (!ShouldExecute())
			{
				return;
			}
			OnOtherChanged();
		}

		protected virtual void OnDestroy()
		{
			#if UNITY_EDITOR
				Undo.SetCurrentGroupName($"Remove {GetType().Name}");
			#endif
		}

		#endregion
	}

	#if UNITY_EDITOR
	[CustomEditor(typeof(EditorComponent), true)]
	public class EditorComponentEditor : Editor
	{
		protected virtual string[] PropertiesToExclude => new[] { "m_Script" };
		
		public override void OnInspectorGUI()
		{
			serializedObject.Update();
			DrawPropertiesExcluding(serializedObject, PropertiesToExclude);
			serializedObject.ApplyModifiedProperties();
		}
	}
	#endif
}