예제 #1
0
        // AHAP ------------------------------------------------------------------------------------------------

        public virtual void PlayAHAP(int index)
        {
            Logo.Shaking = true;

            // for the purpose of the demo, and to be able to observe the difference, if any, on certain devices,
            // the first 4 effects (dice, drums, game over, heart beats) will be called on the main thread, and the remaining ones on a secondary thread
            if (index < 5)
            {
                MMVibrationManager.AdvancedHapticPattern(DemoItems[index].AHAPFile.text,
                                                         DemoItems[index].WaveFormAsset.WaveForm.Pattern, DemoItems[index].WaveFormAsset.WaveForm.Amplitudes, -1,
                                                         DemoItems[index].RumbleWaveFormAsset.WaveForm.Pattern, DemoItems[index].RumbleWaveFormAsset.WaveForm.LowFrequencyAmplitudes,
                                                         DemoItems[index].RumbleWaveFormAsset.WaveForm.HighFrequencyAmplitudes, -1,
                                                         HapticTypes.LightImpact, this, -1, false);
                DemoItems[index].AssociatedSound.Play();
                StartCoroutine(ChangeIcon(DemoItems[index].AssociatedSprite));
            }
            else
            {
                MMVibrationManager.AdvancedHapticPattern(DemoItems[index].AHAPFile.text,
                                                         DemoItems[index].WaveFormAsset.WaveForm.Pattern, DemoItems[index].WaveFormAsset.WaveForm.Amplitudes, -1,
                                                         DemoItems[index].RumbleWaveFormAsset.WaveForm.Pattern, DemoItems[index].RumbleWaveFormAsset.WaveForm.LowFrequencyAmplitudes,
                                                         DemoItems[index].RumbleWaveFormAsset.WaveForm.HighFrequencyAmplitudes, -1,
                                                         HapticTypes.LightImpact, this, -1, true);
                DemoItems[index].AssociatedSound.Play();
                StartCoroutine(ChangeIcon(DemoItems[index].AssociatedSprite));
            }
        }
예제 #2
0
        protected virtual void UpdateUI()
        {
            if (Knob.Active)
            {
                // start dent
                if (Time.time - _lastStartClickAt < StartClickDuration)
                {
                    float elapsedTime = StartClickCurve.Evaluate((Time.time - _lastStartClickAt) * (1 / StartClickDuration));
                    Knob._rectTransform.localScale = Vector3.one + Vector3.one * elapsedTime * 0.05f;
                    Knob._image.color = Color.Lerp(ActiveColor, Color.white, elapsedTime);
                }

                // other dents
                foreach (float f in Dents)
                {
                    if (((_knobValue >= f) && (_knobValueLastFrame < f)) || ((_knobValue <= f) && (_knobValueLastFrame > f)))
                    {
                        _lastDentAt = Time.time;
                        break;
                    }
                }
                if (Time.time - _lastDentAt < DentDuration)
                {
                    float elapsedTime = StartClickCurve.Evaluate((Time.time - _lastDentAt) * (1 / DentDuration));
                    Knob._rectTransform.localScale = Vector3.one + Vector3.one * elapsedTime * 0.02f;
                    Knob._image.color = Color.Lerp(ActiveColor, Color.white, elapsedTime * 0.05f);
                    if (MMVibrationManager.iOS())
                    {
                        MMVibrationManager.TransientHaptic(0.4f, 1f);
                    }
                }
            }

            // gas bar
            PowerBar.UpdateBar(Power, 0f, MaximumPowerDuration);

            // power bars
            if (CarSpeed <= 0.1f)
            {
                for (int i = 0; i < SpeedBars.Count; i++)
                {
                    SpeedBars[i].SetActive(false);
                }
            }
            else
            {
                int barsAmount = (int)(CarSpeed * 5f);
                for (int i = 0; i < SpeedBars.Count; i++)
                {
                    if (i <= barsAmount)
                    {
                        SpeedBars[i].SetActive(true);
                    }
                    else
                    {
                        SpeedBars[i].SetActive(false);
                    }
                }
            }
        }
 protected virtual void UpdateContinuousDemo()
 {
     if (_timeLeft > 0f)
     {
         ContinuousProgressBar.UpdateBar(_timeLeft, 0f, ContinuousDuration);
         _timeLeft       -= Time.deltaTime;
         Logo.Shaking     = true;
         TargetCurve.Move = true;
         Logo.Intensity   = NiceVibrationsDemoHelpers.Remap(ContinuousIntensity, 0f, 1f, 1f, 8f);
         Logo.Sharpness   = NiceVibrationsDemoHelpers.Remap(ContinuousSharpness, 0f, 1f, 10f, 25f);
     }
     else
     {
         ContinuousProgressBar.UpdateBar(0f, 0f, ContinuousDuration);
         Logo.Shaking     = false;
         TargetCurve.Move = false;
         if (_continuousActive)
         {
             MMVibrationManager.StopContinuousHaptic(true);
             OnHapticsStopped();
         }
     }
     if ((_sharpnessLastFrame != ContinuousSharpness) || (_intensityLastFrame != ContinuousIntensity))
     {
         TargetCurve.UpdateCurve(ContinuousIntensity, ContinuousSharpness);
     }
     _intensityLastFrame = ContinuousIntensity;
     _sharpnessLastFrame = ContinuousSharpness;
 }
