コード例 #1
0
        private void OnGenerateVisualContent(MeshGenerationContext mgc)
        {
            if (image == null && sprite == null && vectorImage == null)
            {
                return;
            }

            var alignedRect = GUIUtility.AlignRectToDevice(contentRect);

            var rectParams = new MeshGenerationContextUtils.RectangleParams();

            if (image != null)
            {
                rectParams = MeshGenerationContextUtils.RectangleParams.MakeTextured(alignedRect, uv, image, scaleMode, panel.contextType);
            }
            else if (sprite != null)
            {
                var slices = Vector4.zero;
                rectParams = MeshGenerationContextUtils.RectangleParams.MakeSprite(alignedRect, sprite, scaleMode, panel.contextType, false, ref slices);
            }
            else if (vectorImage != null)
            {
                rectParams = MeshGenerationContextUtils.RectangleParams.MakeVectorTextured(alignedRect, uv, vectorImage, scaleMode, panel.contextType);
            }
            rectParams.color = tintColor;
            mgc.Rectangle(rectParams);
        }
コード例 #2
0
        public void DrawVisualElementBorder()
        {
            bool flag = this.currentElement.layout.width >= Mathf.Epsilon && this.currentElement.layout.height >= Mathf.Epsilon;

            if (flag)
            {
                ComputedStyle computedStyle = this.currentElement.computedStyle;
                bool          flag2         = (computedStyle.borderLeftColor != Color.clear && computedStyle.borderLeftWidth.value > 0f) || (computedStyle.borderTopColor != Color.clear && computedStyle.borderTopWidth.value > 0f) || (computedStyle.borderRightColor != Color.clear && computedStyle.borderRightWidth.value > 0f) || (computedStyle.borderBottomColor != Color.clear && computedStyle.borderBottomWidth.value > 0f);
                if (flag2)
                {
                    MeshGenerationContextUtils.BorderParams borderParams = new MeshGenerationContextUtils.BorderParams
                    {
                        rect              = GUIUtility.AlignRectToDevice(this.currentElement.rect),
                        leftColor         = computedStyle.borderLeftColor.value,
                        topColor          = computedStyle.borderTopColor.value,
                        rightColor        = computedStyle.borderRightColor.value,
                        bottomColor       = computedStyle.borderBottomColor.value,
                        leftWidth         = computedStyle.borderLeftWidth.value,
                        topWidth          = computedStyle.borderTopWidth.value,
                        rightWidth        = computedStyle.borderRightWidth.value,
                        bottomWidth       = computedStyle.borderBottomWidth.value,
                        playmodeTintColor = ((this.currentElement.panel.contextType == ContextType.Editor) ? UIElementsUtility.editorPlayModeTintColor : Color.white)
                    };
                    MeshGenerationContextUtils.GetVisualElementRadii(this.currentElement, out borderParams.topLeftRadius, out borderParams.bottomLeftRadius, out borderParams.topRightRadius, out borderParams.bottomRightRadius);
                    this.DrawBorder(borderParams);
                }
            }
        }
コード例 #3
0
        // Helper function: Get all mouse rects
        private static Rect[] CalcMouseRects(Rect position, GUIContent[] contents, int xCount, float elemWidth, float elemHeight, GUIStyle style, GUIStyle firstStyle, GUIStyle midStyle, GUIStyle lastStyle, bool addBorders, GUI.ToolbarButtonSize buttonSize)
        {
            int      count = contents.Length;
            int      x = 0;
            float    xPos = position.xMin, yPos = position.yMin;
            GUIStyle currentStyle = style;

            Rect[] retval = new Rect[count];
            if (count > 1)
            {
                currentStyle = firstStyle;
            }
            for (int i = 0; i < count; i++)
            {
                float w = 0;
                switch (buttonSize)
                {
                case GUI.ToolbarButtonSize.Fixed:
                    w = elemWidth;
                    break;

                case GUI.ToolbarButtonSize.FitToContents:
                    w = currentStyle.CalcSize(contents[i]).x;
                    break;
                }

                if (!addBorders)
                {
                    retval[i] = new Rect(xPos, yPos, w, elemHeight);
                }
                else
                {
                    retval[i] = currentStyle.margin.Add(new Rect(xPos, yPos, w, elemHeight));
                }

                //we round the values to the dpi-aware pixel grid
                retval[i] = GUIUtility.AlignRectToDevice(retval[i]);

                GUIStyle nextStyle = midStyle;
                if (i == count - 2 || i == xCount - 2)
                {
                    nextStyle = lastStyle;
                }

                xPos = retval[i].xMax + Mathf.Max(currentStyle.margin.right, nextStyle.margin.left);

                x++;
                if (x >= xCount)
                {
                    x         = 0;
                    yPos     += elemHeight + Mathf.Max(style.margin.top, style.margin.bottom);
                    xPos      = position.xMin;
                    nextStyle = firstStyle;
                }

                currentStyle = nextStyle;
            }
            return(retval);
        }
