using System; using System.Collections.Generic; using System.Runtime.InteropServices; using UnityEngine; public static class OVRHaptics { static OVRHaptics() { OVRHaptics.Config.Load(); OVRHaptics.m_outputs = new OVRHaptics.OVRHapticsOutput[] { new OVRHaptics.OVRHapticsOutput(1U), new OVRHaptics.OVRHapticsOutput(2U) }; OVRHaptics.Channels = new OVRHaptics.OVRHapticsChannel[] { OVRHaptics.LeftChannel = new OVRHaptics.OVRHapticsChannel(0U), OVRHaptics.RightChannel = new OVRHaptics.OVRHapticsChannel(1U) }; } public static void Process() { OVRHaptics.Config.Load(); for (int i = 0; i < OVRHaptics.m_outputs.Length; i++) { OVRHaptics.m_outputs[i].Process(); } } public static readonly OVRHaptics.OVRHapticsChannel[] Channels; public static readonly OVRHaptics.OVRHapticsChannel LeftChannel; public static readonly OVRHaptics.OVRHapticsChannel RightChannel; private static readonly OVRHaptics.OVRHapticsOutput[] m_outputs; public static class Config { static Config() { OVRHaptics.Config.Load(); } public static int SampleRateHz { get; private set; } public static int SampleSizeInBytes { get; private set; } public static int MinimumSafeSamplesQueued { get; private set; } public static int MinimumBufferSamplesCount { get; private set; } public static int OptimalBufferSamplesCount { get; private set; } public static int MaximumBufferSamplesCount { get; private set; } public static void Load() { OVRPlugin.HapticsDesc controllerHapticsDesc = OVRPlugin.GetControllerHapticsDesc(2U); OVRHaptics.Config.SampleRateHz = controllerHapticsDesc.SampleRateHz; OVRHaptics.Config.SampleSizeInBytes = controllerHapticsDesc.SampleSizeInBytes; OVRHaptics.Config.MinimumSafeSamplesQueued = controllerHapticsDesc.MinimumSafeSamplesQueued; OVRHaptics.Config.MinimumBufferSamplesCount = controllerHapticsDesc.MinimumBufferSamplesCount; OVRHaptics.Config.OptimalBufferSamplesCount = controllerHapticsDesc.OptimalBufferSamplesCount; OVRHaptics.Config.MaximumBufferSamplesCount = controllerHapticsDesc.MaximumBufferSamplesCount; } } public class OVRHapticsChannel { public OVRHapticsChannel(uint outputIndex) { this.m_output = OVRHaptics.m_outputs[(int)((UIntPtr)outputIndex)]; } public void Preempt(OVRHapticsClip clip) { this.m_output.Preempt(clip); } public void Queue(OVRHapticsClip clip) { this.m_output.Queue(clip); } public void Mix(OVRHapticsClip clip) { this.m_output.Mix(clip); } public void Clear() { this.m_output.Clear(); } private OVRHaptics.OVRHapticsOutput m_output; } private class OVRHapticsOutput { public OVRHapticsOutput(uint controller) { this.m_controller = controller; } public void Process() { OVRPlugin.HapticsState controllerHapticsState = OVRPlugin.GetControllerHapticsState(this.m_controller); float num = Time.realtimeSinceStartup - this.m_prevSamplesQueuedTime; if (this.m_prevSamplesQueued > 0) { int num2 = this.m_prevSamplesQueued - (int)(num * (float)OVRHaptics.Config.SampleRateHz + 0.5f); if (num2 < 0) { num2 = 0; } if (controllerHapticsState.SamplesQueued - num2 == 0) { this.m_numPredictionHits++; } else { this.m_numPredictionMisses++; } if (num2 > 0 && controllerHapticsState.SamplesQueued == 0) { this.m_numUnderruns++; } this.m_prevSamplesQueued = controllerHapticsState.SamplesQueued; this.m_prevSamplesQueuedTime = Time.realtimeSinceStartup; } int num3 = OVRHaptics.Config.OptimalBufferSamplesCount; if (this.m_lowLatencyMode) { float num4 = 1000f / (float)OVRHaptics.Config.SampleRateHz; float num5 = num * 1000f; int num6 = (int)Mathf.Ceil(num5 / num4); int num7 = OVRHaptics.Config.MinimumSafeSamplesQueued + num6; if (num7 < num3) { num3 = num7; } } if (controllerHapticsState.SamplesQueued > num3) { return; } if (num3 > OVRHaptics.Config.MaximumBufferSamplesCount) { num3 = OVRHaptics.Config.MaximumBufferSamplesCount; } if (num3 > controllerHapticsState.SamplesAvailable) { num3 = controllerHapticsState.SamplesAvailable; } int num8 = 0; int num9 = 0; while (num8 < num3 && num9 < this.m_pendingClips.Count) { int num10 = num3 - num8; int num11 = this.m_pendingClips[num9].Clip.Count - this.m_pendingClips[num9].ReadCount; if (num10 > num11) { num10 = num11; } if (num10 > 0) { int length = num10 * OVRHaptics.Config.SampleSizeInBytes; int byteOffset = num8 * OVRHaptics.Config.SampleSizeInBytes; int startIndex = this.m_pendingClips[num9].ReadCount * OVRHaptics.Config.SampleSizeInBytes; Marshal.Copy(this.m_pendingClips[num9].Clip.Samples, startIndex, this.m_nativeBuffer.GetPointer(byteOffset), length); this.m_pendingClips[num9].ReadCount += num10; num8 += num10; } num9++; } int num12 = this.m_pendingClips.Count - 1; while (num12 >= 0 && this.m_pendingClips.Count > 0) { if (this.m_pendingClips[num12].ReadCount >= this.m_pendingClips[num12].Clip.Count) { this.m_pendingClips.RemoveAt(num12); } num12--; } int num13 = num3 - (controllerHapticsState.SamplesQueued + num8); if (num13 < OVRHaptics.Config.MinimumBufferSamplesCount - num8) { num13 = OVRHaptics.Config.MinimumBufferSamplesCount - num8; } if (num13 > controllerHapticsState.SamplesAvailable) { num13 = controllerHapticsState.SamplesAvailable; } if (num13 > 0) { int length2 = num13 * OVRHaptics.Config.SampleSizeInBytes; int byteOffset2 = num8 * OVRHaptics.Config.SampleSizeInBytes; int startIndex2 = 0; Marshal.Copy(this.m_paddingClip.Samples, startIndex2, this.m_nativeBuffer.GetPointer(byteOffset2), length2); num8 += num13; } if (num8 > 0) { OVRPlugin.HapticsBuffer hapticsBuffer; hapticsBuffer.Samples = this.m_nativeBuffer.GetPointer(0); hapticsBuffer.SamplesCount = num8; OVRPlugin.SetControllerHaptics(this.m_controller, hapticsBuffer); this.m_prevSamplesQueued = OVRPlugin.GetControllerHapticsState(this.m_controller).SamplesQueued; this.m_prevSamplesQueuedTime = Time.realtimeSinceStartup; } } public void Preempt(OVRHapticsClip clip) { this.m_pendingClips.Clear(); this.m_pendingClips.Add(new OVRHaptics.OVRHapticsOutput.ClipPlaybackTracker(clip)); } public void Queue(OVRHapticsClip clip) { this.m_pendingClips.Add(new OVRHaptics.OVRHapticsOutput.ClipPlaybackTracker(clip)); } public void Mix(OVRHapticsClip clip) { int num = 0; int num2 = 0; int num3 = clip.Count; while (num3 > 0 && num < this.m_pendingClips.Count) { int num4 = this.m_pendingClips[num].Clip.Count - this.m_pendingClips[num].ReadCount; num3 -= num4; num2 += num4; num++; } if (num3 > 0) { num2 += num3; } if (num > 0) { OVRHapticsClip ovrhapticsClip = new OVRHapticsClip(num2); int i = 0; for (int j = 0; j < num; j++) { OVRHapticsClip clip2 = this.m_pendingClips[j].Clip; for (int k = this.m_pendingClips[j].ReadCount; k < clip2.Count; k++) { if (OVRHaptics.Config.SampleSizeInBytes == 1) { byte sample = 0; if (i < clip.Count && k < clip2.Count) { sample = (byte)Mathf.Clamp((int)(clip.Samples[i] + clip2.Samples[k]), 0, 255); i++; } else if (k < clip2.Count) { sample = clip2.Samples[k]; } ovrhapticsClip.WriteSample(sample); } } } while (i < clip.Count) { if (OVRHaptics.Config.SampleSizeInBytes == 1) { ovrhapticsClip.WriteSample(clip.Samples[i]); } i++; } this.m_pendingClips[0] = new OVRHaptics.OVRHapticsOutput.ClipPlaybackTracker(ovrhapticsClip); for (int l = 1; l < num; l++) { this.m_pendingClips.RemoveAt(1); } } else { this.m_pendingClips.Add(new OVRHaptics.OVRHapticsOutput.ClipPlaybackTracker(clip)); } } public void Clear() { this.m_pendingClips.Clear(); } private bool m_lowLatencyMode = true; private int m_prevSamplesQueued; private float m_prevSamplesQueuedTime; private int m_numPredictionHits; private int m_numPredictionMisses; private int m_numUnderruns; private List m_pendingClips = new List(); private uint m_controller; private OVRNativeBuffer m_nativeBuffer = new OVRNativeBuffer(OVRHaptics.Config.MaximumBufferSamplesCount * OVRHaptics.Config.SampleSizeInBytes); private OVRHapticsClip m_paddingClip = new OVRHapticsClip(); private class ClipPlaybackTracker { public ClipPlaybackTracker(OVRHapticsClip clip) { this.Clip = clip; } public int ReadCount { get; set; } public OVRHapticsClip Clip { get; set; } } } }