Inheritance: MonoBehaviour
    /// <summary>
    /// Initialization of the movie surface
    /// </summary>
    void Awake()
    {
        Debug.Log("MovieSample Awake");

        mediaRenderer = GetComponent <Renderer>();

        videoPlayer = GetComponent <UnityEngine.Video.VideoPlayer>();
        if (videoPlayer == null)
        {
            videoPlayer = gameObject.AddComponent <UnityEngine.Video.VideoPlayer>();
        }
        videoPlayer.isLooping = LoopVideo;

        overlay = GetComponent <OVROverlay>();
        if (overlay == null)
        {
            overlay = gameObject.AddComponent <OVROverlay>();
        }

        // disable it to reset it.
        overlay.enabled = false;
        // only can use external surface with native plugin
        overlay.isExternalSurface = NativeVideoPlayer.IsAvailable;
        // only mobile has Equirect shape
        overlay.enabled = (overlay.currentOverlayShape != OVROverlay.OverlayShape.Equirect || Application.platform == RuntimePlatform.Android);

#if UNITY_EDITOR
        overlay.currentOverlayShape = OVROverlay.OverlayShape.Quad;
        overlay.enabled             = true;
#endif
    }
    private IEnumerator LoadTexture()
    {
        string     textureFilePath  = Application.streamingAssetsPath + "/spidermanSingle.jpg";
        OVROverlay overlayComponent = overlayGameObject.GetComponent <OVROverlay>();

        UnityWebRequest www = UnityWebRequestTexture.GetTexture(textureFilePath);

        yield return(www.SendWebRequest());

        if (www.isNetworkError || www.isHttpError || (www.error != null))
        {
            Debug.Log("XXX Texture not ready: " + textureFilePath);
            yield break;
        }

        Texture2D loadedTexture = ((DownloadHandlerTexture)www.downloadHandler).texture;
        Texture2D pageTexture   = new Texture2D(loadedTexture.width, loadedTexture.height, loadedTexture.format, mipMaps);

        pageTexture.LoadImage(www.downloadHandler.data);

        overlayComponent.textures[0]           = pageTexture;
        overlayComponent.textures[0].hideFlags = HideFlags.HideAndDontSave;
        Debug.Log("XXX TEXTURE " + overlayComponent.textures[0].width + " " + overlayComponent.textures[0].height);
        Recenter();
        www.Dispose();
    }
Example #3
0
    // Update is called once per frame
    void Update()
    {
        // Switch ui display types
        OverlaySwitch();

        // UI trace
        RaycastHit hitInfo;
        int        uiLayerMask = LayerMask.GetMask("DemoUI");

        Vector3    rayTracingDirection  = mainCamera.transform.forward;
        OVROverlay currentOverlay       = GetComponent <OVROverlay>();
        Vector3    cylinderIntersectPos = mainCamera.transform.position + mainCamera.transform.forward * 200;

        // Need transfer ray back to UI camera space for correct ray casting
        if (desiredUiType == EUiDisplayType.EUDT_OverlayCylinder || desiredUiType == EUiDisplayType.EUDT_WorldGeoCylinder)
        {
            cylinderSpaceTransform.position   = currentOverlay.transform.position;
            cylinderSpaceTransform.rotation   = currentOverlay.transform.rotation;
            cylinderSpaceTransform.localScale = Vector3.one;

            float cylinderRadius = currentOverlay.transform.localScale.z;
            CylinderRayTransfer(mainCamera.transform.position, mainCamera.transform.forward, cylinderSpaceTransform, cylinderRadius, ref rayTracingDirection, ref cylinderIntersectPos);
        }

        Physics.Raycast(mainCamera.transform.position, rayTracingDirection, out hitInfo, 500, uiLayerMask);

        // Highlight the selected tile
        if (hitInfo.collider != null)
        {
            Vector3 highLightEdge = new Vector3(0.1f, 0.1f, 0.00f);
            backgroundHighlight.SetActive(true);
            backgroundHighlight.transform.position   = hitInfo.collider.gameObject.transform.position;
            backgroundHighlight.transform.localScale = hitInfo.collider.gameObject.transform.localScale + highLightEdge;
        }
        else
        {
            backgroundHighlight.SetActive(false);
        }

        if (currentOverlay.currentOverlayShape == OVROverlay.OverlayShape.Cylinder)
        {
            cursor.transform.position = cylinderIntersectPos;
        }
        else
        {
            Physics.Raycast(mainCamera.transform.position, mainCamera.transform.forward, out hitInfo, 500);

            if (hitInfo.collider != null)
            {
                cursor.transform.position = hitInfo.point;
            }
            else
            {
                cursor.transform.position = mainCamera.transform.forward * 26 + mainCamera.transform.position;
            }
        }

        cursor.transform.LookAt(mainCamera.transform.position);
    }
Example #4
0
    private void Awake()
    {
        UnityThread.initUnityThread();
        RawImage.GetComponent <Button>().onClick.AddListener(OnClick);
        _overlay      = GetComponent <OVROverlay>();
        _rawImageRect = RawImage.GetComponent <RectTransform>();

        InitializeAndroidPlugin();
    }
Example #5
0
 // Token: 0x06003A27 RID: 14887 RVA: 0x001262E0 File Offset: 0x001246E0
 private void OnPostRender()
 {
     if (this.srcRT)
     {
         Graphics.Blit(this.srcRT, this.overlayRTChain[this.overlayRTIndex]);
         OVROverlay component = this.ovrOverlayObj.GetComponent <OVROverlay>();
         component.OverrideOverlayTextureInfo(this.overlayRTChain[this.overlayRTIndex], this.overlayTexturePtrs[this.overlayRTIndex], VRNode.LeftEye);
         this.overlayRTIndex++;
         this.overlayRTIndex %= 3;
     }
 }
