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    
Size: Mime:
using System.ComponentModel;
using Fluctio.FluctioSim.Common.Configuration;
using Fluctio.FluctioSim.Core.Components.MachineLearning.NumberProviders;
using UnityEngine;

#if UNITY_EDITOR
using Fluctio.FluctioSim.EditorUtils.Gui;
using UnityEditor;
#endif

namespace Fluctio.FluctioSim.Core.Components.MachineLearning.Triggers
{
	[AddComponentMenu(Config.PrefixedName+"/Machine Learning/Triggers/Number Trigger", Config.ComponentMenuOrder + 70)]
	public class NumberTrigger : Trigger
	{
		[field: SerializeField] public ConditionType ConditionType { get; private set; }
		[field: SerializeField] public ComparisonType ComparisonType { get; private set; }
		[field: SerializeField] public float ExactNumber { get; private set; }
		[field: SerializeField] public float MinNumber { get; private set; }
		[field: SerializeField] public float MaxNumber { get; private set; }
		[field: SerializeField] public NumberProvider Number { get; private set; }

		private bool _wasConditionSatisfiedPreviously = false;

		private bool IsConditionSatisfied()
		{
			var number = Number.GetNumber();
			return ComparisonType switch
			{
				ComparisonType.InRange or ComparisonType.Max or ComparisonType.Min
					=> (number >= MinNumber) && (number <= MaxNumber),
				// ReSharper disable once CompareOfFloatsByEqualityOperator
				ComparisonType.Exact => (number == ExactNumber),
				ComparisonType.ApproximateFloat => Mathf.Approximately(number, ExactNumber),
				_ => throw new InvalidEnumArgumentException(
					nameof(ComparisonType),
					(int)ComparisonType,
					ComparisonType.GetType())
			};
		}

		private void OnValidate()
		{
			// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
			switch (ComparisonType)
			{
				case ComparisonType.Max:
					MinNumber = -Mathf.Infinity;
					break;
				case ComparisonType.Min:
					MaxNumber = Mathf.Infinity;
					break;
			}
		}

		private void FixedUpdate()
		{
			var isConditionSatisfied = IsConditionSatisfied();
			switch (ConditionType)
			{
				case ConditionType.EachStepWhileSatisfied:
					if (isConditionSatisfied)
					{
						ScheduleActions();
					}
					break;
				case ConditionType.OnceWhenSatisfied:
					if (isConditionSatisfied && !_wasConditionSatisfiedPreviously)
					{
						ScheduleActions();
					}
					break;
				default:
					throw new InvalidEnumArgumentException(
						nameof(ConditionType),
						(int)ConditionType,
						ConditionType.GetType());
			}
			_wasConditionSatisfiedPreviously = isConditionSatisfied;
		}
	}

	public enum ConditionType
	{
		[Tooltip("Trigger each step while condition is true")]
		EachStepWhileSatisfied,
		[Tooltip("Trigger once when condition becomes true")]
		OnceWhenSatisfied,
	}

	public enum ComparisonType
	{
		[InspectorName("Trigger when smaller than")]
		Max,
		[InspectorName("Trigger when bigger than")]
		Min,
		[InspectorName("Trigger when in range")]
		InRange,
		[InspectorName("Trigger when exactly")]
		Exact,
		[InspectorName("Trigger when almost exactly (use Mathf.Approximately)")]
		[Tooltip("Uses Mathf.Approximately() to avoid floating point inaccuracies")]
		ApproximateFloat,
	}

	#if UNITY_EDITOR
	[CustomEditor(typeof(NumberTrigger), true)]
	public class DistanceTriggerEditor : Editor
	{
		// ReSharper disable once InconsistentNaming
		private new NumberTrigger target => (NumberTrigger)base.target;
		
		private void DrawDistanceProperties()
		{
			switch (target.ComparisonType)
			{
				case ComparisonType.Min:
					serializedObject.DrawProperties(nameof(target.MinNumber));
					break;
				case ComparisonType.Max:
					serializedObject.DrawProperties(nameof(target.MaxNumber));
					break;
				case ComparisonType.InRange:
					serializedObject.DrawProperties(nameof(target.MinNumber), nameof(target.MaxNumber));
					break;
				case ComparisonType.ApproximateFloat:
				case ComparisonType.Exact:
					serializedObject.DrawProperties(nameof(target.ExactNumber));
					break;
				default:
					throw new InvalidEnumArgumentException(
						nameof(target.ComparisonType),
						(int)target.ComparisonType,
						target.ComparisonType.GetType());
			}
		}
		
		public override void OnInspectorGUI()
		{
			serializedObject.Update();
			serializedObject.DrawProperties("ConditionType", "Number", "ComparisonType");
			DrawDistanceProperties();
			serializedObject.ApplyModifiedProperties();
		}
	}
	#endif
}