コード例 #4
0
        private void GenerateStencilClipEntryForRoundedRectBackground()
        {
            bool flag = this.currentElement.layout.width <= Mathf.Epsilon || this.currentElement.layout.height <= Mathf.Epsilon;

            if (!flag)
            {
                ComputedStyle computedStyle = this.currentElement.computedStyle;
                Vector2       a;
                Vector2       a2;
                Vector2       a3;
                Vector2       a4;
                MeshGenerationContextUtils.GetVisualElementRadii(this.currentElement, out a, out a2, out a3, out a4);
                float value  = computedStyle.borderTopWidth.value;
                float value2 = computedStyle.borderLeftWidth.value;
                float value3 = computedStyle.borderBottomWidth.value;
                float value4 = computedStyle.borderRightWidth.value;
                MeshGenerationContextUtils.RectangleParams rectParams = new MeshGenerationContextUtils.RectangleParams
                {
                    rect              = GUIUtility.AlignRectToDevice(this.currentElement.rect),
                    color             = Color.white,
                    topLeftRadius     = Vector2.Max(Vector2.zero, a - new Vector2(value2, value)),
                    topRightRadius    = Vector2.Max(Vector2.zero, a3 - new Vector2(value4, value)),
                    bottomLeftRadius  = Vector2.Max(Vector2.zero, a2 - new Vector2(value2, value3)),
                    bottomRightRadius = Vector2.Max(Vector2.zero, a4 - new Vector2(value4, value3)),
                    playmodeTintColor = ((this.currentElement.panel.contextType == ContextType.Editor) ? UIElementsUtility.editorPlayModeTintColor : Color.white)
                };
                rectParams.rect.x      = rectParams.rect.x + value2;
                rectParams.rect.y      = rectParams.rect.y + value;
                rectParams.rect.width  = rectParams.rect.width - (value2 + value4);
                rectParams.rect.height = rectParams.rect.height - (value + value3);
                bool flag2 = computedStyle.unityOverflowClipBox == OverflowClipBox.ContentBox;
                if (flag2)
                {
                    rectParams.rect.x      = rectParams.rect.x + computedStyle.paddingLeft.value.value;
                    rectParams.rect.y      = rectParams.rect.y + computedStyle.paddingTop.value.value;
                    rectParams.rect.width  = rectParams.rect.width - (computedStyle.paddingLeft.value.value + computedStyle.paddingRight.value.value);
                    rectParams.rect.height = rectParams.rect.height - (computedStyle.paddingTop.value.value + computedStyle.paddingBottom.value.value);
                }
                this.m_CurrentEntry.clipRectID          = this.m_ClipRectID;
                this.m_CurrentEntry.isStencilClipped    = this.m_StencilClip;
                this.m_CurrentEntry.isClipRegisterEntry = true;
                MeshBuilder.MakeSolidRect(rectParams, 1f, new MeshBuilder.AllocMeshData
                {
                    alloc = this.m_AllocRawVertsIndicesDelegate
                });
                bool flag3 = this.m_CurrentEntry.vertices.Length > 0 && this.m_CurrentEntry.indices.Length > 0;
                if (flag3)
                {
                    this.m_Entries.Add(this.m_CurrentEntry);
                    this.totalVertices += this.m_CurrentEntry.vertices.Length;
                    this.totalIndices  += this.m_CurrentEntry.indices.Length;
                    this.m_StencilClip  = true;
                    this.m_ClosingInfo.needsClosing = true;
                }
                this.m_CurrentEntry = default(UIRStylePainter.Entry);
            }
        }
