public static float getGrabStrength(GrabbingInfoSettings settings, Hand hand, InteractionObject volume, bool isCurrentlyGrabbing)
    {
        GrabbingInfoCalculator calculator = getCalculator(settings, hand, volume);

        calculator.ensureUpdated(hand, isCurrentlyGrabbing);
        return(calculator.grabValue);
    }
    private const long CALCULATOR_FRAME_TIMEOUT = 60; //number of frames to pass before a calculator can be recycled

    private static GrabbingInfoCalculator getCalculator(GrabbingInfoSettings settings, Hand hand, InteractionObject volume)
    {
        HandObjectPair key     = new HandObjectPair(hand.Id, volume);
        long           frameId = hand.Frame.Id;

        int index = -1;

        if (!_indexMap.TryGetValue(key, out index))
        {
            for (int i = 0; i < _calculators.Count; i++)
            {
                if (_calculators[i].lastUpdatedFrameId < frameId - CALCULATOR_FRAME_TIMEOUT)
                {
                    _calculators[i].reset(settings, volume);
                    _indexMap[key] = i;
                    return(_calculators[i]);
                }
            }

            GrabbingInfoCalculator newCalculator = new GrabbingInfoCalculator(settings, volume);
            _indexMap[key] = _calculators.Count;
            _calculators.Add(newCalculator);
            return(newCalculator);
        }

        return(_calculators[index]);
    }
        public void reset(GrabbingInfoSettings newSettings, InteractionObject targetVolume)
        {
            if (newSettings != _settings)
            {
                _settings = newSettings;

                _valueCalculators.Clear();

                _valueCalculators.Add(new FingerProximityCalculator(this, _settings.fingerProximity, ValueType.GRAB));
                _valueCalculators.Add(new FingerGrabbingPoseCalculator(this, _settings.fingerGrabbingPose, ValueType.GRAB));
                _valueCalculators.Add(new FingerGrabbingSpeedCalculator(this, _settings.fingerGrabbingSpeed, ValueType.GRAB));

                _valueCalculators.Add(new FingerReleasingPoseCalculator(this, _settings.fingerReleasingPose, ValueType.RELEASE));
                _valueCalculators.Add(new FingerReleasingSpeedCalculator(this, _settings.fingerReleasingSpeed, ValueType.RELEASE));
                _valueCalculators.Add(new HandPalmDirectionCalculator(this, _settings.handPalmDirection, ValueType.RELEASE));
                _valueCalculators.Add(new HandPalmDistanceReleaseCalculator(this, _settings.handPalmDistanceRelease, ValueType.RELEASE));

                _valueCalculators.Add(new HandMovementRateCalculator(this, _settings.movementRate, ValueType.STABILITY));
                _valueCalculators.Add(new HandRotationRateCalculator(this, _settings.rotationRate, ValueType.STABILITY));
            }
            else
            {
                foreach (IValueCalculator c in _valueCalculators)
                {
                    c.reset();
                }
            }

            _targetVolume = targetVolume;
        }
 void Awake()
 {
     _instance             = this;
     _grabbingInfoSettings = GetComponent <GrabbingInfoSettings>();
 }
 public static bool shouldRelease(GrabbingInfoSettings settings, Hand hand, InteractionObject volume)
 {
     return(getGrabStrength(settings, hand, volume, true) < settings.releaseGrabThreshold.x);
 }
 public static bool shouldGrab(GrabbingInfoSettings settings, Hand hand, InteractionObject volume)
 {
     return(getGrabStrength(settings, hand, volume, false) > settings.releaseGrabThreshold.y);
 }
 public GrabbingInfoCalculator(GrabbingInfoSettings settings, InteractionObject targetVolume)
 {
     reset(settings, targetVolume);
 }
 void Awake()
 {
     _instance = this;
     _grabbingInfoSettings = GetComponent<GrabbingInfoSettings>();
 }