Example #6
0
        /// Should be called after correct cameras are enabled
        public void Init()
        {
            m_Bloom.Clear();
            m_Fxaa.Clear();
            m_MobileBloom.Clear();

            var cameras = new HashSet <Camera>(
                FindObjectsOfType <Camera>(), new ReferenceComparer <Camera>());

            if (!App.Config.IsMobileHardware)
            {
                cameras.UnionWith(m_OptInCamerasForPC);
                cameras.ExceptWith(m_OptOutCamerasForPC);
            }
            m_Cameras = cameras.Where(x => x.tag != "Ignore").ToList();

            foreach (var camera in m_Cameras)
            {
                var rBloom = camera.GetComponent <SENaturalBloomAndDirtyLens>();
                if (rBloom)
                {
                    m_Bloom.Add(rBloom);
                }
                var rFxaa = camera.GetComponent <FXAA>();
                if (rFxaa)
                {
                    m_Fxaa.Add(rFxaa);
                }
                var mobileBloom = camera.GetComponent <MobileBloom>();
                if (mobileBloom)
                {
                    m_MobileBloom.Add(mobileBloom);
                }
            }

            m_FrameTimeStamps = new Queue <double>();

            m_MobileBloomAmount = 0;
            m_DesiredBloom      = 1;

            // Set up the OVR overlay for the dynamic quality debug readout.
#if OCULUS_SUPPORTED
            if (m_DebugText && m_DebugText.gameObject.activeInHierarchy &&
                App.Config.m_SdkMode == SdkMode.Oculus)
            {
                OVROverlay overlay = m_DebugText.gameObject.AddComponent <OVROverlay>();
                overlay.textures  = new Texture[] { m_DebugText.RenderedTexture };
                overlay.isDynamic = true;
            }
#endif // OCULUS_SUPPORTED

            // Push current level to camera settings.
            SetQualityLevel(QualityLevel);
        }
Example #7
0
 /// <summary>
 /// Copy camera's render target to triple buffered texture array and send it to OVROverlay object
 /// </summary>
 void OnPostRender()
 {
     if (srcRT)
     {
         Graphics.Blit(srcRT, overlayRTChain[overlayRTIndex]);
         OVROverlay OVROverlay = OVROverlayObj.GetComponent <OVROverlay>();
         Debug.Assert(OVROverlay);
         OVROverlay.OverrideOverlayTextureInfo(overlayRTChain[overlayRTIndex], overlayTexturePtrs[overlayRTIndex], UnityEngine.XR.XRNode.LeftEye);
         overlayRTIndex++;
         overlayRTIndex = overlayRTIndex % overlayRTChainSize;
     }
 }
 /// <summary>
 /// Copy camera's render target to triple buffered texture array and send it to OVROverlay object
 /// </summary>
 void OnPostRender()
 {
     if (srcRT)
     {
         Graphics.Blit(srcRT, overlayRTChain[overlayRTIndex]);
         OVROverlay ovrOverlay = ovrOverlayObj.GetComponent <OVROverlay>();
         Debug.Assert(ovrOverlay);
         ovrOverlay.OverrideOverlayTextureInfo(overlayRTChain[overlayRTIndex], overlayTexturePtrs[overlayRTIndex]);
         overlayRTIndex++;
         overlayRTIndex = overlayRTIndex % overlayRTChainSize;
     }
 }
Example #9
0
    private void SetRectsByVideoType(OVROverlay overlay, StereoType stereoType, DisplayType displayType)
    {
        Rect srcRectLeft, srcRectRight, destRectLeft, destRectRight;

        switch (displayType)
        {
        case DisplayType.Full:
            destRectLeft = destRectRight = new Rect(0, 0, 1, 1);
            break;

        case DisplayType.Half:
            destRectLeft = destRectRight = new Rect(0.25f, 0, 0.5f, 1);
            break;

        default:
            destRectLeft  = overlay.destRectLeft;
            destRectRight = overlay.destRectRight;
            break;
        }

        switch (stereoType)
        {
        case StereoType.Mono:
        case StereoType.Stereo:
            srcRectLeft = srcRectRight = new Rect(0, 0, 1, 1);
            break;

        case StereoType.StereoTopBottom:
            if (overlay.invertTextureRects)
            {
                srcRectLeft  = new Rect(0, 0.0f, 1, 0.5f);
                srcRectRight = new Rect(0, 0.5f, 1, 0.5f);
            }
            else
            {
                srcRectLeft  = new Rect(0, 0.5f, 1, 0.5f);
                srcRectRight = new Rect(0, 0.0f, 1, 0.5f);
            }
            break;

        case StereoType.StereoLeftRight:
            srcRectLeft  = new Rect(0, 0, 0.5f, 1);
            srcRectRight = new Rect(0.5f, 0, 0.5f, 1);
            break;

        default:
            srcRectLeft  = overlay.srcRectLeft;
            srcRectRight = overlay.srcRectRight;
            break;
        }
        overlay.SetSrcDestRects(srcRectLeft, srcRectRight, destRectLeft, destRectRight);
    }
    void Update()
    {
        if (overlay == null)
        {
            overlay = GetComponent <OVROverlay>();
        }

        if (overlay == null)
        {
            return;
        }

        overlay.textures[0] = videoPlayer.texture;
    }
