using System; using System.Collections; using Leap.Unity.Attributes; using UnityEngine; using UnityEngine.Serialization; namespace Leap.Unity { [RequireComponent(typeof(Camera))] public class LeapImageRetriever : MonoBehaviour { public LeapImageRetriever.EyeTextureData TextureData { get { return this._eyeTextureData; } } private void Start() { if (this._provider == null) { Debug.LogWarning("Cannot use LeapImageRetriever if there is no LeapProvider!"); base.enabled = false; return; } this.ApplyGammaCorrectionValues(); this.ApplyCameraProjectionValues(base.GetComponent()); } private void OnEnable() { Controller leapController = this._provider.GetLeapController(); if (leapController != null) { this.onController(leapController); } else { base.StartCoroutine(this.waitForController()); } LeapVRCameraControl.OnLeftPreRender += this.ApplyCameraProjectionValues; LeapVRCameraControl.OnRightPreRender += this.ApplyCameraProjectionValues; } private void OnDisable() { base.StopAllCoroutines(); Controller leapController = this._provider.GetLeapController(); if (leapController != null) { this._provider.GetLeapController().DistortionChange -= new EventHandler(this.onDistortionChange); } LeapVRCameraControl.OnLeftPreRender -= this.ApplyCameraProjectionValues; LeapVRCameraControl.OnRightPreRender -= this.ApplyCameraProjectionValues; } private void OnDestroy() { base.StopAllCoroutines(); Controller leapController = this._provider.GetLeapController(); if (leapController != null) { this._provider.GetLeapController().DistortionChange -= new EventHandler(this.onDistortionChange); } } private void OnPreRender() { if (this.imagesEnabled) { Controller leapController = this._provider.GetLeapController(); long num = leapController.Now(); while (!this._requestedImage.IsComplete) { if (leapController.Now() - num > this.ImageTimeout) { break; } } if (this._requestedImage.IsComplete) { if (this._eyeTextureData.CheckStale(this._requestedImage, this._requestedImage)) { this._eyeTextureData.Reconstruct(this._requestedImage, this._requestedImage); } this._eyeTextureData.UpdateTextures(this._requestedImage, this._requestedImage); } else if (!this.checkingImageState) { base.StartCoroutine(this.checkImageMode()); } } } private void Update() { if (this.imagesEnabled) { Frame currentFrame = this._provider.CurrentFrame; Controller leapController = this._provider.GetLeapController(); this._requestedImage = leapController.RequestImages(currentFrame.Id, Image.ImageType.DEFAULT); } else if (!this.checkingImageState) { base.StartCoroutine(this.checkImageMode()); } } private IEnumerator waitForController() { Controller controller = null; do { controller = this._provider.GetLeapController(); yield return null; } while (controller == null); this.onController(controller); yield break; } private IEnumerator checkImageMode() { this.checkingImageState = true; yield return new WaitForSeconds(2f); this._provider.GetLeapController().Config.Get("images_mode", delegate(int enabled) { this.$this.imagesEnabled = (enabled != 0); this.$this.checkingImageState = false; }); yield break; } private void onController(Controller controller) { controller.DistortionChange += new EventHandler(this.onDistortionChange); controller.Connect += delegate { this._provider.GetLeapController().Config.Get("images_mode", delegate(int enabled) { this.imagesEnabled = (enabled != 0); }); }; if (!this.checkingImageState) { base.StartCoroutine(this.checkImageMode()); } } public void ApplyGammaCorrectionValues() { float value = 1f; if (QualitySettings.activeColorSpace != ColorSpace.Linear) { value = -Mathf.Log10(Mathf.GammaToLinearSpace(0.1f)); } Shader.SetGlobalFloat("_LeapGlobalColorSpaceGamma", value); Shader.SetGlobalFloat("_LeapGlobalGammaCorrectionExponent", 1f / this._gammaCorrection); } public void ApplyCameraProjectionValues(Camera camera) { Shader.SetGlobalVector("_LeapGlobalProjection", new Vector4 { x = camera.projectionMatrix[0, 2], y = 0f, z = camera.projectionMatrix[0, 0], w = camera.projectionMatrix[1, 1] }); } private void onDistortionChange(object sender, LeapEventArgs args) { this._eyeTextureData.MarkStale(); } public const string GLOBAL_COLOR_SPACE_GAMMA_NAME = "_LeapGlobalColorSpaceGamma"; public const string GLOBAL_GAMMA_CORRECTION_EXPONENT_NAME = "_LeapGlobalGammaCorrectionExponent"; public const string GLOBAL_CAMERA_PROJECTION_NAME = "_LeapGlobalProjection"; public const int IMAGE_WARNING_WAIT = 10; public const int LEFT_IMAGE_INDEX = 0; public const int RIGHT_IMAGE_INDEX = 1; public const float IMAGE_SETTING_POLL_RATE = 2f; [AutoFind(AutoFindLocations.All)] [SerializeField] private LeapServiceProvider _provider; [SerializeField] [FormerlySerializedAs("gammaCorrection")] private float _gammaCorrection = 1f; [MinValue(0f)] [SerializeField] protected long ImageTimeout = 9000L; private LeapImageRetriever.EyeTextureData _eyeTextureData = new LeapImageRetriever.EyeTextureData(); protected Image _requestedImage = new Image(); protected bool imagesEnabled = true; private bool checkingImageState; public class LeapTextureData { public Texture2D CombinedTexture { get { return this._combinedTexture; } } public bool CheckStale(Image image) { return this._combinedTexture == null || this._intermediateArray == null || (image.Width != this._combinedTexture.width || image.Height * 2 != this._combinedTexture.height) || this._combinedTexture.format != this.getTextureFormat(image); } public void Reconstruct(Image image, string globalShaderName, string pixelSizeName) { int width = image.Width; int num = image.Height * 2; TextureFormat textureFormat = this.getTextureFormat(image); if (this._combinedTexture != null) { UnityEngine.Object.DestroyImmediate(this._combinedTexture); } this._combinedTexture = new Texture2D(width, num, textureFormat, false, true); this._combinedTexture.wrapMode = TextureWrapMode.Clamp; this._combinedTexture.filterMode = FilterMode.Bilinear; this._combinedTexture.name = globalShaderName; this._combinedTexture.hideFlags = HideFlags.DontSave; this._intermediateArray = new byte[width * num * this.bytesPerPixel(textureFormat)]; Shader.SetGlobalTexture(globalShaderName, this._combinedTexture); Shader.SetGlobalVector(pixelSizeName, new Vector2(1f / (float)image.Width, 1f / (float)image.Height)); } public void UpdateTexture(Image image) { Array.Copy(image.Data, 0, this._intermediateArray, 0, this._intermediateArray.Length); this._combinedTexture.LoadRawTextureData(this._intermediateArray); this._combinedTexture.Apply(); } private TextureFormat getTextureFormat(Image image) { switch (image.Format) { case Image.FormatType.INFRARED: return TextureFormat.Alpha8; case Image.FormatType.IBRG: case (Image.FormatType)4: return TextureFormat.RGBA32; } throw new Exception("Unexpected image format " + image.Format + "!"); } private int bytesPerPixel(TextureFormat format) { switch (format) { case TextureFormat.Alpha8: return 1; default: if (format != TextureFormat.BGRA32) { throw new Exception("Unexpected texture format " + format); } break; case TextureFormat.RGBA32: case TextureFormat.ARGB32: break; } return 4; } private Texture2D _combinedTexture; private byte[] _intermediateArray; } public class LeapDistortionData { public Texture2D CombinedTexture { get { return this._combinedTexture; } } public bool CheckStale() { return this._combinedTexture == null; } public void Reconstruct(Image image, string shaderName) { int num = image.DistortionWidth / 2; int num2 = image.DistortionHeight * 2; if (this._combinedTexture != null) { UnityEngine.Object.DestroyImmediate(this._combinedTexture); } Color32[] array = new Color32[num * num2]; this._combinedTexture = new Texture2D(num, num2, TextureFormat.RGBA32, false, true); this._combinedTexture.filterMode = FilterMode.Bilinear; this._combinedTexture.wrapMode = TextureWrapMode.Clamp; this._combinedTexture.hideFlags = HideFlags.DontSave; this.addDistortionData(image, array, 0); this._combinedTexture.SetPixels32(array); this._combinedTexture.Apply(); Shader.SetGlobalTexture(shaderName, this._combinedTexture); } private void addDistortionData(Image image, Color32[] colors, int startIndex) { float[] distortion = image.Distortion; for (int i = 0; i < distortion.Length; i += 2) { byte r; byte g; this.encodeFloat(distortion[i], out r, out g); byte b; byte a; this.encodeFloat(distortion[i + 1], out b, out a); colors[i / 2 + startIndex] = new Color32(r, g, b, a); } } private void encodeFloat(float value, out byte byte0, out byte byte1) { value = (value + 0.6f) / 2.3f; float num = value; float num2 = value * 255f; num -= (float)((int)num); num2 -= (float)((int)num2); num -= 0.003921569f * num2; byte0 = (byte)(num * 256f); byte1 = (byte)(num2 * 256f); } private Texture2D _combinedTexture; } public class EyeTextureData { public EyeTextureData() { this.BrightTexture = new LeapImageRetriever.LeapTextureData(); this.RawTexture = new LeapImageRetriever.LeapTextureData(); this.Distortion = new LeapImageRetriever.LeapDistortionData(); } public static void ResetGlobalShaderValues() { Texture2D texture2D = new Texture2D(1, 1, TextureFormat.ARGB32, false, false); texture2D.name = "EmptyTexture"; texture2D.hideFlags = HideFlags.DontSave; texture2D.SetPixel(0, 0, new Color(0f, 0f, 0f, 0f)); Shader.SetGlobalTexture("_LeapGlobalBrightnessTexture", texture2D); Shader.SetGlobalTexture("_LeapGlobalRawTexture", texture2D); Shader.SetGlobalTexture("_LeapGlobalDistortion", texture2D); } public bool CheckStale(Image bright, Image raw) { return this.BrightTexture.CheckStale(bright) || this.RawTexture.CheckStale(raw) || this.Distortion.CheckStale() || this._isStale; } public void MarkStale() { this._isStale = true; } public void Reconstruct(Image bright, Image raw) { this.BrightTexture.Reconstruct(bright, "_LeapGlobalBrightnessTexture", "_LeapGlobalBrightnessPixelSize"); this.RawTexture.Reconstruct(raw, "_LeapGlobalRawTexture", "_LeapGlobalRawPixelSize"); this.Distortion.Reconstruct(raw, "_LeapGlobalDistortion"); Image.FormatType format = raw.Format; if (format != Image.FormatType.INFRARED) { if (format != (Image.FormatType)4) { Debug.LogWarning("Unexpected format type " + raw.Format); } else { Shader.DisableKeyword("LEAP_FORMAT_IR"); Shader.EnableKeyword("LEAP_FORMAT_RGB"); } } else { Shader.DisableKeyword("LEAP_FORMAT_RGB"); Shader.EnableKeyword("LEAP_FORMAT_IR"); } this._isStale = false; } public void UpdateTextures(Image bright, Image raw) { this.BrightTexture.UpdateTexture(bright); this.RawTexture.UpdateTexture(raw); } private const string IR_SHADER_VARIANT_NAME = "LEAP_FORMAT_IR"; private const string RGB_SHADER_VARIANT_NAME = "LEAP_FORMAT_RGB"; private const string GLOBAL_BRIGHT_TEXTURE_NAME = "_LeapGlobalBrightnessTexture"; private const string GLOBAL_RAW_TEXTURE_NAME = "_LeapGlobalRawTexture"; private const string GLOBAL_DISTORTION_TEXTURE_NAME = "_LeapGlobalDistortion"; private const string GLOBAL_BRIGHT_PIXEL_SIZE_NAME = "_LeapGlobalBrightnessPixelSize"; private const string GLOBAL_RAW_PIXEL_SIZE_NAME = "_LeapGlobalRawPixelSize"; public readonly LeapImageRetriever.LeapTextureData BrightTexture; public readonly LeapImageRetriever.LeapTextureData RawTexture; public readonly LeapImageRetriever.LeapDistortionData Distortion; private bool _isStale; } } }