예제 #4
0
        // AHAP ------------------------------------------------------------------------------------------------

        public virtual void PlayAHAP(int index)
        {
            Logo.Shaking = true;
            MMVibrationManager.AdvancedHapticPattern(DemoItems[index].AHAPFile.text, DemoItems[index].WaveFormAsset.WaveForm.Pattern, DemoItems[index].WaveFormAsset.WaveForm.Amplitudes, -1, HapticTypes.LightImpact);
            DemoItems[index].AssociatedSound.Play();
            StartCoroutine(ChangeIcon(DemoItems[index].AssociatedSprite));
        }
        /// <summary>
        /// A coroutine used to update continuous haptics as they're playing
        /// </summary>
        /// <returns></returns>
        protected virtual IEnumerator ContinuousHapticsCoroutine()
        {
            _continuousStartedAt = (Timescale == Timescales.ScaledTime) ? Time.time : Time.unscaledTime;
            _continuousPlaying   = true;
            float elapsedTime = ComputeElapsedTime();

            MMVibrationManager.ContinuousHaptic(InitialContinuousIntensity, InitialContinuousSharpness, ContinuousDuration, HapticTypes.Success, this);

            while (_continuousPlaying && (elapsedTime < ContinuousDuration))
            {
                elapsedTime = ComputeElapsedTime();
                float remappedTime = Remap(elapsedTime, 0f, ContinuousDuration, 0f, 1f);
                float intensity    = ContinuousIntensityCurve.Evaluate(remappedTime);
                float sharpness    = ContinuousSharpnessCurve.Evaluate(remappedTime);
                MMVibrationManager.UpdateContinuousHaptic(intensity, sharpness, true);
                if (AllowRumble)
                {
                    #if MOREMOUNTAINS_NICEVIBRATIONS_RUMBLE
                    MMNVRumble.RumbleContinuous(intensity, sharpness);
                    #endif
                }
                yield return(null);
            }
            if (_continuousPlaying)
            {
                _continuousPlaying = false;
                MMVibrationManager.StopContinuousHaptic(AllowRumble);
            }
        }
 /// <summary>
 /// Returns true if the device running the game has amplitude control
 /// </summary>
 /// <returns></returns>
 public static bool AndroidHasAmplitudeControl()
 {
     if (!MMVibrationManager.Android())
     {
         return(false);
     }
     return(AndroidVibrator.Call <bool>("hasAmplitudeControl"));
 }
 /// <summary>
 /// Returns true if the device running the game has vibrations
 /// </summary>
 /// <returns></returns>
 public static bool AndroidHasVibrator()
 {
     if (!MMVibrationManager.Android())
     {
         return(false);
     }
     return(AndroidVibrator.Call <bool>("hasVibrator"));
 }
 /// <summary>
 /// Stops all Android vibrations that may be active
 /// </summary>
 public static void AndroidCancelVibrations()
 {
     if (!MMVibrationManager.Android())
     {
         return;
     }
     AndroidVibrator.Call("cancel");
 }
예제 #9
0
 public virtual void TransientHapticsButton()
 {
     MMVibrationManager.TransientHaptic(TransientIntensity, TransientSharpness);
     StartCoroutine(Logo.Shake(0.2f));
     DebugAudioTransient.volume = TransientIntensity;
     DebugAudioTransient.pitch  = 0.5f + TransientSharpness / 2f;
     DebugAudioTransient.Play();
 }