Example #11
0
    void OnDisable()
    {
        if (OVRManager.loadedXRDevice == OVRManager.XRDevice.Oculus)
        {
            DestroySurfaceGeometries(true);
        }

        if (auxGameObject != null)
        {
            Debug.Assert(passthroughOverlay != null);
            Destroy(auxGameObject);
            auxGameObject      = null;
            passthroughOverlay = null;
        }
    }
    /// <summary>
    /// Copy camera's render target to triple buffered texture array and send it to OVROverlay object
    /// </summary>
    void OnPostRender()
    {
        if (srcRT)
        {
            Graphics.Blit(srcRT, overlayRTChain[overlayRTIndex]);
            OVROverlay ovrOverlay = ovrOverlayObj.GetComponent <OVROverlay>();
            Debug.Assert(ovrOverlay);
#if UNITY_2017_2_OR_NEWER
            ovrOverlay.OverrideOverlayTextureInfo(overlayRTChain[overlayRTIndex], overlayTexturePtrs[overlayRTIndex], UnityEngine.XR.XRNode.LeftEye);
#else
            ovrOverlay.OverrideOverlayTextureInfo(overlayRTChain[overlayRTIndex], overlayTexturePtrs[overlayRTIndex], UnityEngine.VR.VRNode.LeftEye);
#endif
            overlayRTIndex++;
            overlayRTIndex = overlayRTIndex % overlayRTChainSize;
        }
    }
Example #13
0
    // Use this for initialization
    void Start()
    {
        cylinderSpaceTransform = new GameObject().transform;
        overOverlay            = GetComponent <OVROverlay>();
        startPos = transform.position;

        // Start with Overlay Quad
        desiredUiType = EUiDisplayType.EUDT_OverlayQuad;
        CameraAndRenderTargetSetup();
        overOverlay.enabled             = true;
        overOverlay.currentOverlayShape = OVROverlay.OverlayShape.Quad;
        worldGeoProxy_Cylinder.SetActive(false);
        worldGeoProxy_Quad.SetActive(false);

        // Keep the cursor on the top by enabling last
        cursor.SetActive(true);
    }
Example #14
0
    private void Awake()
    {
        List <GUIContent> selectableShapeNameList = new List <GUIContent>();
        List <OVROverlay.OverlayShape> selectableShapesValueList = new List <OVROverlay.OverlayShape>();

        foreach (OVROverlay.OverlayShape value in Enum.GetValues(typeof(OVROverlay.OverlayShape)))
        {
            if (!OVROverlay.IsPassthroughShape(value))
            {
                string name = Enum.GetName(typeof(OVROverlay.OverlayShape), value);
                selectableShapeNameList.Add(new GUIContent(name, name));
                selectableShapesValueList.Add(value);
            }
        }
        selectableShapeNames  = selectableShapeNameList.ToArray();
        selectableShapeValues = selectableShapesValueList.ToArray();
    }
Example #15
0
 private StereoType GetStereoType(OVROverlay overlay)
 {
     if (overlay.textures[0] != null && overlay.textures[1] != null)
     {
         if (IsUnitRect(overlay.srcRectLeft) && IsUnitRect(overlay.srcRectRight))
         {
             return(StereoType.Stereo);
         }
         else
         {
             return(StereoType.Custom);
         }
     }
     else if (overlay.textures[0] != null)
     {
         if (IsUnitRect(overlay.srcRectLeft) && IsUnitRect(overlay.srcRectRight))
         {
             return(StereoType.Mono);
         }
         else if (IsRect(overlay.srcRectLeft, 0, 0, 0.5f, 1f) && IsRect(overlay.srcRectRight, 0.5f, 0, 0.5f, 1f))
         {
             return(StereoType.StereoLeftRight);
         }
         else if (overlay.invertTextureRects && IsRect(overlay.srcRectLeft, 0, 0.0f, 1f, 0.5f) && IsRect(overlay.srcRectRight, 0f, 0.5f, 1f, 0.5f))
         {
             return(StereoType.StereoTopBottom);
         }
         else if (!overlay.invertTextureRects && IsRect(overlay.srcRectLeft, 0, 0.5f, 1f, 0.5f) && IsRect(overlay.srcRectRight, 0f, 0f, 1f, 0.5f))
         {
             return(StereoType.StereoTopBottom);
         }
         else
         {
             return(StereoType.Custom);
         }
     }
     else
     {
         return(StereoType.Mono);
     }
 }
Example #16
0
    protected void Awake()
    {
        _Overlay      = GetComponent <OVROverlay>();
        _MeshFilter   = GetComponent <MeshFilter>();
        _MeshCollider = GetComponent <MeshCollider>();

        _Transform = transform;
        if (Camera.main && Camera.main.transform.parent)
        {
            _CameraRoot = Camera.main.transform.parent;
        }

        #if UNITY_EDITOR
        if (!Application.isPlaying)
        {
            UnityEditor.EditorApplication.update += Update;
        }
        #endif

        _Awake = true;
    }
        protected void UpdateOverlay()
        {
            Profiler.BeginSample("InterfaceRenderer.UpdateOverlay");
            try
            {
                if (!_canvasRenderTexture.ShouldUseOVROverlay)
                {
                    _overlay?.gameObject?.SetActive(false);
                    return;
                }

                if (_overlay == null)
                {
                    GameObject overlayObj = CreateChildObject("__Overlay");
                    _overlay = overlayObj.AddComponent <OVROverlay>();
                    _overlay.isAlphaPremultiplied = !Application.isMobilePlatform;
                }
                else
                {
                    _overlay.gameObject.SetActive(true);
                }

                bool useUnderlayRendering = _canvasRenderTexture.RenderingMode == RenderingMode.OVR_Underlay;
                _overlay.textures = new Texture[1] {
                    _canvasRenderTexture.Texture
                };
                _overlay.noDepthBufferTesting    = useUnderlayRendering;
                _overlay.currentOverlayType      = useUnderlayRendering ? OVROverlay.OverlayType.Underlay : OVROverlay.OverlayType.Overlay;
                _overlay.currentOverlayShape     = OverlayShape;
                _overlay.useExpensiveSuperSample = _canvasRenderTexture.EnableSuperSampling;

                UpdateOverlayPositionAndScale();
            }
            finally
            {
                Profiler.EndSample();
            }
        }
    /// <summary>
    /// Initialization of the movie surface
    /// </summary>
    void Awake()
    {
        Debug.Log("MovieSample Awake");

        mediaRenderer = GetComponent <Renderer>();

        videoPlayer = GetComponent <UnityEngine.Video.VideoPlayer>();
        if (videoPlayer == null)
        {
            videoPlayer = gameObject.AddComponent <UnityEngine.Video.VideoPlayer>();
        }

        overlay = GetComponent <OVROverlay>();
        if (overlay == null)
        {
            overlay = gameObject.AddComponent <OVROverlay>();
        }

        // only mobile has Equirect shape
        overlay.enabled = Application.platform == RuntimePlatform.Android;
        // only can use external surface with native plugin
        overlay.isExternalSurface = NativeVideoPlayer.IsAvailable;
    }
