示例#1
0
        private void OnHapticFeedbackReceived(object sender, HapticPulse hapticPulse)
        {
            lastHapticPulseLengthUs = hapticPulse.LengthUs;
            lastHapticPulseTime     = DateTime.Now;

            RaisePropertyChanged(() => HapticPulseInfo);
        }
示例#2
0
 /// <summary>
 /// Perform a haptic feedback pulse
 /// </summary>
 /// <param name="node">Node on which to control the pulse</param>
 /// <param name="hapticPulse">Haptic pulse to perform</param>
 /// <param name="durationMultiplier">(Optional) Multiplier value applied to the hapticPulse duration</param>
 /// <param name="intensityMultiplier">(Optional) Multiplier value applied to the hapticPulse intensity</param>
 public static void Pulse(this IControlHaptics obj, Node?node, HapticPulse hapticPulse, float durationMultiplier = 1f, float intensityMultiplier = 1f)
 {
     pulse(node, hapticPulse, durationMultiplier, intensityMultiplier);
 }
示例#3
0
        // Sets up connection and returns true if all links are established.
        private bool TrySettingUpConnection()
        {
            lastConnectionAttempt = DateTime.Now;

            // Make sure API server is alive
            var status = api.GetStatus(timeoutThresholdMs);

            if (status == null)
            {
                return(false);
            }

            // Reset current connections, if exist
            DisconnectAllEndpoints();

            try
            {
                if (capabilities.HasFlag(Capabilities.HeadTracking))
                {
                    var endpointStatus = status.Endpoints.FirstOrDefault(x => x.Name == EndpointNames.HeadTracking);
                    if (endpointStatus == null || endpointStatus.Code != (int)ControlResponseCode.OK)
                    {
                        return(false);
                    }

                    head = new HeadRemote(api.CreateProxy <HeadTrackingProxy>());
                }

                if (capabilities.HasFlag(Capabilities.Controllers))
                {
                    var endpointStatus = status.Endpoints.FirstOrDefault(x => x.Name == EndpointNames.Controller);
                    if (endpointStatus == null || endpointStatus.Code != (int)ControlResponseCode.OK)
                    {
                        return(false);
                    }

                    controller = new ControllerRemote(api.CreateProxy <ControllerProxy>());
                }

                // Subscribe to haptic pulse broadcasts, if controller proxy is in use
                if (controller != null)
                {
                    broadcasts = api.CreateProxy <BroadcastProxy>();

                    // Forward the events to long-lived event so API user doesn't
                    // have to resubscribe on reconnect
                    broadcasts.HapticPulseReceived += (s, e) => HapticPulse?.Invoke(this, e);
                }

                return(true);
            }
            catch (Exception x)
            {
                Logger.Error("Error during API connection: " + x);

                // Cleanup possibly connected endpoints
                DisconnectAllEndpoints();
            }

            return(false);
        }
        /// <summary>
        /// Perform a haptic feedback pulse
        /// </summary>
        /// <param name="user">The functionality user</param>
        /// <param name="node">Node on which to control the pulse</param>
        /// <param name="hapticPulse">Haptic pulse to perform</param>
        /// <param name="durationMultiplier">(Optional) Multiplier value applied to the hapticPulse duration</param>
        /// <param name="intensityMultiplier">(Optional) Multiplier value applied to the hapticPulse intensity</param>
        public static void Pulse(this IUsesControlHaptics user, Node node, HapticPulse hapticPulse, float durationMultiplier = 1f, float intensityMultiplier = 1f)
        {
#if !FI_AUTOFILL
            user.provider.Pulse(node, hapticPulse, durationMultiplier, intensityMultiplier);
#endif
        }
