| using UnityEditorInternal; | 
| using UnityEngine; | 
| using UnityEngine.PostProcessing; | 
|   | 
| namespace UnityEditor.PostProcessing | 
| { | 
|     public class VectorscopeMonitor : PostProcessingMonitor | 
|     { | 
|         static GUIContent s_MonitorTitle = new GUIContent("Vectorscope"); | 
|   | 
|         ComputeShader m_ComputeShader; | 
|         ComputeBuffer m_Buffer; | 
|         Material m_Material; | 
|         RenderTexture m_VectorscopeTexture; | 
|         Rect m_MonitorAreaRect; | 
|   | 
|         public VectorscopeMonitor() | 
|         { | 
|             m_ComputeShader = EditorResources.Load<ComputeShader>("Monitors/VectorscopeCompute.compute"); | 
|         } | 
|   | 
|         public override void Dispose() | 
|         { | 
|             GraphicsUtils.Destroy(m_Material); | 
|             GraphicsUtils.Destroy(m_VectorscopeTexture); | 
|   | 
|             if (m_Buffer != null) | 
|                 m_Buffer.Release(); | 
|   | 
|             m_Material = null; | 
|             m_VectorscopeTexture = null; | 
|             m_Buffer = null; | 
|         } | 
|   | 
|         public override bool IsSupported() | 
|         { | 
|             return m_ComputeShader != null && GraphicsUtils.supportsDX11; | 
|         } | 
|   | 
|         public override GUIContent GetMonitorTitle() | 
|         { | 
|             return s_MonitorTitle; | 
|         } | 
|   | 
|         public override void OnMonitorSettings() | 
|         { | 
|             EditorGUI.BeginChangeCheck(); | 
|   | 
|             bool refreshOnPlay = m_MonitorSettings.refreshOnPlay; | 
|             float exposure = m_MonitorSettings.vectorscopeExposure; | 
|             bool showBackground = m_MonitorSettings.vectorscopeShowBackground; | 
|   | 
|             refreshOnPlay = GUILayout.Toggle(refreshOnPlay, new GUIContent(FxStyles.playIcon, "Keep refreshing the vectorscope in play mode; this may impact performances."), FxStyles.preButton); | 
|             exposure = GUILayout.HorizontalSlider(exposure, 0.05f, 0.3f, FxStyles.preSlider, FxStyles.preSliderThumb, GUILayout.Width(40f)); | 
|             showBackground = GUILayout.Toggle(showBackground, new GUIContent(FxStyles.checkerIcon, "Show an YUV background in the vectorscope."), FxStyles.preButton); | 
|   | 
|             if (EditorGUI.EndChangeCheck()) | 
|             { | 
|                 Undo.RecordObject(m_BaseEditor.serializedObject.targetObject, "Vectorscope Settings Changed"); | 
|                 m_MonitorSettings.refreshOnPlay = refreshOnPlay; | 
|                 m_MonitorSettings.vectorscopeExposure = exposure; | 
|                 m_MonitorSettings.vectorscopeShowBackground = showBackground; | 
|                 InternalEditorUtility.RepaintAllViews(); | 
|             } | 
|         } | 
|   | 
|         public override void OnMonitorGUI(Rect r) | 
|         { | 
|             if (Event.current.type == EventType.Repaint) | 
|             { | 
|                 // If m_MonitorAreaRect isn't set the preview was just opened so refresh the render to get the vectoscope data | 
|                 if (Mathf.Approximately(m_MonitorAreaRect.width, 0) && Mathf.Approximately(m_MonitorAreaRect.height, 0)) | 
|                     InternalEditorUtility.RepaintAllViews(); | 
|   | 
|                 // Sizing | 
|                 float size = 0f; | 
|   | 
|                 if (r.width < r.height) | 
|                 { | 
|                     size = m_VectorscopeTexture != null | 
|                         ? Mathf.Min(m_VectorscopeTexture.width, r.width - 35f) | 
|                         : r.width; | 
|                 } | 
|                 else | 
|                 { | 
|                     size = m_VectorscopeTexture != null | 
|                         ? Mathf.Min(m_VectorscopeTexture.height, r.height - 25f) | 
|                         : r.height; | 
|                 } | 
|   | 
|                 m_MonitorAreaRect = new Rect( | 
|                         Mathf.Floor(r.x + r.width / 2f - size / 2f), | 
|                         Mathf.Floor(r.y + r.height / 2f - size / 2f - 5f), | 
|                         size, size | 
|                         ); | 
|   | 
|                 if (m_VectorscopeTexture != null) | 
|                 { | 
|                     m_Material.SetFloat("_Exposure", m_MonitorSettings.vectorscopeExposure); | 
|   | 
|                     var oldActive = RenderTexture.active; | 
|                     Graphics.Blit(null, m_VectorscopeTexture, m_Material, m_MonitorSettings.vectorscopeShowBackground ? 0 : 1); | 
|                     RenderTexture.active = oldActive; | 
|   | 
|                     Graphics.DrawTexture(m_MonitorAreaRect, m_VectorscopeTexture); | 
|   | 
|                     var color = Color.white; | 
|                     const float kTickSize = 10f; | 
|                     const int kTickCount = 24; | 
|   | 
|                     float radius = m_MonitorAreaRect.width / 2f; | 
|                     float midX = m_MonitorAreaRect.x + radius; | 
|                     float midY = m_MonitorAreaRect.y + radius; | 
|                     var center = new Vector2(midX, midY); | 
|   | 
|                     // Cross | 
|                     color.a *= 0.5f; | 
|                     Handles.color = color; | 
|                     Handles.DrawLine(new Vector2(midX, m_MonitorAreaRect.y), new Vector2(midX, m_MonitorAreaRect.y + m_MonitorAreaRect.height)); | 
|                     Handles.DrawLine(new Vector2(m_MonitorAreaRect.x, midY), new Vector2(m_MonitorAreaRect.x + m_MonitorAreaRect.width, midY)); | 
|   | 
|                     if (m_MonitorAreaRect.width > 100f) | 
|                     { | 
|                         color.a = 1f; | 
|   | 
|                         // Ticks | 
|                         Handles.color = color; | 
|                         for (int i = 0; i < kTickCount; i++) | 
|                         { | 
|                             float a = (float)i / (float)kTickCount; | 
|                             float theta = a * (Mathf.PI * 2f); | 
|                             float tx = Mathf.Cos(theta + (Mathf.PI / 2f)); | 
|                             float ty = Mathf.Sin(theta - (Mathf.PI / 2f)); | 
|                             var innerVec = center + new Vector2(tx, ty) * (radius - kTickSize); | 
|                             var outerVec = center + new Vector2(tx, ty) * radius; | 
|                             Handles.DrawAAPolyLine(3f, innerVec, outerVec); | 
|                         } | 
|   | 
|                         // Labels (where saturation reaches 75%) | 
|                         color.a = 1f; | 
|                         var oldColor = GUI.color; | 
|                         GUI.color = color * 2f; | 
|   | 
|                         var point = new Vector2(-0.254f, -0.750f) * radius + center; | 
|                         var rect = new Rect(point.x - 10f, point.y - 10f, 20f, 20f); | 
|                         GUI.Label(rect, "[R]", FxStyles.tickStyleCenter); | 
|   | 
|                         point = new Vector2(-0.497f, 0.629f) * radius + center; | 
|                         rect = new Rect(point.x - 10f, point.y - 10f, 20f, 20f); | 
|                         GUI.Label(rect, "[G]", FxStyles.tickStyleCenter); | 
|   | 
|                         point = new Vector2(0.750f, 0.122f) * radius + center; | 
|                         rect = new Rect(point.x - 10f, point.y - 10f, 20f, 20f); | 
|                         GUI.Label(rect, "[B]", FxStyles.tickStyleCenter); | 
|   | 
|                         point = new Vector2(-0.750f, -0.122f) * radius + center; | 
|                         rect = new Rect(point.x - 10f, point.y - 10f, 20f, 20f); | 
|                         GUI.Label(rect, "[Y]", FxStyles.tickStyleCenter); | 
|   | 
|                         point = new Vector2(0.254f, 0.750f) * radius + center; | 
|                         rect = new Rect(point.x - 10f, point.y - 10f, 20f, 20f); | 
|                         GUI.Label(rect, "[C]", FxStyles.tickStyleCenter); | 
|   | 
|                         point = new Vector2(0.497f, -0.629f) * radius + center; | 
|                         rect = new Rect(point.x - 10f, point.y - 10f, 20f, 20f); | 
|                         GUI.Label(rect, "[M]", FxStyles.tickStyleCenter); | 
|                         GUI.color = oldColor; | 
|                     } | 
|                 } | 
|             } | 
|         } | 
|   | 
|         public override void OnFrameData(RenderTexture source) | 
|         { | 
|             if (Application.isPlaying && !m_MonitorSettings.refreshOnPlay) | 
|                 return; | 
|   | 
|             if (Mathf.Approximately(m_MonitorAreaRect.width, 0) || Mathf.Approximately(m_MonitorAreaRect.height, 0)) | 
|                 return; | 
|   | 
|             float ratio = (float)source.width / (float)source.height; | 
|             int h = 384; | 
|             int w = Mathf.FloorToInt(h * ratio); | 
|   | 
|             var rt = RenderTexture.GetTemporary(w, h, 0, source.format); | 
|             Graphics.Blit(source, rt); | 
|             ComputeVectorscope(rt); | 
|             m_BaseEditor.Repaint(); | 
|             RenderTexture.ReleaseTemporary(rt); | 
|         } | 
|   | 
|         void CreateBuffer(int width, int height) | 
|         { | 
|             m_Buffer = new ComputeBuffer(width * height, sizeof(uint)); | 
|         } | 
|   | 
|         void ComputeVectorscope(RenderTexture source) | 
|         { | 
|             if (m_Buffer == null) | 
|             { | 
|                 CreateBuffer(source.width, source.height); | 
|             } | 
|             else if (m_Buffer.count != (source.width * source.height)) | 
|             { | 
|                 m_Buffer.Release(); | 
|                 CreateBuffer(source.width, source.height); | 
|             } | 
|   | 
|             var cs = m_ComputeShader; | 
|   | 
|             int kernel = cs.FindKernel("KVectorscopeClear"); | 
|             cs.SetBuffer(kernel, "_Vectorscope", m_Buffer); | 
|             cs.SetVector("_Res", new Vector4(source.width, source.height, 0f, 0f)); | 
|             cs.Dispatch(kernel, Mathf.CeilToInt(source.width / 32f), Mathf.CeilToInt(source.height / 32f), 1); | 
|   | 
|             kernel = cs.FindKernel("KVectorscope"); | 
|             cs.SetBuffer(kernel, "_Vectorscope", m_Buffer); | 
|             cs.SetTexture(kernel, "_Source", source); | 
|             cs.SetInt("_IsLinear", GraphicsUtils.isLinearColorSpace ? 1 : 0); | 
|             cs.SetVector("_Res", new Vector4(source.width, source.height, 0f, 0f)); | 
|             cs.Dispatch(kernel, Mathf.CeilToInt(source.width / 32f), Mathf.CeilToInt(source.height / 32f), 1); | 
|   | 
|             if (m_VectorscopeTexture == null || m_VectorscopeTexture.width != source.width || m_VectorscopeTexture.height != source.height) | 
|             { | 
|                 GraphicsUtils.Destroy(m_VectorscopeTexture); | 
|                 m_VectorscopeTexture = new RenderTexture(source.width, source.height, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear) | 
|                 { | 
|                     hideFlags = HideFlags.DontSave, | 
|                     wrapMode = TextureWrapMode.Clamp, | 
|                     filterMode = FilterMode.Bilinear | 
|                 }; | 
|             } | 
|   | 
|             if (m_Material == null) | 
|                 m_Material = new Material(Shader.Find("Hidden/Post FX/Monitors/Vectorscope Render")) { hideFlags = HideFlags.DontSave }; | 
|   | 
|             m_Material.SetBuffer("_Vectorscope", m_Buffer); | 
|             m_Material.SetVector("_Size", new Vector2(m_VectorscopeTexture.width, m_VectorscopeTexture.height)); | 
|         } | 
|     } | 
| } |