Example #19
0
    /// <summary>
    /// Initialization of the movie surface
    /// </summary>
    void Awake()
    {
        Debug.Log("MovieSample Awake");

        mediaRenderer = GetComponent <Renderer>();

        videoPlayer = GetComponent <UnityEngine.Video.VideoPlayer>();
        if (videoPlayer == null)
        {
            videoPlayer = gameObject.AddComponent <UnityEngine.Video.VideoPlayer>();
        }

        overlay = GetComponent <OVROverlay>();
        if (overlay == null)
        {
            overlay = gameObject.AddComponent <OVROverlay>();
        }

        // set shape to Equirect
        overlay.currentOverlayShape = OVROverlay.OverlayShape.Equirect;

        // set source and dest matrices for 180 video
        overlay.overrideTextureRectMatrix = true;
        overlay.SetSrcDestRects(new Rect(0, 0, 0.5f, 1.0f), new Rect(0.5f, 0, 0.5f, 1.0f), new Rect(0.25f, 0, 0.5f, 1.0f), new Rect(0.25f, 0, 0.5f, 1.0f));

        // disable it to reset it.
        overlay.enabled = false;
        // only can use external surface with native plugin
        overlay.isExternalSurface = NativeVideoPlayer.IsAvailable;
        // only mobile has Equirect shape
        overlay.enabled = Application.platform == RuntimePlatform.Android;

#if UNITY_EDITOR
        overlay.currentOverlayShape = OVROverlay.OverlayShape.Quad;
        overlay.enabled             = true;
#endif
    }
Example #20
0
    void OnEnable()
    {
        Debug.Assert(auxGameObject == null);
        Debug.Assert(passthroughOverlay == null);

        // Create auxiliary GameObject which contains the OVROverlay component for the proxy layer (and possibly other
        // auxiliary layers in the future).
        auxGameObject = new GameObject("OVRPassthroughLayer auxiliary GameObject");

        // Auxiliary GameObject must be a child of the current GameObject s.t. it survives if `DontDestroyOnLoad` is
        // called on the current GameObject.
        auxGameObject.transform.parent = this.transform;

        // Add OVROverlay component for the passthrough proxy layer.
        passthroughOverlay = auxGameObject.AddComponent <OVROverlay>();
        passthroughOverlay.currentOverlayShape = overlayShape;
        SyncToOverlay();

        // Surface geometries have been moved to the deferred additions queue in OnDisable() and will be re-added
        // in LateUpdate().

        // Flag style to be re-applied in LateUpdate()
        styleDirty = true;
    }
    /// <summary>
    /// Initialization of the movie surface
    /// </summary>
    void Awake()
    {
        Debug.Log("MovieSample Awake");

        mediaRenderer = GetComponent <Renderer>();

        videoPlayer = GetComponent <UnityEngine.Video.VideoPlayer>();
        if (videoPlayer == null)
        {
            videoPlayer = gameObject.AddComponent <UnityEngine.Video.VideoPlayer>();
        }
        videoPlayer.isLooping = LoopVideo;

        overlay = GetComponent <OVROverlay>();
        if (overlay == null)
        {
            overlay = gameObject.AddComponent <OVROverlay>();
        }

        Rect destRect = new Rect(0, 0, 1, 1);

        switch (Shape)
        {
        case VideoShape._360:
            // set shape to Equirect
            overlay.currentOverlayShape = OVROverlay.OverlayShape.Equirect;
            break;

        case VideoShape._180:
            overlay.currentOverlayShape = OVROverlay.OverlayShape.Equirect;
            destRect = new Rect(0.25f, 0, 0.5f, 1.0f);
            break;

        case VideoShape.Quad:
        default:
            overlay.currentOverlayShape = OVROverlay.OverlayShape.Quad;
            break;
        }

        overlay.overrideTextureRectMatrix = true;

        Rect sourceLeft  = new Rect(0, 0, 1, 1);
        Rect sourceRight = new Rect(0, 0, 1, 1);

        switch (Stereo)
        {
        case VideoStereo.LeftRight:
            // set source matrices for left/right
            sourceLeft  = new Rect(0, 0, 0.5f, 1.0f);
            sourceRight = new Rect(0.5f, 0, 0.5f, 1.0f);
            break;

        case VideoStereo.TopBottom:
            // set source matrices for top/bottom
            sourceLeft  = new Rect(0, 0, 1.0f, 0.5f);
            sourceRight = new Rect(0, 0.5f, 1.0f, 0.5f);
            break;
        }
        overlay.SetSrcDestRects(sourceLeft, sourceRight, destRect, destRect);

        // disable it to reset it.
        overlay.enabled = false;
        // only can use external surface with native plugin
        overlay.isExternalSurface = NativeVideoPlayer.IsAvailable;
        // only mobile has Equirect shape
        overlay.enabled = (overlay.currentOverlayShape != OVROverlay.OverlayShape.Equirect || Application.platform == RuntimePlatform.Android);

#if UNITY_EDITOR
        overlay.currentOverlayShape = OVROverlay.OverlayShape.Quad;
        overlay.enabled             = true;
#endif
    }