示例#5
0
        /// <summary>
        /// Pulse haptic feedback
        /// </summary>
        /// <param name="node">Node on which to perform the pulse.</param>
        /// <param name="hapticPulse">Haptic pulse</param>
        /// <param name="durationMultiplier">(Optional) Multiplier value applied to the hapticPulse duration</param>
        /// <param name="intensityMultiplier">(Optional) Multiplier value applied to the hapticPulse intensity</param>
        public void Pulse(Node node, HapticPulse hapticPulse, float durationMultiplier = 1f, float intensityMultiplier = 1f)
        {
            // Clip buffer can hold up to 800 milliseconds of samples
            // At 320Hz, each sample is 3.125f milliseconds
            if (Mathf.Approximately(m_MasterIntensity, 0))
            {
                return;
            }

#if ENABLE_OVR_INPUT
            m_GeneratedHapticClip.Reset();

            var duration  = hapticPulse.duration * durationMultiplier;
            var intensity = hapticPulse.intensity * intensityMultiplier;
            var fadeIn    = hapticPulse.fadeIn;
            var fadeOut   = hapticPulse.fadeOut;
            if (duration > MaxDuration)
            {
                duration = Mathf.Clamp(duration, 0f, MaxDuration); // Clamp at maximum 800ms for sample buffer

                if (!m_SampleLengthWarningShown)
                {
                    Debug.LogWarning("Pulse durations greater than 0.8f are not currently supported");
                }

                m_SampleLengthWarningShown = true;
            }

            const int   kSampleRateConversion        = 490; // Samplerate conversion : 44100/90fps = 490
            const int   kIntensityIncreaseMultiplier = 255; // Maximum value of 255 for intensity
            const float kFadeInProportion            = 0.25f;
            var         fadeInSampleCount            = duration * kSampleRateConversion * kFadeInProportion;
            var         fadeOutSampleCount           = fadeInSampleCount * 2; // FadeOut is less apparent than FadeIn unless FadeOut duration is increased
            duration *= kSampleRateConversion;
            var durationFadeOutPosition = duration - fadeOutSampleCount;
            intensity = Mathf.Clamp(Mathf.Clamp01(intensity) * kIntensityIncreaseMultiplier * m_MasterIntensity, 0, kIntensityIncreaseMultiplier);
            var hapticClipSample = Convert.ToByte(intensity);
            for (int i = 1; i < duration; ++i)
            {
                float sampleShaped = hapticClipSample;
                if (fadeIn && i < fadeInSampleCount)
                {
                    sampleShaped = Mathf.Lerp(0, intensity, i / fadeInSampleCount);
                }
                else if (fadeOut && i > durationFadeOutPosition)
                {
                    sampleShaped = Mathf.Lerp(0, intensity, (duration - i) / fadeOutSampleCount);
                }

                m_GeneratedHapticClip.WriteSample(Convert.ToByte(sampleShaped));
            }

            const float kMaxSimultaneousClipDuration = 0.25f;
            var         channel = GetTargetChannel(node);
            if (duration > kMaxSimultaneousClipDuration)
            {
                // Prevent multiple long clips from playing back simultaneously
                // If the new clip has a long duration, stop playback of any existing clips in order to prevent haptic feedback noise
                if (channel != null)
                {
                    channel.Preempt(m_GeneratedHapticClip);
                }
                else
                {
                    m_RHapticsChannel.Preempt(m_GeneratedHapticClip);
                    m_LHapticsChannel.Preempt(m_GeneratedHapticClip);
                }
            }
            else
            {
                // Allow multiple short clips to play simultaneously
                if (channel != null)
                {
                    channel.Mix(m_GeneratedHapticClip);
                }
                else
                {
                    m_RHapticsChannel.Mix(m_GeneratedHapticClip);
                    m_LHapticsChannel.Mix(m_GeneratedHapticClip);
                }
            }
#endif
        }
