RestrictionSuggestor.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using UnityEngine;
  5. using Valve.VR.InteractionSystem;
  6. namespace SicknessReduction.Visual.Vignetting
  7. {
  8. public interface IRestrectionSuggestor
  9. {
  10. float Suggestion { get; }
  11. }
  12. public abstract class RestrictionSuggestor : IRestrectionSuggestor
  13. {
  14. protected readonly float threshold;
  15. protected readonly float minRestriction;
  16. protected readonly float maxRestriction;
  17. protected readonly float maxValue;
  18. protected RestrictionSuggestor(float threshold, float minRestriction, float maxRestriction,
  19. float maxValue)
  20. {
  21. this.threshold = threshold;
  22. this.minRestriction = minRestriction;
  23. this.maxRestriction = maxRestriction;
  24. this.maxValue = maxValue;
  25. }
  26. protected float LerpedSuggestion(float value) => Mathf.Lerp(minRestriction, maxRestriction,
  27. (value - threshold) / (maxValue - threshold));
  28. public abstract float Suggestion { get; }
  29. }
  30. public class ValueBasedRestrictionSuggestor : RestrictionSuggestor
  31. {
  32. public override float Suggestion
  33. {
  34. get
  35. {
  36. var abs = Mathf.Abs(Value);
  37. return abs < threshold
  38. ? 0f
  39. : LerpedSuggestion(abs);
  40. }
  41. }
  42. public float Value { set; get; } = 0f;
  43. public ValueBasedRestrictionSuggestor(float threshold, float minRestriction, float maxRestriction,
  44. float maxValue) : base(threshold, minRestriction, maxRestriction, maxValue)
  45. {
  46. }
  47. }
  48. public class ValueAndTimeBasedRestrictionSuggestor : RestrictionSuggestor
  49. {
  50. private readonly float tolerance;
  51. private readonly float timespan;
  52. private readonly Dictionary<float, float> values = new Dictionary<float, float>();
  53. private float value;
  54. public ValueAndTimeBasedRestrictionSuggestor(float threshold, float minRestriction, float maxRestriction, float maxValue, float tolerance, float timespan) : base(threshold, minRestriction, maxRestriction, maxValue)
  55. {
  56. this.tolerance = tolerance;
  57. this.timespan = timespan;
  58. }
  59. public override float Suggestion
  60. {
  61. get
  62. {
  63. var abs = Mathf.Abs(value);
  64. var stable = !values.Values.Any(v => Mathf.Abs(v - value) > tolerance);
  65. return abs < threshold || stable
  66. ? 0f
  67. : LerpedSuggestion(abs);
  68. }
  69. }
  70. public void UpdateValue(float v)
  71. {
  72. value = v;
  73. var t = Time.time;
  74. values[t] = v;
  75. var keys = values.Keys.Where(k => t - k > timespan).ToList();
  76. keys.ForEach(k => values.Remove(k));
  77. }
  78. }
  79. public abstract class QueueBasedRestrictionSuggestor<T> : RestrictionSuggestor
  80. {
  81. protected Queue<Tuple<float, T>> values;
  82. protected int bufferSize;
  83. public QueueBasedRestrictionSuggestor(float threshold, float minRestriction, float maxRestriction,
  84. float maxValue, int bufferSize = 10) : base(threshold, minRestriction, maxRestriction, maxValue)
  85. {
  86. this.bufferSize = bufferSize;
  87. values = new Queue<Tuple<float, T>>(bufferSize);
  88. }
  89. public void AddValue(T value)
  90. {
  91. if (values.Count >= bufferSize)
  92. {
  93. values.Dequeue();
  94. }
  95. values.Enqueue(new Tuple<float, T>(Time.time, value));
  96. }
  97. }
  98. public class QueueBasedRestrictionSuggestorFloat : QueueBasedRestrictionSuggestor<float>
  99. {
  100. public QueueBasedRestrictionSuggestorFloat(float threshold, float minRestriction, float maxRestriction,
  101. float maxValue, int bufferSize = 10) : base(threshold, minRestriction, maxRestriction, maxValue, bufferSize)
  102. {
  103. }
  104. public override float Suggestion
  105. {
  106. get
  107. {
  108. var perSecond = new float[values.Count];
  109. var index = 0;
  110. var previousValue = values.FirstOrDefault();
  111. foreach (var value in values)
  112. {
  113. // ReSharper disable once PossibleNullReferenceException
  114. var timeDif = value.Item1 - previousValue.Item1;
  115. perSecond[index] = timeDif == 0
  116. ? 0f
  117. : Mathf.Abs(value.Item2 - previousValue.Item2) /
  118. timeDif;
  119. previousValue = value;
  120. index++;
  121. }
  122. var avg = perSecond.Length == 0 ? 0f : perSecond.Average();
  123. return avg < threshold
  124. ? 0f
  125. : LerpedSuggestion(avg);
  126. }
  127. }
  128. }
  129. public class QueueBasedRestrictionSuggestorVector3 : QueueBasedRestrictionSuggestor<Vector3>
  130. {
  131. public QueueBasedRestrictionSuggestorVector3(float threshold, float minRestriction, float maxRestriction,
  132. float maxValue, int bufferSize = 10) : base(threshold, minRestriction, maxRestriction, maxValue, bufferSize)
  133. {
  134. }
  135. public override float Suggestion
  136. {
  137. get
  138. {
  139. var perSecond = new Vector3[values.Count];
  140. var index = 0;
  141. var previousValue = values.FirstOrDefault();
  142. foreach (var value in values)
  143. {
  144. // ReSharper disable once PossibleNullReferenceException
  145. var timeDif = value.Item1 - previousValue.Item1;
  146. perSecond[index] = timeDif == 0
  147. ? Vector3.zero
  148. : Helpers.Vector3Abs(value.Item2 - previousValue.Item2) /
  149. timeDif;
  150. previousValue = value;
  151. index++;
  152. }
  153. var avg = perSecond.Aggregate(Vector3.zero, (agg, v) => agg + v) / perSecond.Length;
  154. var max = Helpers.GetMaxComponent(avg);
  155. return max < threshold
  156. ? 0f
  157. : LerpedSuggestion(max);
  158. }
  159. }
  160. }
  161. }