Example #22
0
 public void SetOverlay(OVROverlay overlay)
 {
     _Overlay = overlay;
 }
Example #23
0
    // Start is called before the first frame update
    void Start()
    {
        _canvas = GetComponent <Canvas>();

        _rectTransform = _canvas.GetComponent <RectTransform>();

        float rectWidth  = _rectTransform.rect.width;
        float rectHeight = _rectTransform.rect.height;

        float aspectX = rectWidth >= rectHeight ? 1 : rectWidth / rectHeight;
        float aspectY = rectHeight >= rectWidth ? 1 : rectHeight / rectWidth;

        // if we are scaling the viewport we don't need to add a border
        int pixelBorder = ScaleViewport ? 0 : 8;
        int innerWidth  = Mathf.CeilToInt(aspectX * (MaxTextureSize - pixelBorder * 2));
        int innerHeight = Mathf.CeilToInt(aspectY * (MaxTextureSize - pixelBorder * 2));
        int width       = innerWidth + pixelBorder * 2;
        int height      = innerHeight + pixelBorder * 2;

        float paddedWidth  = rectWidth * (width / (float)innerWidth);
        float paddedHeight = rectHeight * (height / (float)innerHeight);

        float insetRectWidth  = innerWidth / (float)width;
        float insetRectHeight = innerHeight / (float)height;

        // ever so slightly shrink our opaque mesh to avoid black borders
        Vector2 opaqueTrim = Opacity == DrawMode.Opaque ? new Vector2(0.005f / _rectTransform.lossyScale.x, 0.005f / _rectTransform.lossyScale.y) : Vector2.zero;

        _renderTexture = new RenderTexture(width, height, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
        // if we can't scale the viewport, generate mipmaps instead
        _renderTexture.useMipMap = !ScaleViewport;

        GameObject overlayCamera = new GameObject(name + " Overlay Camera")
        {
#if !DEBUG_OVERLAY_CANVAS
            hideFlags = HideFlags.HideInHierarchy | HideFlags.NotEditable
#endif
        };

        overlayCamera.transform.SetParent(transform, false);

        _camera = overlayCamera.AddComponent <Camera>();
        _camera.stereoTargetEye    = StereoTargetEyeMask.None;
        _camera.transform.position = transform.position - transform.forward;
        _camera.orthographic       = true;
        _camera.enabled            = false;
        _camera.targetTexture      = _renderTexture;
        _camera.cullingMask        = 1 << gameObject.layer;
        _camera.clearFlags         = CameraClearFlags.SolidColor;
        _camera.backgroundColor    = Color.clear;
        _camera.orthographicSize   = 0.5f * paddedHeight * _rectTransform.localScale.y;
        _camera.nearClipPlane      = 0.99f;
        _camera.farClipPlane       = 1.01f;

        _quad = new Mesh()
        {
            name      = name + " Overlay Quad",
            hideFlags = HideFlags.HideAndDontSave
        };

        _quad.vertices  = new Vector3[] { new Vector3(-0.5f, -0.5f), new Vector3(-0.5f, 0.5f), new Vector3(0.5f, 0.5f), new Vector3(0.5f, -0.5f) };
        _quad.uv        = new Vector2[] { new Vector2(0, 0), new Vector2(0, 1), new Vector2(1, 1), new Vector2(1, 0) };
        _quad.triangles = new int[] { 0, 1, 2, 2, 3, 0 };
        _quad.bounds    = new Bounds(Vector3.zero, Vector3.one);
        _quad.UploadMeshData(true);

        switch (Opacity)
        {
        case DrawMode.Opaque:
            _defaultMat = new Material(_opaqueShader);
            break;

        case DrawMode.OpaqueWithClip:
            _defaultMat = new Material(_opaqueShader);
            _defaultMat.EnableKeyword("WITH_CLIP");
            break;

        case DrawMode.TransparentDefaultAlpha:
            _defaultMat = new Material(_transparentShader);
            _defaultMat.EnableKeyword("ALPHA_SQUARED");
            break;

        case DrawMode.TransparentCorrectAlpha:
            _defaultMat = new Material(_transparentShader);
            break;
        }
        _defaultMat.mainTexture       = _renderTexture;
        _defaultMat.color             = Color.black;
        _defaultMat.mainTextureOffset = new Vector2(0.5f - 0.5f * insetRectWidth, 0.5f - 0.5f * insetRectHeight);
        _defaultMat.mainTextureScale  = new Vector2(insetRectWidth, insetRectHeight);

        GameObject meshRenderer = new GameObject(name + " MeshRenderer")
        {
#if !DEBUG_OVERLAY_CANVAS
            hideFlags = HideFlags.HideInHierarchy | HideFlags.NotEditable
#endif
        };

        meshRenderer.transform.SetParent(transform, false);
        meshRenderer.AddComponent <MeshFilter>().sharedMesh = _quad;
        _meshRenderer = meshRenderer.AddComponent <MeshRenderer>();
        _meshRenderer.sharedMaterial      = _defaultMat;
        meshRenderer.layer                = Layer;
        meshRenderer.transform.localScale = new Vector3(rectWidth - opaqueTrim.x, rectHeight - opaqueTrim.y, 1);

        GameObject overlay = new GameObject(name + " Overlay")
        {
#if !DEBUG_OVERLAY_CANVAS
            hideFlags = HideFlags.HideInHierarchy | HideFlags.NotEditable
#endif
        };

        overlay.transform.SetParent(transform, false);
        _overlay                         = overlay.AddComponent <OVROverlay>();
        _overlay.isDynamic               = true;
        _overlay.noDepthBufferTesting    = true;
        _overlay.isAlphaPremultiplied    = !Application.isMobilePlatform;
        _overlay.textures[0]             = _renderTexture;
        _overlay.currentOverlayType      = OVROverlay.OverlayType.Underlay;
        _overlay.transform.localScale    = new Vector3(paddedWidth, paddedHeight, 1);
        _overlay.useExpensiveSuperSample = Expensive;
    }
    public override void OnInspectorGUI()
    {
        OVROverlay overlay = (OVROverlay)target;

        if (overlay == null)
        {
            return;
        }

        EditorGUILayout.LabelField("Display Order", EditorStyles.boldLabel);
        overlay.currentOverlayType   = (OVROverlay.OverlayType)EditorGUILayout.EnumPopup(new GUIContent("Current Overlay Type", "Whether this overlay should layer behind the scene or in front of it"), overlay.currentOverlayType);
        overlay.compositionDepth     = EditorGUILayout.IntField(new GUIContent("Composition Depth", "Depth value used to sort OVROverlays in the scene, smaller value appears in front"), overlay.compositionDepth);
        overlay.noDepthBufferTesting = EditorGUILayout.Toggle(new GUIContent("No Depth Buffer Testing", "The noDepthBufferTesting will stop layer's depth buffer compositing even if the engine has \"Shared Depth Buffer\" enabled"), overlay.noDepthBufferTesting);
        EditorGUILayout.Space();

        EditorGUILayout.LabelField(new GUIContent("Overlay Shape", "The shape of this overlay"), EditorStyles.boldLabel);
        overlay.currentOverlayShape = (OVROverlay.OverlayShape)EditorGUILayout.EnumPopup(new GUIContent("Overlay Shape", "The shape of this overlay"), overlay.currentOverlayShape);
        EditorGUILayout.Space();

        EditorGUILayout.Separator();
        EditorGUILayout.LabelField("Textures", EditorStyles.boldLabel);

#if UNITY_ANDROID
        bool lastIsExternalSurface = overlay.isExternalSurface;
        overlay.isExternalSurface = EditorGUILayout.Toggle(new GUIContent("Is External Surface", "On Android, retrieve an Android Surface object to render to (e.g., video playback)"), overlay.isExternalSurface);

        if (lastIsExternalSurface)
        {
            overlay.externalSurfaceWidth  = EditorGUILayout.IntField("External Surface Width", overlay.externalSurfaceWidth);
            overlay.externalSurfaceHeight = EditorGUILayout.IntField("External Surface Height", overlay.externalSurfaceHeight);
            overlay.isProtectedContent    = EditorGUILayout.Toggle(new GUIContent("Is Protected Content", "The external surface has L1 widevine protection."), overlay.isProtectedContent);
        }
        else
#endif
        {
            if (overlay.textures == null)
            {
                overlay.textures = new Texture[2];
            }
            if (overlay.textures.Length < 2)
            {
                Texture[] tmp = new Texture[2];
                for (int i = 0; i < overlay.textures.Length; i++)
                {
                    tmp[i] = overlay.textures[i];
                }
                overlay.textures = tmp;
            }

            var labelControlRect = EditorGUILayout.GetControlRect();
            EditorGUI.LabelField(new Rect(labelControlRect.x, labelControlRect.y, labelControlRect.width / 2, labelControlRect.height), new GUIContent("Left Texture", "Texture used for the left eye"));
            EditorGUI.LabelField(new Rect(labelControlRect.x + labelControlRect.width / 2, labelControlRect.y, labelControlRect.width / 2, labelControlRect.height), new GUIContent("Right Texture", "Texture used for the right eye"));


            var textureControlRect = EditorGUILayout.GetControlRect(GUILayout.Height(64));

            overlay.textures[0] = (Texture)EditorGUI.ObjectField(new Rect(textureControlRect.x, textureControlRect.y, 64, textureControlRect.height), overlay.textures[0], typeof(Texture), true);
            Texture right = (Texture)EditorGUI.ObjectField(new Rect(textureControlRect.x + textureControlRect.width / 2, textureControlRect.y, 64, textureControlRect.height), overlay.textures[1] != null ? overlay.textures[1] : overlay.textures[0], typeof(Texture), true);
            if (right == overlay.textures[0])
            {
                overlay.textures[1] = null;
            }
            else
            {
                overlay.textures[1] = right;
            }

            overlay.isDynamic = EditorGUILayout.Toggle(new GUIContent("Dynamic Texture", "This texture will be updated dynamically at runtime (e.g., Video)"), overlay.isDynamic);
#if !UNITY_ANDROID
            overlay.isProtectedContent = EditorGUILayout.Toggle(new GUIContent("Is Protected Content", "The texture has copy protection, e.g., HDCP"), overlay.isProtectedContent);
#endif
        }
        if (overlay.currentOverlayShape == OVROverlay.OverlayShape.Cylinder || overlay.currentOverlayShape == OVROverlay.OverlayShape.Equirect || overlay.currentOverlayShape == OVROverlay.OverlayShape.Quad)
        {
            EditorGUILayout.Separator();
            EditorGUILayout.Space();
            EditorGUILayout.LabelField("Texture Rects", EditorStyles.boldLabel);

            bool lastOverrideTextureRectMatrix = overlay.overrideTextureRectMatrix;
            overlay.overrideTextureRectMatrix = !EditorGUILayout.Toggle(new GUIContent("Use Default Rects", overlay.textures[1] == null ? "If you need to use a single texture as a stereo image, uncheck this box" : "Uncheck this box if you need to clip you textures or layer"), !overlay.overrideTextureRectMatrix);

            if (lastOverrideTextureRectMatrix)
            {
                sourceRectsVisible = EditorGUILayout.Foldout(sourceRectsVisible, new GUIContent("Source Rects", "What portion of the source texture will ultimately be shown in each eye."));

                if (sourceRectsVisible)
                {
                    var mat = SrcRectMaterial;

                    if (mat != null)
                    {
                        Rect drawRect = EditorGUILayout.GetControlRect(GUILayout.Height(128 + 8));
                        mat.SetVector("_SrcRectLeft", new Vector4(Mathf.Max(0.0f, overlay.srcRectLeft.x), Mathf.Max(0.0f, overlay.srcRectLeft.y), Mathf.Min(1.0f - overlay.srcRectLeft.x, overlay.srcRectLeft.width), Mathf.Min(1.0f - overlay.srcRectLeft.y, overlay.srcRectLeft.height)));
                        mat.SetVector("_SrcRectRight", new Vector4(Mathf.Max(0.0f, overlay.srcRectRight.x), Mathf.Max(0.0f, overlay.srcRectRight.y), Mathf.Min(1.0f - overlay.srcRectRight.x, overlay.srcRectRight.width), Mathf.Min(1.0f - overlay.srcRectRight.y, overlay.srcRectRight.height)));
                        // center our draw rect
                        var drawRectCentered = new Rect(drawRect.x + drawRect.width / 2 - 128 - 4, drawRect.y, 256 + 8, drawRect.height);
                        EditorGUI.DrawPreviewTexture(drawRectCentered, overlay.textures[0] ?? Texture2D.blackTexture, mat);

                        var drawRectInset = new Rect(drawRectCentered.x + 4, drawRectCentered.y + 4, drawRectCentered.width - 8, drawRectCentered.height - 8);
                        UpdateRectDragging(drawRectInset, drawRectInset, TextureRect.SrcLeft, TextureRect.SrcRight, ref overlay.srcRectLeft, ref overlay.srcRectRight);
                        CreateCursorRects(drawRectInset, overlay.srcRectLeft);
                        CreateCursorRects(drawRectInset, overlay.srcRectRight);
                    }

                    var labelControlRect = EditorGUILayout.GetControlRect();
                    EditorGUI.LabelField(new Rect(labelControlRect.x, labelControlRect.y, labelControlRect.width / 2, labelControlRect.height), new GUIContent("Left Source Rect", "The rect in the source image that will be displayed on the left eye layer"));
                    EditorGUI.LabelField(new Rect(labelControlRect.x + labelControlRect.width / 2, labelControlRect.y, labelControlRect.width / 2, labelControlRect.height), new GUIContent("Right Source Rect", "The rect in the source image that will be displayed on the right eye layer"));

                    var rectControlRect = EditorGUILayout.GetControlRect(GUILayout.Height(34));

                    overlay.srcRectLeft  = Clamp01(EditorGUI.RectField(new Rect(rectControlRect.x, rectControlRect.y, rectControlRect.width / 2 - 20, rectControlRect.height), overlay.srcRectLeft));
                    overlay.srcRectRight = Clamp01(EditorGUI.RectField(new Rect(rectControlRect.x + rectControlRect.width / 2, rectControlRect.y, rectControlRect.width / 2 - 20, rectControlRect.height), overlay.srcRectRight));


                    EditorGUILayout.BeginHorizontal();
                    if (overlay.textures[1] != null)
                    {
                        if (GUILayout.Button(new GUIContent("Reset To Default", "Reset Source Rects to default")))
                        {
                            SetRectsByVideoType(overlay, StereoType.Stereo, DisplayType.Custom);
                        }
                    }
                    else
                    {
                        if (GUILayout.Button(new GUIContent("Monoscopic", "Display the full Texture in both eyes")))
                        {
                            SetRectsByVideoType(overlay, StereoType.Mono, DisplayType.Custom);
                        }
                        if (GUILayout.Button(new GUIContent("Stereo Left/Right", "The left half of the texture is displayed in the left eye, and the right half in the right eye")))
                        {
                            SetRectsByVideoType(overlay, StereoType.StereoLeftRight, DisplayType.Custom);
                        }
                        if (GUILayout.Button(new GUIContent("Stereo Top/Bottom", "The top half of the texture is displayed in the left eye, and the bottom half in the right eye")))
                        {
                            SetRectsByVideoType(overlay, StereoType.StereoTopBottom, DisplayType.Custom);
                        }
                    }
                    EditorGUILayout.EndHorizontal();
                }
                destRectsVisible = EditorGUILayout.Foldout(destRectsVisible, new GUIContent("Destination Rects", "What portion of the destination texture that the source will be rendered into."));
                if (destRectsVisible)
                {
                    var mat = DestRectMaterial;

                    if (mat != null)
                    {
                        Rect drawRect = EditorGUILayout.GetControlRect(GUILayout.Height(128 + 8));
                        mat.SetVector("_SrcRectLeft", new Vector4(Mathf.Max(0.0f, overlay.srcRectLeft.x), Mathf.Max(0.0f, overlay.srcRectLeft.y), Mathf.Min(1.0f - overlay.srcRectLeft.x, overlay.srcRectLeft.width), Mathf.Min(1.0f - overlay.srcRectLeft.y, overlay.srcRectLeft.height)));
                        mat.SetVector("_SrcRectRight", new Vector4(Mathf.Max(0.0f, overlay.srcRectRight.x), Mathf.Max(0.0f, overlay.srcRectRight.y), Mathf.Min(1.0f - overlay.srcRectRight.x, overlay.srcRectRight.width), Mathf.Min(1.0f - overlay.srcRectRight.y, overlay.srcRectRight.height)));
                        mat.SetVector("_DestRectLeft", new Vector4(Mathf.Max(0.0f, overlay.destRectLeft.x), Mathf.Max(0.0f, overlay.destRectLeft.y), Mathf.Min(1.0f - overlay.destRectLeft.x, overlay.destRectLeft.width), Mathf.Min(1.0f - overlay.destRectLeft.y, overlay.destRectLeft.height)));
                        mat.SetVector("_DestRectRight", new Vector4(Mathf.Max(0.0f, overlay.destRectRight.x), Mathf.Max(0.0f, overlay.destRectRight.y), Mathf.Min(1.0f - overlay.destRectRight.x, overlay.destRectRight.width), Mathf.Min(1.0f - overlay.destRectRight.y, overlay.destRectRight.height)));
                        mat.SetColor("_BackgroundColor", EditorGUIUtility.isProSkin ? (Color) new Color32(56, 56, 56, 255) : (Color) new Color32(194, 194, 194, 255));

                        var drawRectCentered = new Rect(drawRect.x + drawRect.width / 2 - 128 - 16 - 4, drawRect.y, 256 + 32 + 8, drawRect.height);
                        // center our draw rect
                        EditorGUI.DrawPreviewTexture(drawRectCentered, overlay.textures[0] ?? Texture2D.blackTexture, mat);

                        var drawRectInsetLeft  = new Rect(drawRectCentered.x + 4, drawRectCentered.y + 4, drawRectCentered.width / 2 - 20, drawRectCentered.height - 8);
                        var drawRectInsetRight = new Rect(drawRectCentered.x + drawRectCentered.width / 2 + 16, drawRectCentered.y + 4, drawRectCentered.width / 2 - 20, drawRectCentered.height - 8);
                        UpdateRectDragging(drawRectInsetLeft, drawRectInsetRight, TextureRect.DestLeft, TextureRect.DestRight, ref overlay.destRectLeft, ref overlay.destRectRight);

                        CreateCursorRects(drawRectInsetLeft, overlay.destRectLeft);
                        CreateCursorRects(drawRectInsetRight, overlay.destRectRight);
                    }

                    var labelControlRect = EditorGUILayout.GetControlRect();
                    EditorGUI.LabelField(new Rect(labelControlRect.x, labelControlRect.y, labelControlRect.width / 2, labelControlRect.height), new GUIContent("Left Destination Rect", "The rect in the destination layer the left eye will display to"));
                    EditorGUI.LabelField(new Rect(labelControlRect.x + labelControlRect.width / 2, labelControlRect.y, labelControlRect.width / 2, labelControlRect.height), new GUIContent("Right Destination Rect", "The rect in the destination layer the right eye will display to"));

                    var rectControlRect = EditorGUILayout.GetControlRect(GUILayout.Height(34));

                    overlay.destRectLeft  = Clamp01(EditorGUI.RectField(new Rect(rectControlRect.x, rectControlRect.y, rectControlRect.width / 2 - 20, rectControlRect.height), overlay.destRectLeft));
                    overlay.destRectRight = Clamp01(EditorGUI.RectField(new Rect(rectControlRect.x + rectControlRect.width / 2, rectControlRect.y, rectControlRect.width / 2 - 20, rectControlRect.height), overlay.destRectRight));


                    if (overlay.currentOverlayShape == OVROverlay.OverlayShape.Equirect)
                    {
                        EditorGUILayout.BeginHorizontal();
                        if (GUILayout.Button(new GUIContent("360 Video", "Display the full 360 layer")))
                        {
                            SetRectsByVideoType(overlay, StereoType.Custom, DisplayType.Full);
                        }
                        if (GUILayout.Button(new GUIContent("180 Video", "Display the front 180 layer")))
                        {
                            SetRectsByVideoType(overlay, StereoType.Custom, DisplayType.Half);
                        }
                        EditorGUILayout.EndHorizontal();
                    }
                    else
                    {
                        if (GUILayout.Button(new GUIContent("Reset To Default", "Reset Source Rects to default")))
                        {
                            SetRectsByVideoType(overlay, StereoType.Custom, DisplayType.Full);
                        }
                    }
                }
            }
        }
        EditorGUILayout.Separator();
        EditorGUILayout.LabelField("Color Scale", EditorStyles.boldLabel);
        EditorGUILayout.Space();
        overlay.overridePerLayerColorScaleAndOffset = EditorGUILayout.Toggle(new GUIContent("Override Color Scale", "Manually set color scale and offset of this layer, regardless of what the global values are from OVRManager.SetColorScaleAndOffset()."), overlay.overridePerLayerColorScaleAndOffset);
        if (overlay.overridePerLayerColorScaleAndOffset)
        {
            Vector4 colorScale  = EditorGUILayout.Vector4Field(new GUIContent("Color Scale", "Scale that the color values for this overlay will be multiplied by."), overlay.colorScale);
            Vector4 colorOffset = EditorGUILayout.Vector4Field(new GUIContent("Color Offset", "Offset that the color values for this overlay will be added to."), overlay.colorOffset);
            overlay.SetPerLayerColorScaleAndOffset(colorScale, colorOffset);
        }

        EditorUtility.SetDirty(overlay);
    }