예제 #10
0
 /// <summary>
 /// Releases the feedback generators, usually you'll want to call this at OnDisable(); or anytime you know you won't need
 /// vibrations anymore.
 /// </summary>
 public static void iOSReleaseHaptics()
 {
     if (!MMVibrationManager.iOS())
     {
         return;
     }
     MMNViOS_ReleaseFeedbackGenerators();
 }
 protected virtual void UpdateContinuous()
 {
     if (_continuousActive)
     {
         MMVibrationManager.UpdateContinuousHaptic(ContinuousIntensity, ContinuousSharpness, true, -1, true);
         DebugAudioContinuous.volume = ContinuousIntensity;
         DebugAudioContinuous.pitch  = 0.5f + ContinuousSharpness / 2f;
     }
 }
예제 #12
0
 public virtual void HitPusher()
 {
     HitPusherParticles.Play();
     MMVibrationManager.TransientHaptic(0.85f, 0.05f, true, this);
     TransientAudioSource.volume = 0.1f;
     StartCoroutine(LogoShaker.Shake(0.2f));
     TransientAudioSource.Play();
     _ballAnimator.SetTrigger(_hitAnimationParameter);
 }
예제 #13
0
 /// <summary>
 /// Enables or disables all haptics called via this class
 /// </summary>
 /// <param name="status"></param>
 public static void SetHapticsActive(bool status)
 {
     DebugLog("[MMVibrationManager] Set haptics active : " + status);
     _vibrationsActive = status;
     if (!status)
     {
         MMVibrationManager.StopContinuousHaptic(true);
     }
 }
예제 #14
0
 /// <summary>
 /// Requests a default vibration on Android, for the specified duration, in milliseconds
 /// </summary>
 /// <param name="milliseconds">Milliseconds.</param>
 public static void AndroidVibrate(long milliseconds)
 {
     if (!MMVibrationManager.Android())
     {
         return;
     }
     AndroidVibrateMethodRawClassParameters[0].j = milliseconds;
     AndroidJNI.CallVoidMethod(AndroidVibrator.GetRawObject(), AndroidVibrateMethodRawClass, AndroidVibrateMethodRawClassParameters);
 }
예제 #15
0
 /// <summary>
 /// Call this method to initialize the haptics. If you forget to do it, Nice Vibrations will do it for you the first time you
 /// call iOSTriggerHaptics. It's better if you do it though.
 /// </summary>
 public static void iOSInitializeHaptics()
 {
     if (!MMVibrationManager.iOS())
     {
         return;
     }
     MMNViOS_InstantiateFeedbackGenerators();
     iOSHapticsInitialized = true;
 }
예제 #16
0
        protected virtual void HitWall()
        {
            float intensity = _rigidBody.velocity.magnitude / 100f;

            MMVibrationManager.TransientHaptic(intensity, 0.7f, true, this);
            TransientAudioSource.volume = intensity;
            StartCoroutine(LogoShaker.Shake(0.2f));
            TransientAudioSource.Play();
            _ballAnimator.SetTrigger(_hitAnimationParameter);
        }
예제 #17
0
        protected virtual void Transition(int previous, int next, bool goingRight)
        {
            MMVibrationManager.StopAllHaptics(true);

            if (_transitionCoroutine != null)
            {
                StopCoroutine(_transitionCoroutine);
            }
            _transitionCoroutine = StartCoroutine(TransitionCoroutine(previous, next, goingRight));
        }
예제 #18
0
        protected virtual void Start()
        {
            _text.text = Version;

            if (MMVibrationManager.iOS())
            {
                _text.text += " iOS " + MMVibrationManager.iOSVersion.ToString();
            }

            if (MMVibrationManager.Android())
            {
                _text.text += " Android " + MMNVAndroid.AndroidSDKVersion().ToString();
            }
        }
 protected virtual void DisplayInformation()
 {
     if (MMVibrationManager.Android())
     {
         _platformString = "API version " + MMVibrationManager.AndroidSDKVersion().ToString();
     }
     else if (MMVibrationManager.iOS())
     {
         _platformString = "iOS " + MMVibrationManager.iOSSDKVersion();
     }
     else
     {
         _platformString = Application.platform + ", not supported by Nice Vibrations for now.";
     }
     DebugTextBox.text = "Platform : " + _platformString + "\n Nice Vibrations v1.2";
 }
