Added Feel plugin
This commit is contained in:
262
Assets/External/Feel/NiceVibrations/Scripts/Components/HapticSource.cs
vendored
Normal file
262
Assets/External/Feel/NiceVibrations/Scripts/Components/HapticSource.cs
vendored
Normal file
@@ -0,0 +1,262 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace Lofelt.NiceVibrations
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides haptic playback functionality for a single haptic clip.
|
||||
/// </summary>
|
||||
///
|
||||
/// HapticSource plays back the HapticClip assigned in the \ref clip property
|
||||
/// when calling Play(). It also provides various ways to control playback, such as
|
||||
/// seeking, looping and amplitude/frequency modulation.
|
||||
///
|
||||
/// When a gamepad is connected, the haptic clip will be played back on that gamepad.
|
||||
/// See the HapticController documentation for more details about gamepad support.
|
||||
///
|
||||
/// At the moment, playback of a haptic source is not triggered automatically
|
||||
/// by e.g. proximity between the HapticReceiver and the HapticSource,
|
||||
/// so you need to call Play() to trigger playback.
|
||||
///
|
||||
/// You can place multiple HapticSource components in your scene, with a different
|
||||
/// HapticClip assigned to each.
|
||||
///
|
||||
/// HapticSource provides a per-clip <c>MonoBehaviour</c> API for the functionality
|
||||
/// in HapticController, while HapticReceiver provides a <c>MonoBehaviour</c> API
|
||||
/// for the global functionality in HapticController.
|
||||
///
|
||||
/// <c>HapticSourceInspector</c> provides a custom editor for HapticSource for the
|
||||
/// Inspector.
|
||||
[AddComponentMenu("Nice Vibrations/Haptic Source")]
|
||||
public class HapticSource : MonoBehaviour
|
||||
{
|
||||
const int DEFAULT_PRIORITY = 128;
|
||||
|
||||
/// The HapticClip this HapticSource loads and plays.
|
||||
public HapticClip clip;
|
||||
|
||||
/// <summary>
|
||||
/// The priority of the HapticSource
|
||||
/// </summary>
|
||||
///
|
||||
/// This property is set by <c>HapticSourceInspector</c>. 0 is the highest priority and 256
|
||||
/// is the lowest priority.
|
||||
///
|
||||
/// The default value is 128.
|
||||
public int priority = DEFAULT_PRIORITY;
|
||||
|
||||
/// <summary>
|
||||
/// Jump in time position of haptic source playback.
|
||||
/// </summary>
|
||||
///
|
||||
/// Initially set to 0.0 seconds.
|
||||
/// This value can only be set when using Seek().
|
||||
float seekTime = 0.0f;
|
||||
|
||||
[SerializeField]
|
||||
HapticPatterns.PresetType _fallbackPreset = HapticPatterns.PresetType.None;
|
||||
|
||||
/// <summary>
|
||||
/// The haptic preset to be played when it's not possible to play a haptic clip
|
||||
/// </summary>
|
||||
[System.ComponentModel.DefaultValue(HapticPatterns.PresetType.None)]
|
||||
public HapticPatterns.PresetType fallbackPreset
|
||||
{
|
||||
get { return _fallbackPreset; }
|
||||
set { _fallbackPreset = value; }
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
bool _loop = false;
|
||||
|
||||
/// <summary>
|
||||
/// Set the haptic source to loop playback of the haptic clip.
|
||||
/// </summary>
|
||||
///
|
||||
/// It will only have any effect once Play() is called.
|
||||
///
|
||||
/// See HapticController::Loop() for further details.
|
||||
[System.ComponentModel.DefaultValue(false)]
|
||||
public bool loop
|
||||
{
|
||||
get { return _loop; }
|
||||
set { _loop = value; }
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
float _level = 1.0f;
|
||||
|
||||
/// <summary>
|
||||
/// The level of the haptic source
|
||||
/// </summary>
|
||||
///
|
||||
/// Haptic source level is applied in combination with output level (which can be set on either
|
||||
/// HapticReceiver or HapticController according to preference), to the currently playing
|
||||
/// haptic clip. The combination of these two levels and the amplitude within the loaded
|
||||
/// haptic at a given moment in time determines the strength of the vibration felt on the device. See
|
||||
/// HapticController::clipLevel for further details.
|
||||
[System.ComponentModel.DefaultValue(1.0)]
|
||||
public float level
|
||||
{
|
||||
get { return _level; }
|
||||
set
|
||||
{
|
||||
_level = value;
|
||||
|
||||
if (IsLoaded())
|
||||
{
|
||||
HapticController.clipLevel = _level;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
float _frequencyShift = 0.0f;
|
||||
|
||||
/// <summary>
|
||||
/// This shift is added to the frequency of every breakpoint in the clip, including the
|
||||
/// emphasis.
|
||||
/// </summary>
|
||||
///
|
||||
/// See HapticController::clipFrequencyShift for further details.
|
||||
[System.ComponentModel.DefaultValue(0.0)]
|
||||
public float frequencyShift
|
||||
{
|
||||
get { return _frequencyShift; }
|
||||
set
|
||||
{
|
||||
_frequencyShift = value;
|
||||
|
||||
if (IsLoaded())
|
||||
{
|
||||
HapticController.clipFrequencyShift = _frequencyShift;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The HapticSource that is currently loaded into HapticController.
|
||||
/// This can be null if nothing was ever loaded, or if HapticController::Load()
|
||||
/// was called directly, bypassing HapticSource.
|
||||
static HapticSource loadedHapticSource = null;
|
||||
|
||||
/// The HapticSource that was last played.
|
||||
/// This can be null if nothing was ever player, or if HapticController::Play()
|
||||
/// was called directly, bypassing HapticSource.
|
||||
/// The lastPlayedHapticSource isn't necessarily playing now, lastPlayedHapticSource
|
||||
/// will remain set even if playback has finished or was stopped.
|
||||
static HapticSource lastPlayedHapticSource = null;
|
||||
|
||||
static HapticSource()
|
||||
{
|
||||
// When HapticController::Load() or HapticController::Play() is
|
||||
// called directly, bypassing HapticSource, reset loadedHapticSource
|
||||
// and lastPlayedHapticSource.
|
||||
HapticController.LoadedClipChanged += () =>
|
||||
{
|
||||
loadedHapticSource = null;
|
||||
};
|
||||
HapticController.PlaybackStarted += () =>
|
||||
{
|
||||
lastPlayedHapticSource = null;
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads and plays back the haptic clip.
|
||||
/// </summary>
|
||||
///
|
||||
/// At the moment only one haptic clip at a time can be played. If another
|
||||
/// HapticSource is currently playing and has lower priority, its playback will
|
||||
/// be stopped.
|
||||
///
|
||||
/// If a seek time within the time range of the clip has been set with Seek(),
|
||||
/// it will jump to that position if \ref loop is <c>false</c>. If \ref loop
|
||||
/// is <c>true</c>, seeking will have no effect.
|
||||
///
|
||||
/// It will loop playback in case \ref loop is <c>true</c>.
|
||||
public void Play()
|
||||
{
|
||||
if (CanPlay())
|
||||
{
|
||||
//
|
||||
// Load
|
||||
//
|
||||
HapticController.Load(clip);
|
||||
loadedHapticSource = this;
|
||||
|
||||
//
|
||||
// Apply properties like loop, modulation and seek position
|
||||
//
|
||||
HapticController.Loop(loop);
|
||||
|
||||
HapticController.clipLevel = level;
|
||||
HapticController.clipFrequencyShift = frequencyShift;
|
||||
|
||||
if (seekTime != 0.0f && !loop)
|
||||
{
|
||||
HapticController.Seek(seekTime);
|
||||
}
|
||||
|
||||
//
|
||||
// Play
|
||||
//
|
||||
HapticController.fallbackPreset = fallbackPreset;
|
||||
HapticController.Play();
|
||||
lastPlayedHapticSource = this;
|
||||
}
|
||||
}
|
||||
|
||||
private bool CanPlay()
|
||||
{
|
||||
return (!HapticController.IsPlaying() ||
|
||||
(lastPlayedHapticSource != null && priority <= lastPlayedHapticSource.priority));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the current HapticSource has been loaded into HapticController.
|
||||
/// </summary>
|
||||
///
|
||||
/// This is used to avoid triggering operations on HapticController while
|
||||
/// another HapticSource is loaded.
|
||||
private bool IsLoaded()
|
||||
{
|
||||
return Object.ReferenceEquals(this, loadedHapticSource);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops playback that was previously started with Play().
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
if (IsLoaded())
|
||||
{
|
||||
HapticController.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the time position to jump to when Play() is called.
|
||||
/// </summary>
|
||||
///
|
||||
/// It will only have an effect once Play() is called.
|
||||
///
|
||||
/// <param name="time">The position in the clip, in seconds</param>
|
||||
public void Seek(float time)
|
||||
{
|
||||
this.seekTime = time;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When a <c>GameObject</c> is disabled, stop playback if this HapticSource is
|
||||
/// playing.
|
||||
/// </summary>
|
||||
public void OnDisable()
|
||||
{
|
||||
if (HapticController.IsPlaying() && IsLoaded())
|
||||
{
|
||||
this.Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user