using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; namespace MoreMountains.Tools { /// /// A class used to generate signals, normalized values between 0 and 1 /// You can then use these values from a MMRadioBroadcaster, or simply evaluate its value to use wherever you want, /// like a supercharged animation curve. In that case, simply disable the component, and read from it using its Evaluate method /// public class MMRadioSignalGenerator : MMRadioSignal { /// whether or not to display an animated preview public bool AnimatedPreview = false; /// whether this signal should play in back & forth (mirroring the curve around a tipping point) public bool BackAndForth = false; /// the tipping point at which to mirror the curve (between 0 and 1) [MMCondition("BackAndForth", true)] public float BackAndForthMirrorPoint = 0.5f; /// the list of signals to assemble to create the final signal public MMRadioSignalGeneratorItemList SignalList; /// how to clamp the result value [MMVector("Min", "Max")] public Vector2 Clamps = new Vector2(0f, 1f); /// the amplitude of the signal [Range(0f, 1f)] public float Bias = 0.5f; /// /// On reset, we initialize our list /// void Reset() { SignalList = new MMRadioSignalGeneratorItemList(){ new MMRadioSignalGeneratorItem() }; } /// /// Returns the y value of the generated signal curve, at the x time value specified in parameters /// /// /// public virtual float Evaluate(float time) { float level = 1f; if (SignalList.Count <= 0) { return level; } time = ApplyBias(time, Bias); for (int i = 0; i < SignalList.Count; i++) { if (SignalList[i].Active) { float newLevel = MMSignal.GetValueNormalized(time, SignalList[i].SignalType, SignalList[i].Phase, SignalList[i].Amplitude, SignalList[i].Frequency, SignalList[i].Offset, SignalList[i].Invert, SignalList[i].Curve, SignalList[i].TweenCurve, true, Clamps.x, Clamps.y, BackAndForth, BackAndForthMirrorPoint); level = (SignalList[i].Mode == MMRadioSignalGeneratorItem.GeneratorItemModes.Multiply) ? level * newLevel : level + newLevel; } } CurrentLevel *= GlobalMultiplier; CurrentLevel = Mathf.Clamp(CurrentLevel, Clamps.x, Clamps.y); return level; } /// /// On Shake, we shake our level if needed /// protected override void Shake() { base.Shake(); if (!Playing) { return; } if (SignalMode == SignalModes.OneTime) { float elapsedTime = TimescaleTime - _shakeStartedTimestamp; CurrentLevel = Evaluate(MMMaths.Remap(elapsedTime, 0f, Duration, 0f, 1f)); } else { CurrentLevel = Evaluate(DriverTime); } } /// /// Once the shake is complete, we apply our final level /// protected override void ShakeComplete() { base.ShakeComplete(); CurrentLevel = Evaluate(1f); } /// /// returns a custom value to display in the graph in inspector /// /// /// public override float GraphValue(float time) { time = ApplyBias(time, Bias); return Evaluate(time); } } /// /// A class used to store generator items and their properties /// [System.Serializable] public class MMRadioSignalGeneratorItem { /// whether this individual signal should be multiplied or added to the rest public enum GeneratorItemModes { Multiply, Additive } /// whether to take this signal into account in the generator or not public bool Active = true; /// the type of this signal public MMSignal.SignalType SignalType = MMSignal.SignalType.Sine; /// if the type is animation curve, the curve to consider [MMEnumCondition("SignalType", (int)MMSignal.SignalType.AnimationCurve)] public AnimationCurve Curve = new AnimationCurve(new Keyframe(0, 0), new Keyframe(1, 1)); /// if the type is MMTween, the tween to consider [MMEnumCondition("SignalType", (int)MMSignal.SignalType.MMTween)] public MMTween.MMTweenCurve TweenCurve = MMTween.MMTweenCurve.EaseInOutQuartic; /// the selected mode (multiply or additive) public GeneratorItemModes Mode = GeneratorItemModes.Multiply; /// the phase of the signal [Range(-1f, 1f)] public float Phase = 0f; /// the frequency of the signal [Range(0f, 10f)] public float Frequency = 5f; /// the amplitude of the signal [Range(0f, 1f)] public float Amplitude = 1f; /// the offset of the signal [Range(-1f, 1f)] public float Offset = 0f; /// whether or not to vertically invert the signal public bool Invert = false; } /// /// A reorderable list type used to store generator items /// [System.Serializable] public class MMRadioSignalGeneratorItemList : MMReorderableArray { } }