summaryrefslogtreecommitdiff
path: root/Assets/Samples/XR Interaction Toolkit/3.1.2/Hands Interaction Demo/HandsDemoSceneAssets/Scripts/PokeBlendShapeAnimator.cs
blob: f70af262c5d03d8cf38f99294e2fcdcac969b841 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
using Unity.XR.CoreUtils.Bindings;
using UnityEngine.XR.Interaction.Toolkit.AffordanceSystem.State;
using UnityEngine.XR.Interaction.Toolkit.Filtering;
using UnityEngine.XR.Interaction.Toolkit.Interactables;
using UnityEngine.XR.Interaction.Toolkit.Utilities.Tweenables.Primitives;

namespace UnityEngine.XR.Interaction.Toolkit.Samples.Hands
{
    /// <summary>
    /// Animates a blend shape on a SkinnedMeshRenderer based on the interaction strength of a poke.
    /// </summary>
    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;
#pragma warning disable CS0618 // Type or member is obsolete
        readonly FloatTweenableVariable m_TweenableVariable = new FloatTweenableVariable();
#pragma warning restore CS0618 // Type or member is obsolete

        float m_TweenTarget;

        /// <summary>
        /// See <see cref="MonoBehaviour"/>.
        /// </summary>
        void OnEnable()
        {
            if (m_PokeFilter == null || m_SkinnedMeshRenderer == null)
            {
                enabled = false;
                return;
            }

            m_HoverInteractable = m_PokeFilter.GetComponent<IXRHoverInteractable>();
            m_InteractionStrengthInteractable = m_PokeFilter.GetComponent<IXRInteractionStrengthInteractable>();

            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);
            }));
        }

        /// <summary>
        /// See <see cref="MonoBehaviour"/>.
        /// </summary>
        void OnDisable()
        {
            m_BindingsGroup.Clear();
        }

        /// <summary>
        /// See <see cref="MonoBehaviour"/>.
        /// </summary>
        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;
        }
    }
}