コード例 #5
0
        public static RectStylePainterParameters GetDefault(VisualElement ve)
        {
            ComputedStyle style         = ve.computedStyle;
            var           painterParams = new RectStylePainterParameters
            {
                rect  = GUIUtility.AlignRectToDevice(ve.rect),
                color = style.backgroundColor.value,
            };

            BorderParameters.SetFromStyle(ref painterParams.border, style);
            return(painterParams);
        }
コード例 #6
0
 void OnGUI()
 {
     if (consoleOpen)
     {
         if (Event.current.keyCode == toggleKey)
         {
             GUIUtility.keyboardControl = 0;
         }
         ApplySkins();
         consoleRect = GUIUtility.AlignRectToDevice(consoleRect);
         consoleRect = GUI.Window(0, consoleRect, OnWindow, "");
     }
 }
コード例 #7
0
        public void DrawVisualElementBackground()
        {
            bool flag = this.currentElement.layout.width <= Mathf.Epsilon || this.currentElement.layout.height <= Mathf.Epsilon;

            if (!flag)
            {
                ComputedStyle computedStyle = this.currentElement.computedStyle;
                bool          flag2         = computedStyle.backgroundColor != Color.clear;
                if (flag2)
                {
                    MeshGenerationContextUtils.RectangleParams rectParams = new MeshGenerationContextUtils.RectangleParams
                    {
                        rect              = GUIUtility.AlignRectToDevice(this.currentElement.rect),
                        color             = computedStyle.backgroundColor.value,
                        playmodeTintColor = ((this.currentElement.panel.contextType == ContextType.Editor) ? UIElementsUtility.editorPlayModeTintColor : Color.white)
                    };
                    MeshGenerationContextUtils.GetVisualElementRadii(this.currentElement, out rectParams.topLeftRadius, out rectParams.bottomLeftRadius, out rectParams.topRightRadius, out rectParams.bottomRightRadius);
                    this.DrawRectangle(rectParams);
                }
                Background value = computedStyle.backgroundImage.value;
                bool       flag3 = value.texture != null || value.vectorImage != null;
                if (flag3)
                {
                    MeshGenerationContextUtils.RectangleParams rectParams2 = default(MeshGenerationContextUtils.RectangleParams);
                    bool flag4 = value.texture != null;
                    if (flag4)
                    {
                        rectParams2 = MeshGenerationContextUtils.RectangleParams.MakeTextured(GUIUtility.AlignRectToDevice(this.currentElement.rect), new Rect(0f, 0f, 1f, 1f), value.texture, computedStyle.unityBackgroundScaleMode.value, this.currentElement.panel.contextType);
                    }
                    else
                    {
                        bool flag5 = value.vectorImage != null;
                        if (flag5)
                        {
                            rectParams2 = MeshGenerationContextUtils.RectangleParams.MakeVectorTextured(GUIUtility.AlignRectToDevice(this.currentElement.rect), new Rect(0f, 0f, 1f, 1f), value.vectorImage, computedStyle.unityBackgroundScaleMode.value, this.currentElement.panel.contextType);
                        }
                    }
                    MeshGenerationContextUtils.GetVisualElementRadii(this.currentElement, out rectParams2.topLeftRadius, out rectParams2.bottomLeftRadius, out rectParams2.topRightRadius, out rectParams2.bottomRightRadius);
                    rectParams2.leftSlice   = computedStyle.unitySliceLeft.value;
                    rectParams2.topSlice    = computedStyle.unitySliceTop.value;
                    rectParams2.rightSlice  = computedStyle.unitySliceRight.value;
                    rectParams2.bottomSlice = computedStyle.unitySliceBottom.value;
                    bool flag6 = computedStyle.unityBackgroundImageTintColor != Color.clear;
                    if (flag6)
                    {
                        rectParams2.color = computedStyle.unityBackgroundImageTintColor.value;
                    }
                    this.DrawRectangle(rectParams2);
                }
            }
        }
コード例 #8
0
        public static TextureStylePainterParameters GetDefault(VisualElement ve)
        {
            ComputedStyle style         = ve.computedStyle;
            var           painterParams = new TextureStylePainterParameters
            {
                rect        = GUIUtility.AlignRectToDevice(ve.rect),
                uv          = new Rect(0, 0, 1, 1),
                color       = (Color)Color.white,
                texture     = style.backgroundImage.value.texture,
                scaleMode   = style.unityBackgroundScaleMode.value,
                sliceLeft   = style.unitySliceLeft.value,
                sliceTop    = style.unitySliceTop.value,
                sliceRight  = style.unitySliceRight.value,
                sliceBottom = style.unitySliceBottom.value
            };

            BorderParameters.SetFromStyle(ref painterParams.border, style);
            return(painterParams);
        }