예제 #20
0
 // Requests a vibration on Android for the specified pattern and optional repeat
 // Straight out of the Android documentation :
 // Pass in an array of ints that are the durations for which to turn on or off the vibrator in milliseconds.
 // The first value indicates the number of milliseconds to wait before turning the vibrator on.
 // The next value indicates the number of milliseconds for which to keep the vibrator on before turning it off.
 // Subsequent values alternate between durations in milliseconds to turn the vibrator off or to turn the vibrator on.
 // repeat:  the index into pattern at which to repeat, or -1 if you don't want to repeat.
 public static void AndroidVibrate(long[] pattern, int repeat)
 {
     if (!MMVibrationManager.Android())
     {
         return;
     }
     if ((AndroidSDKVersion() < 26))
     {
         AndroidVibrator.Call("vibrate", pattern, repeat);
     }
     else
     {
         AndroidVibrationEffectClassInitialization();
         VibrationEffect = VibrationEffectClass.CallStatic <AndroidJavaObject>("createWaveform", new object[] { pattern, repeat });
         AndroidVibrator.Call("vibrate", VibrationEffect);
     }
 }
예제 #21
0
 /// <summary>
 /// Requests a vibration of the specified amplitude and duration. If amplitude is not supported by the device's SDK, a default vibration will be requested
 /// </summary>
 /// <param name="milliseconds">Milliseconds.</param>
 /// <param name="amplitude">Amplitude.</param>
 public static void AndroidVibrate(long milliseconds, int amplitude)
 {
     if (!MMVibrationManager.Android())
     {
         return;
     }
     // amplitude is only supported after API26
     if ((AndroidSDKVersion() < 26))
     {
         AndroidVibrate(milliseconds);
     }
     else
     {
         AndroidVibrationEffectClassInitialization();
         VibrationEffect = VibrationEffectClass.CallStatic <AndroidJavaObject>("createOneShot", new object[] { milliseconds, amplitude });
         AndroidVibrator.Call("vibrate", VibrationEffect);
     }
 }
 public virtual void ContinuousHapticsButton()
 {
     if (!_continuousActive)
     {
         // START
         MMVibrationManager.ContinuousHaptic(ContinuousIntensity, ContinuousSharpness, ContinuousDuration, HapticTypes.LightImpact, this, true, -1, true);
         _timeLeft = ContinuousDuration;
         ContinuousButtonText.text   = "Stop continuous haptic pattern";
         DurationSlider.interactable = false;
         _continuousActive           = true;
         DebugAudioContinuous.Play();
     }
     else
     {
         // STOP
         MMVibrationManager.StopContinuousHaptic(true);
         ResetPlayState();
     }
 }
        public virtual void OnPointerExit(PointerEventData data)
        {
            _eventPosition = _pointerEventData.position;

            _newTargetPosition   = GetWorldPosition(_eventPosition);
            _newTargetPosition   = Vector2.ClampMagnitude(_newTargetPosition - _neutralPosition, MaxRange);
            _newTargetPosition   = _neutralPosition + _newTargetPosition;
            _newTargetPosition.z = _initialZPosition;

            _dragging           = false;
            _dragEndedPosition  = _newTargetPosition;
            _dragEndedAt        = Time.time;
            _dragResetDirection = _dragEndedPosition - _neutralPosition;
            _pointerOn          = false;

            TargetAnimator.SetTrigger(_sparkAnimationParameter);
            SpringAudioSource.Play();
            MMVibrationManager.AdvancedHapticPattern(AHAPFile.text, _wobbleAndroidPattern, _wobbleAndroidAmplitude, -1, HapticTypes.LightImpact);
        }
        /// <summary>
        /// When this feedback gets played
        /// </summary>
        /// <param name="position"></param>
        /// <param name="attenuation"></param>
        protected virtual void TestVibration()
        {
            Vector3 position = this.transform.position;

            switch (HapticMethod)
            {
            case HapticMethods.AdvancedPattern:
                string iOSString = (AHAPFileForIOS == null) ? "" : AHAPFileForIOS.text;

                long[] androidPattern   = (AndroidWaveFormFile == null) ? null : AndroidWaveFormFile.WaveForm.Pattern;
                int[]  androidAmplitude = (AndroidWaveFormFile == null) ? null : AndroidWaveFormFile.WaveForm.Amplitudes;

                long[] rumblePattern     = (RumbleWaveFormFile == null) ? null : RumbleWaveFormFile.WaveForm.Pattern;
                int[]  lowFreqAmplitude  = (RumbleWaveFormFile == null) ? null : RumbleWaveFormFile.WaveForm.LowFrequencyAmplitudes;
                int[]  highFreqAmplitude = (RumbleWaveFormFile == null) ? null : RumbleWaveFormFile.WaveForm.HighFrequencyAmplitudes;

                MMVibrationManager.AdvancedHapticPattern(iOSString, androidPattern, androidAmplitude, AndroidRepeat,
                                                         rumblePattern, lowFreqAmplitude, highFreqAmplitude, RumbleRepeat,
                                                         OldIOSFallback, this);
                break;

            case HapticMethods.Continuous:
                StartCoroutine(ContinuousHapticsCoroutine());
                break;

            case HapticMethods.NativePreset:
                MMVibrationManager.Haptic(HapticType, false, AllowRumble, this);
                break;

            case HapticMethods.Transient:
                MMVibrationManager.TransientHaptic(TransientIntensity, TransientSharpness, AllowRumble, this);
                break;

            case HapticMethods.Stop:
                if (_continuousPlaying)
                {
                    MMVibrationManager.StopContinuousHaptic(AllowRumble);
                    _continuousPlaying = false;
                }
                break;
            }
        }
