using Unity.XR.CoreUtils.Bindings;
using UnityEngine.XR.Interaction.Toolkit.AffordanceSystem.State;
using UnityEngine.XR.Interaction.Toolkit.Filtering;
using UnityEngine.XR.Interaction.Toolkit.Utilities.Tweenables.Primitives;
namespace UnityEngine.XR.Interaction.Toolkit.Samples.Hands
{
///
/// Animates a blend shape on a SkinnedMeshRenderer based on the interaction strength of a poke.
///
public class PokeBlendShapeAnimator : MonoBehaviour
{
[SerializeField]
[Tooltip("The PokeFilter to use to determine the interaction strength.")]
XRPokeFilter m_PokeFilter;
[SerializeField]
[Tooltip("The SkinnedMeshRenderer to animate.")]
SkinnedMeshRenderer m_SkinnedMeshRenderer;
[SerializeField]
[Tooltip("The index of the blend shape to animate.")]
int m_BlendShapeIndex;
[SerializeField]
[Tooltip("The minimum blend shape value.")]
float m_BlendShapeMin;
[SerializeField]
[Tooltip("The maximum blend shape value.")]
float m_BlendShapeMax = 100f;
readonly BindingsGroup m_BindingsGroup = new BindingsGroup();
IXRHoverInteractable m_HoverInteractable;
IXRInteractionStrengthInteractable m_InteractionStrengthInteractable;
readonly FloatTweenableVariable m_TweenableVariable = new FloatTweenableVariable();
float m_TweenTarget;
///
/// See .
///
void OnEnable()
{
if (m_PokeFilter == null || m_SkinnedMeshRenderer == null)
{
enabled = false;
return;
}
m_HoverInteractable = m_PokeFilter.GetComponent();
m_InteractionStrengthInteractable = m_PokeFilter.GetComponent();
m_BindingsGroup.AddBinding(m_PokeFilter.pokeStateData.Subscribe(data =>
{
var blendShapeValue = Mathf.Lerp(m_BlendShapeMin, m_BlendShapeMax, data.interactionStrength);
m_TweenTarget = blendShapeValue;
}));
m_BindingsGroup.AddBinding(m_TweenableVariable.SubscribeAndUpdate(newValue =>
{
m_SkinnedMeshRenderer.SetBlendShapeWeight(m_BlendShapeIndex, newValue);
}));
}
///
/// See .
///
void OnDisable()
{
m_BindingsGroup.Clear();
}
///
/// See .
///
void Update()
{
m_TweenableVariable.HandleTween(Time.deltaTime * 16f);
if (m_HoverInteractable.interactorsHovering.Count == 0)
return;
var pokeInteractorStrength = 0f;
var largestNonPokeInteractorStrength = 0f;
for (var index = 0; index < m_HoverInteractable.interactorsHovering.Count; ++index)
{
var interactor = m_HoverInteractable.interactorsHovering[index];
var interactionStrength = m_InteractionStrengthInteractable.GetInteractionStrength(interactor);
var isPokeProvider = interactor is IPokeStateDataProvider;
if (isPokeProvider)
{
pokeInteractorStrength = interactionStrength;
}
else
{
largestNonPokeInteractorStrength = Mathf.Max(largestNonPokeInteractorStrength, interactionStrength);
}
}
m_TweenableVariable.target = pokeInteractorStrength > largestNonPokeInteractorStrength ? m_TweenTarget : 0f;
}
}
}