コード例 #9
0
        public static TextureStylePainterParameters GetDefault(VisualElement ve)
        {
            IStyle style         = ve.style;
            var    painterParams = new TextureStylePainterParameters
            {
                rect = GUIUtility.AlignRectToDevice(ve.rect),
                uv   = new Rect(0, 0, 1, 1),
                // When the background color is not clear, we have to embed it into the texture...
                //  whereas if the color is clear, the white color is used...
                color       = (style.backgroundColor != Color.clear) ? (Color)style.backgroundColor : (Color)Color.white,
                texture     = style.backgroundImage,
                scaleMode   = style.backgroundScaleMode,
                sliceLeft   = style.sliceLeft,
                sliceTop    = style.sliceTop,
                sliceRight  = style.sliceRight,
                sliceBottom = style.sliceBottom
            };

            BorderParameters.SetFromStyle(ref painterParams.border, style);
            return(painterParams);
        }
コード例 #10
0
        private void PaintSubTree(Event e, VisualElement root, Matrix4x4 offset, VisualElement.ClippingOptions clippingOption, Rect currentGlobalClip)
        {
            if (root == null || root.panel != this)
            {
                return;
            }

            if (root.visible == false ||
                root.style.opacity.GetSpecifiedValueOrDefault(1.0f) < Mathf.Epsilon)
            {
                return;
            }

            // update clip
            if (root.clippingOptions != VisualElement.ClippingOptions.NoClipping)
            {
                var worldBound = ComputeAAAlignedBound(root.rect, offset * root.worldTransform);
                // are we and our children clipped?
                if (!worldBound.Overlaps(currentGlobalClip))
                {
                    return;
                }

                float x1 = Mathf.Max(worldBound.x, currentGlobalClip.x);
                float x2 = Mathf.Min(worldBound.xMax, currentGlobalClip.xMax);
                float y1 = Mathf.Max(worldBound.y, currentGlobalClip.y);
                float y2 = Mathf.Min(worldBound.yMax, currentGlobalClip.yMax);

                // new global clip and hierarchical clip space option.
                currentGlobalClip = new Rect(x1, y1, x2 - x1, y2 - y1);
                clippingOption    = root.clippingOptions;
            }
            else
            {
                //since our children are not clipped, there is no early out.
            }

            // Check for the rotated space - clipping issue.
            if (!whinedOnceAboutRotatedClipSpaceThisFrame && clippingOption == VisualElement.ClippingOptions.ClipContents && DoesMatrixHaveUnsupportedRotation(root.worldTransform))
            {
                Debug.LogError("Panel.PaintSubTree - Rotated clip-spaces are only supported by the VisualElement.ClippingOptions.ClipAndCacheContents mode. First offending Panel:'" + root.name + "'.");
                whinedOnceAboutRotatedClipSpaceThisFrame = true;
            }

            if (ShouldUsePixelCache(root))
            {
                // now actually paint the texture to previous group
                IStylePainter painter = stylePainter;

                // validate cache texture size first
                var worldBound = root.worldBound;

                Rect alignedRect;
                int  textureWidth, textureHeight;
                painter.currentWorldClip = currentGlobalClip;
                painter.currentTransform = offset * root.worldTransform;
                using (new GUIClip.ParentClipScope(painter.currentTransform, currentGlobalClip))
                {
                    alignedRect = GUIUtility.AlignRectToDevice(root.rect, out textureWidth, out textureHeight);
                }

                // Prevent the texture size from going empty, which may occur if the element has a sub-pixel size
                textureWidth  = Math.Max(textureWidth, 1);
                textureHeight = Math.Max(textureHeight, 1);

                var cache = root.renderData.pixelCache;

                if (cache != null &&
                    (cache.width != textureWidth || cache.height != textureHeight) &&
                    (!keepPixelCacheOnWorldBoundChange || root.IsDirty(ChangeType.Repaint)))
                {
                    Object.DestroyImmediate(cache);
                    cache = root.renderData.pixelCache = null;
                }

                // if the child node world transforms are not up to date due to changes below the pixel cache this is fine.
                if (root.IsDirty(ChangeType.Repaint) ||
                    root.renderData.pixelCache == null ||
                    !root.renderData.pixelCache.IsCreated())
                {
                    // Recreate as needed
                    if (cache == null)
                    {
                        root.renderData.pixelCache = cache = new RenderTexture(
                            textureWidth,
                            textureHeight,
                            32,         // depth
                            RenderTextureFormat.ARGB32,
                            RenderTextureReadWrite.sRGB);
                    }


                    bool hasRoundedBorderRects = (root.style.borderTopLeftRadius > 0 ||
                                                  root.style.borderTopRightRadius > 0 ||
                                                  root.style.borderBottomLeftRadius > 0 ||
                                                  root.style.borderBottomRightRadius > 0);

                    RenderTexture temporaryTexture = null;
                    var           old = RenderTexture.active;

                    try
                    {
                        // We first render to a temp texture, then blit the result into the result pixelCache again to mask the rounder corners
                        if (hasRoundedBorderRects)
                        {
                            temporaryTexture = cache = RenderTexture.GetTemporary(textureWidth, textureHeight, 32,
                                                                                  RenderTextureFormat.ARGB32, RenderTextureReadWrite.sRGB);
                        }

                        // render the texture again to clip the round rect borders
                        RenderTexture.active = cache;

                        GL.Clear(true, true, new Color(0, 0, 0, 0));

                        // Calculate the offset required to translate the origin of the rect to the upper left corner
                        // of the pixel cache. We need to round because the rect will be rounded when rendered.
                        Rect worldAlignedRect = root.LocalToWorld(alignedRect);
                        var  childrenOffset   = Matrix4x4.Translate(new Vector3(-worldAlignedRect.x, -worldAlignedRect.y, 0));

                        Matrix4x4 offsetWorldTransform = childrenOffset * root.worldTransform;

                        // reset clipping
                        var textureClip = new Rect(0, 0, worldAlignedRect.width, worldAlignedRect.height);
                        painter.currentTransform = offsetWorldTransform;

                        // Metal ignores the sRGBWrite flag and will always do linear to gamma conversions
                        // when writing to an sRGB buffer.  In this situation, we disable the manual sRGB
                        // conversion since it will be done automatically when writing to the framebuffer.
                        bool manualTex2SRGBEnabled = (SystemInfo.graphicsDeviceType != GraphicsDeviceType.Metal);
                        using (new GUIUtility.ManualTex2SRGBScope(manualTex2SRGBEnabled))
                            using (new GUIClip.ParentClipScope(painter.currentTransform, textureClip))
                            {
                                // Paint self
                                painter.currentWorldClip = textureClip;

                                stylePainter.opacity = root.style.opacity.GetSpecifiedValueOrDefault(1.0f);
                                root.DoRepaint(painter);
                                stylePainter.opacity = 1.0f;

                                root.ClearDirty(ChangeType.Repaint);

                                PaintSubTreeChildren(e, root, childrenOffset, clippingOption, textureClip);
                            }

                        if (hasRoundedBorderRects)
                        {
                            RenderTexture.active = root.renderData.pixelCache;

                            // Fix up transform for subtree to match texture upper left.
                            painter.currentTransform = Matrix4x4.identity;

                            using (new GUIUtility.ManualTex2SRGBScope(manualTex2SRGBEnabled))
                                using (new GUIClip.ParentClipScope(painter.currentTransform, textureClip))
                                {
                                    GL.Clear(true, true, new Color(0, 0, 0, 0));

                                    var textureParams = painter.GetDefaultTextureParameters(root);
                                    textureParams.texture   = cache;
                                    textureParams.scaleMode = ScaleMode.StretchToFill;
                                    textureParams.rect      = textureClip;

                                    textureParams.border.SetWidth(0.0f);

                                    // The rect of the temporary texture implicitly carries the scale factor of the
                                    // transform. Since we are blitting with an identity matrix, we need to scale the
                                    // radius manually.
                                    // We assume uniform positive scaling without rotations.
                                    Vector4 toScale     = new Vector4(1, 0, 0, 0);
                                    Vector4 scaled      = offsetWorldTransform * toScale;
                                    float   radiusScale = scaled.x;
                                    textureParams.border.SetRadius(
                                        textureParams.border.topLeftRadius * radiusScale,
                                        textureParams.border.topRightRadius * radiusScale,
                                        textureParams.border.bottomRightRadius * radiusScale,
                                        textureParams.border.bottomLeftRadius * radiusScale);

                                    // No border is drawn but the rounded corners are clipped properly.
                                    // Use premultiply alpha to avoid blending again.
                                    textureParams.usePremultiplyAlpha = true;
                                    painter.DrawTexture(textureParams);
                                }

                            // Redraw the border (border was already drawn in first root.DoRepaint call).
                            painter.currentTransform = offsetWorldTransform;
                            using (new GUIUtility.ManualTex2SRGBScope(manualTex2SRGBEnabled))
                                using (new GUIClip.ParentClipScope(painter.currentTransform, textureClip))
                                {
                                    painter.DrawBorder(root);
                                }
                        }
                    }
                    finally
                    {
                        cache = null;
                        if (temporaryTexture != null)
                        {
                            RenderTexture.ReleaseTemporary(temporaryTexture);
                        }
                        RenderTexture.active = old;
                    }
                }

                // now actually paint the texture to previous group
                painter.currentWorldClip = currentGlobalClip;
                painter.currentTransform = offset * root.worldTransform;

                using (new GUIClip.ParentClipScope(painter.currentTransform, currentGlobalClip))
                {
                    var painterParams = new TextureStylePainterParameters
                    {
                        rect                = GUIUtility.AlignRectToDevice(root.rect),
                        uv                  = new Rect(0, 0, 1, 1),
                        texture             = root.renderData.pixelCache,
                        color               = Color.white,
                        scaleMode           = ScaleMode.StretchToFill,
                        usePremultiplyAlpha = true
                    };
                    painter.DrawTexture(painterParams);
                }
            }
            else
            {
                stylePainter.currentTransform = offset * root.worldTransform;

                using (new GUIClip.ParentClipScope(stylePainter.currentTransform, currentGlobalClip))
                {
                    stylePainter.currentWorldClip = currentGlobalClip;
                    stylePainter.mousePosition    = root.worldTransform.inverse.MultiplyPoint3x4(e.mousePosition);

                    stylePainter.opacity = root.style.opacity.GetSpecifiedValueOrDefault(1.0f);

                    root.DoRepaint(stylePainter);
                    stylePainter.opacity = 1.0f;
                    root.ClearDirty(ChangeType.Repaint);

                    PaintSubTreeChildren(e, root, offset, clippingOption, currentGlobalClip);
                }
            }
        }