예제 #25
0
        protected virtual void HandlePower()
        {
            _knobValue = Knob.Active ? Knob.Value : 0f;

            if (!_carStarted)
            {
                if ((_knobValue > MinimumKnobValue) && (Knob.Active))
                {
                    _carStarted       = true;
                    _carStartedAt     = Time.time;
                    _lastStartClickAt = Time.time;
                    MMVibrationManager.ContinuousHaptic(_knobValue, _knobValue, MaximumPowerDuration, HapticTypes.MediumImpact, this);
                    CarEngineAudioSource.Play();
                }
                else
                {
                    Power += Time.deltaTime * ChargingSpeed;
                    Power  = Mathf.Clamp(Power, 0f, MaximumPowerDuration);

                    if (Power == MaximumPowerDuration)
                    {
                        Knob.SetActive(true);
                        Knob._rectTransform.localScale = Vector3.one;
                        ReloadingPrompt.SetActive(false);
                    }
                    else
                    {
                        if (!Knob.Active)
                        {
                            Knob.SetValue(CarSpeed);
                        }
                    }
                }
            }
            else
            {
                if (Time.time - _carStartedAt > MaximumPowerDuration)
                {
                    _carStarted = false;
                    Knob.SetActive(false);
                    Knob._rectTransform.localScale = Vector3.one * 0.9f;
                    ReloadingPrompt.SetActive(true);
                }
                else
                {
                    if (_knobValue > MinimumKnobValue)
                    {
                        Power -= Time.deltaTime;
                        Power  = Mathf.Clamp(Power, 0f, MaximumPowerDuration);

                        MMVibrationManager.UpdateContinuousHaptic(_knobValue, _knobValue, true);

                        if (Power <= 0f)
                        {
                            _carStarted = false;
                            Knob.SetActive(false);
                            Knob._rectTransform.localScale = Vector3.one * 0.9f;
                            ReloadingPrompt.SetActive(true);
                        }
                    }
                    else
                    {
                        _carStarted       = false;
                        _lastStartClickAt = Time.time;
                        MMVibrationManager.StopContinuousHaptic(true);
                    }
                }
            }
        }
 /// <summary>
 /// On Awake, we initialize our iOS haptics.
 /// Of course, this only needs to be done when on iOS, or targeting iOS.
 /// A test will be done and this method will do nothing if running on anything else
 /// </summary>
 protected virtual void Awake()
 {
     MMVibrationManager.iOSInitializeHaptics();
 }
 /// <summary>
 /// Triggers the success haptic feedback, a light then heavy vibration on Android, and a success impact on iOS
 /// </summary>
 public virtual void TriggerSuccess()
 {
     MMVibrationManager.Haptic(HapticTypes.Success);
 }
 /// <summary>
 /// Triggers the selection haptic feedback, a light vibration on Android, and a light impact on iOS
 /// </summary>
 public virtual void TriggerSelection()
 {
     MMVibrationManager.Haptic(HapticTypes.Selection);
 }
 /// <summary>
 /// Triggers the default Vibrate method, which will result in a medium vibration on Android and a medium impact on iOS
 /// </summary>
 public virtual void TriggerVibrate()
 {
     MMVibrationManager.Vibrate();
 }
 /// <summary>
 /// On Disable, we release our iOS haptics (to save memory and avoid garbage).
 /// Of course, this only needs to be done when on iOS, or targeting iOS.
 /// A test will be done and this method will do nothing if running on anything else
 /// </summary>
 protected virtual void OnDisable()
 {
     MMVibrationManager.iOSReleaseHaptics();
 }