示例#6
0
        /// <summary>
        /// Pulse haptic feedback
        /// </summary>
        /// <param name="node">Node on which to perform the pulse.</param>
        /// <param name="hapticPulse">Haptic pulse</param>
        /// <param name="durationMultiplier">(Optional) Multiplier value applied to the hapticPulse duration</param>
        /// <param name="intensityMultiplier">(Optional) Multiplier value applied to the hapticPulse intensity</param>
        public void Pulse(Node node, HapticPulse hapticPulse, float durationMultiplier = 1f, float intensityMultiplier = 1f)
        {
            // Clip buffer can hold up to 800 milliseconds of samples
            // At 320Hz, each sample is 3.125f milliseconds
            if (Mathf.Approximately(m_MasterIntensity, 0))
            {
                return;
            }

            // Reset buffer
            m_GeneratedHapticClip.Seek(0, SeekOrigin.Begin);
            m_GeneratedHapticClip.SetLength(0);

            var duration  = hapticPulse.duration * durationMultiplier;
            var intensity = hapticPulse.intensity * intensityMultiplier;
            var fadeIn    = hapticPulse.fadeIn;
            var fadeOut   = hapticPulse.fadeOut;

            if (duration > MaxDuration)
            {
                duration = Mathf.Clamp(duration, 0f, MaxDuration); // Clamp at maximum 800ms for sample buffer

                if (!m_SampleLengthWarningShown)
                {
                    Debug.LogWarning("Pulse durations greater than 0.8f are not currently supported");
                }

                m_SampleLengthWarningShown = true;
            }

            const int   kSampleRateConversion        = 490; // Samplerate conversion : 44100/90fps = 490
            const int   kIntensityIncreaseMultiplier = 255; // Maximum value of 255 for intensity
            const float kFadeInProportion            = 0.25f;
            var         fadeInSampleCount            = duration * kSampleRateConversion * kFadeInProportion;
            var         fadeOutSampleCount           = fadeInSampleCount * 2; // FadeOut is less apparent than FadeIn unless FadeOut duration is increased

            duration *= kSampleRateConversion;
            var durationFadeOutPosition = duration - fadeOutSampleCount;

            intensity = Mathf.Clamp(Mathf.Clamp01(intensity) * kIntensityIncreaseMultiplier * m_MasterIntensity, 0, kIntensityIncreaseMultiplier);
            var hapticClipSample = Convert.ToByte(intensity);

            for (int i = 1; i < duration; ++i)
            {
                float sampleShaped = hapticClipSample;
                if (fadeIn && i < fadeInSampleCount)
                {
                    sampleShaped = Mathf.Lerp(0, intensity, i / fadeInSampleCount);
                }
                else if (fadeOut && i > durationFadeOutPosition)
                {
                    sampleShaped = Mathf.Lerp(0, intensity, (duration - i) / fadeOutSampleCount);
                }

                var sampleByte = Convert.ToByte(sampleShaped);
                m_GeneratedHapticClip.WriteByte(sampleByte);
            }

            const float kMaxSimultaneousClipDuration = 0.25f;
            var         channel = GetTargetChannel(node);

            if (duration > kMaxSimultaneousClipDuration)
            {
                // Prevent multiple long clips from playing back simultaneously
                // If the new clip has a long duration, stop playback of any existing clips in order to prevent haptic feedback noise
                var buffer = m_GeneratedHapticClip.GetBuffer();
                if (node == Node.None)
                {
                    StopPulses();
                    if (m_Capabilites.supportsBuffer)
                    {
                        m_LeftHand.SendHapticBuffer(0, buffer);
                        m_RightHand.SendHapticBuffer(0, buffer);
                    }
                    else
                    {
                        m_LeftHand.SendHapticImpulse(0, intensity, duration);
                        m_RightHand.SendHapticImpulse(0, intensity, duration);
                    }
                }
                else
                {
                    StopPulses(node);
                    if (m_Capabilites.supportsBuffer)
                    {
                        channel.SendHapticBuffer(0, buffer);
                    }
                    else
                    {
                        channel.SendHapticImpulse(0, intensity, duration);
                    }
                }
            }
        }