コード例 #11
0
 public static Rect AlignRectToDevice(Rect rect)
 {
     return(GUIUtility.AlignRectToDevice(rect));
 }
コード例 #12
0
 public static Rect AlignRectToDevice(Rect rect, out int widthInPixels, out int heightInPixels)
 {
     return(GUIUtility.AlignRectToDevice(rect, out widthInPixels, out heightInPixels));
 }
コード例 #13
0
        private void PaintSubTree(VisualElement root, Matrix4x4 offset, bool shouldClip, bool shouldCache, Rect currentGlobalClip)
        {
            if (root == null || root.panel != panel)
            {
                return;
            }

            if (root.visible == false ||
                root.style.opacity.GetSpecifiedValueOrDefault(1.0f) < Mathf.Epsilon)
            {
                return;
            }

            // update clip
            if (root.ShouldClip())
            {
                var worldBound = VisualElement.ComputeAAAlignedBound(root.rect, offset * root.worldTransform);
                // are we and our children clipped?
                if (!worldBound.Overlaps(currentGlobalClip))
                {
                    return;
                }

                float x1 = Mathf.Max(worldBound.x, currentGlobalClip.x);
                float x2 = Mathf.Min(worldBound.xMax, currentGlobalClip.xMax);
                float y1 = Mathf.Max(worldBound.y, currentGlobalClip.y);
                float y2 = Mathf.Min(worldBound.yMax, currentGlobalClip.yMax);

                // new global clip and hierarchical clip space option.
                currentGlobalClip = new Rect(x1, y1, x2 - x1, y2 - y1);
                shouldClip        = true;
                shouldCache       = root.clippingOptions == VisualElement.ClippingOptions.ClipAndCacheContents;
            }
            else
            {
                //since our children are not clipped, there is no early out.
            }

            // Check for the rotated space - clipping issue.
            if (!m_WhinedOnceAboutRotatedClipSpaceThisFrame && shouldClip && !shouldCache && DoesMatrixHaveUnsupportedRotation(root.worldTransform))
            {
                Debug.LogError("Panel.PaintSubTree - Rotated clip-spaces are only supported by the VisualElement.ClippingOptions.ClipAndCacheContents mode. First offending Panel:'" + root.name + "'.");
                m_WhinedOnceAboutRotatedClipSpaceThisFrame = true;
            }

            var prevElement = m_StylePainter.currentElement;

            m_StylePainter.currentElement = root;

            var repaintData = panel.repaintData;

            if (ShouldUsePixelCache(root))
            {
                // now actually paint the texture to previous group
                // validate cache texture size first
                var worldBound = root.worldBound;

                Rect alignedRect;
                int  textureWidth, textureHeight;
                repaintData.currentWorldClip = currentGlobalClip;
                repaintData.currentOffset    = offset;
                using (new GUIClip.ParentClipScope(offset * root.worldTransform, currentGlobalClip))
                {
                    alignedRect = GUIUtility.AlignRectToDevice(root.rect, out textureWidth, out textureHeight);
                }

                // Prevent the texture size from going empty, which may occur if the element has a sub-pixel size
                textureWidth  = Math.Max(textureWidth, 1);
                textureHeight = Math.Max(textureHeight, 1);

                var cache = root.renderData.pixelCache;

                if (cache != null &&
                    (cache.width != textureWidth || cache.height != textureHeight) &&
                    (!panel.keepPixelCacheOnWorldBoundChange || m_RepaintList.Contains(root)))
                {
                    Object.DestroyImmediate(cache);
                    cache = root.renderData.pixelCache = null;
                }

                // if the child node world transforms are not up to date due to changes below the pixel cache this is fine.
                if (m_RepaintList.Contains(root) ||
                    root.renderData.pixelCache == null ||
                    !root.renderData.pixelCache.IsCreated())
                {
                    // Recreate as needed
                    if (cache == null)
                    {
                        root.renderData.pixelCache = cache = new RenderTexture(
                            textureWidth,
                            textureHeight,
                            32,         // depth
                            RenderTextureFormat.ARGB32,
                            RenderTextureReadWrite.Linear);
                    }

                    bool hasRoundedBorderRects = (root.style.borderTopLeftRadius > 0 ||
                                                  root.style.borderTopRightRadius > 0 ||
                                                  root.style.borderBottomLeftRadius > 0 ||
                                                  root.style.borderBottomRightRadius > 0);

                    RenderTexture temporaryTexture = null;
                    var           old = RenderTexture.active;

                    try
                    {
                        // We first render to a temp texture, then blit the result into the result pixelCache again to mask the rounder corners
                        if (hasRoundedBorderRects)
                        {
                            // This should be an sRGB texture to conform with editor texture guidelines, however
                            // converting the cache to sRGB requires a shader to do it, and this whole pixel cache
                            // thing is slated to go away, so we take a short-cut here and use a linear texture
                            // along with the use of manualTex2SRGBEnabled to get the correct results.
                            temporaryTexture = cache = RenderTexture.GetTemporary(textureWidth, textureHeight, 32,
                                                                                  RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
                        }

                        // render the texture again to clip the round rect borders
                        RenderTexture.active = cache;

                        GL.Clear(true, true, new Color(0, 0, 0, 0));

                        // Calculate the offset required to translate the origin of the rect to the upper left corner
                        // of the pixel cache. We need to round because the rect will be rounded when rendered.
                        Rect worldAlignedRect = root.LocalToWorld(alignedRect);
                        var  childrenOffset   = Matrix4x4.Translate(new Vector3(-worldAlignedRect.x, -worldAlignedRect.y, 0));

                        Matrix4x4 offsetWorldTransform = childrenOffset * root.worldTransform;

                        // reset clipping
                        var textureClip = new Rect(0, 0, worldAlignedRect.width, worldAlignedRect.height);
                        repaintData.currentOffset = childrenOffset;

                        using (new GUIClip.ParentClipScope(offsetWorldTransform, textureClip))
                        {
                            // Paint self
                            repaintData.currentWorldClip = textureClip;

                            m_StylePainter.opacity = root.style.opacity.GetSpecifiedValueOrDefault(1.0f);
                            root.Repaint(m_StylePainter);
                            m_StylePainter.opacity = 1.0f;

                            PaintSubTreeChildren(root, childrenOffset, shouldClip, shouldCache, textureClip);
                        }

                        if (hasRoundedBorderRects)
                        {
                            RenderTexture.active = root.renderData.pixelCache;

                            bool oldManualTex2SRGBEnabled = GUIUtility.manualTex2SRGBEnabled;
                            GUIUtility.manualTex2SRGBEnabled = false;
                            using (new GUIClip.ParentClipScope(Matrix4x4.identity, textureClip))
                            {
                                GL.Clear(true, true, new Color(0, 0, 0, 0));

                                var textureParams = TextureStylePainterParameters.GetDefault(root);
                                textureParams.color     = Color.white;
                                textureParams.texture   = cache;
                                textureParams.scaleMode = ScaleMode.StretchToFill;
                                textureParams.rect      = textureClip;

                                textureParams.border.SetWidth(0.0f);

                                // The rect of the temporary texture implicitly carries the scale factor of the
                                // transform. Since we are blitting with an identity matrix, we need to scale the
                                // radius manually.
                                // We assume uniform positive scaling without rotations.
                                Vector4 toScale     = new Vector4(1, 0, 0, 0);
                                Vector4 scaled      = offsetWorldTransform * toScale;
                                float   radiusScale = scaled.x;
                                textureParams.border.SetRadius(
                                    textureParams.border.topLeftRadius * radiusScale,
                                    textureParams.border.topRightRadius * radiusScale,
                                    textureParams.border.bottomRightRadius * radiusScale,
                                    textureParams.border.bottomLeftRadius * radiusScale);

                                // No border is drawn but the rounded corners are clipped properly.
                                // Use premultiply alpha to avoid blending again.
                                textureParams.usePremultiplyAlpha = true;
                                m_StylePainter.DrawTexture(textureParams);
                            }

                            // Redraw the border (border was already drawn in first root.DoRepaint call).
                            using (new GUIClip.ParentClipScope(offsetWorldTransform, textureClip))
                            {
                                m_StylePainter.DrawBorder();
                            }
                            GUIUtility.manualTex2SRGBEnabled = oldManualTex2SRGBEnabled;
                        }
                    }
                    finally
                    {
                        cache = null;
                        if (temporaryTexture != null)
                        {
                            RenderTexture.ReleaseTemporary(temporaryTexture);
                        }
                        RenderTexture.active = old;
                    }
                }

                // now actually paint the texture to previous group
                repaintData.currentWorldClip = currentGlobalClip;
                repaintData.currentOffset    = offset;

                bool oldManualTex2SRGBEnabled2 = GUIUtility.manualTex2SRGBEnabled;
                GUIUtility.manualTex2SRGBEnabled = false;
                using (new GUIClip.ParentClipScope(offset * root.worldTransform, currentGlobalClip))
                {
                    var painterParams = new TextureStylePainterParameters
                    {
                        rect                = GUIUtility.AlignRectToDevice(root.rect),
                        uv                  = new Rect(0, 0, 1, 1),
                        texture             = root.renderData.pixelCache,
                        color               = Color.white,
                        scaleMode           = ScaleMode.StretchToFill,
                        usePremultiplyAlpha = true
                    };

                    // We must not reapply the editor Play Mode Tint if it was already applied !
                    var playModeTint = UIElementsUtility.editorPlayModeTintColor;
                    UIElementsUtility.editorPlayModeTintColor = Color.white;

                    m_StylePainter.DrawTexture(painterParams);
                    UIElementsUtility.editorPlayModeTintColor = playModeTint;
                }
                GUIUtility.manualTex2SRGBEnabled = oldManualTex2SRGBEnabled2;
            }
            else
            {
                repaintData.currentOffset = offset;

                using (new GUIClip.ParentClipScope(offset * root.worldTransform, currentGlobalClip))
                {
                    repaintData.currentWorldClip = currentGlobalClip;
                    repaintData.mousePosition    = root.worldTransform.inverse.MultiplyPoint3x4(repaintData.repaintEvent.mousePosition);

                    m_StylePainter.opacity = root.style.opacity.GetSpecifiedValueOrDefault(1.0f);
                    root.Repaint(m_StylePainter);
                    m_StylePainter.opacity = 1.0f;


                    PaintSubTreeChildren(root, offset, shouldClip, shouldCache, currentGlobalClip);
                }
            }

            m_StylePainter.currentElement = prevElement;
        }