/// <summary>Updates the FlatWorldUI so it builds the mesh for this element.</summary>
        private void UpdateRenderer(LayoutBox box, float width, float height)
        {
            // - Set w/h to width and height:
            int w = (int)width;
            int h = (int)height;

            // Resize the renderer (which will emit a changed image event):
            Renderer.SetDimensions(w, h);

            // Temporarily set the positioning of 'box' such that it's at the origin:
            int      _pos      = box.PositionMode;
            BoxStyle _position = box.Position;

            // Clear:
            box.Position     = new BoxStyle(0f, float.MaxValue, float.MaxValue, 0f);
            box.PositionMode = PositionMode.Fixed;

            // Put the RenderData in the render only queue of *Renderer* and ask it to layout now:
            RenderableData _next     = RenderData.Next;
            UpdateMode     _mode     = RenderData.NextUpdateMode;
            RenderableData _ancestor = RenderData.Ancestor;

            // Clear:
            RenderData.Next           = null;
            RenderData.NextUpdateMode = UpdateMode.Render;
            RenderData.Ancestor       = null;

            // Queue:
            Renderer.Renderer.StylesToUpdate    = RenderData;
            Renderer.Renderer.HighestUpdateMode = UpdateMode.Render;

            // Draw now!
            Renderer.Renderer.Update();

            // Restore (box):
            box.Position     = _position;
            box.PositionMode = _pos;

            // Restore (queue):
            RenderData.Next           = _next;
            RenderData.NextUpdateMode = _mode;
            RenderData.Ancestor       = _ancestor;
        }
示例#2
0
        /// <summary>Renders and performs a layout of the round corners.</summary>
        public void Layout(Color colour, LayoutBox box, Renderman renderer, int i)
        {
            // Get the co-ord of the top edge:
            float top  = box.Y;
            float left = box.X;

            // Get border widths:
            BoxStyle border = box.Border;

            // And the dimensions of the lines:
            // Note: boxwidth doesn't include the left/right widths to prevent overlapping.
            float boxWidth  = box.PaddedWidth;
            float boxHeight = box.PaddedHeight + border.Top + border.Bottom;

            switch (i)
            {
            case 0:
                // Top:

                // Move over by the top-left corner:
                if (TopLeft != null)
                {
                    TopLeft.Colour = colour;

                    // Render the top left corner:
                    TopLeft.RenderInverse(box, renderer, left, top);
                }

                break;

            case 1:
                // Right:

                if (TopRight != null)
                {
                    TopRight.Colour = colour;

                    // Render the top right corners inverse now:
                    TopRight.RenderInverse(box, renderer, left + boxWidth + border.Left + border.Right, top);
                }

                break;

            case 2:
                // Bottom:

                if (BottomRight != null)
                {
                    BottomRight.Colour = colour;

                    // Render the bottom right corners inverse now:
                    BottomRight.RenderInverse(box, renderer, left + boxWidth + border.Left + border.Right, top + boxHeight);
                }

                break;

            case 3:
                // Left:

                if (BottomLeft != null)
                {
                    BottomLeft.Colour = colour;

                    // Render the bottom left corners inverse now:
                    BottomLeft.RenderInverse(box, renderer, left, top + boxHeight);
                }

                break;
            }
        }
示例#3
0
        /// <summary>Recomputes the inner arc. The inner arc is special because it depends on border width.
        /// The two borders that this corner connects may be different widths, so it may have to transition from one thickness to another.</summary>
        private void RecomputeInnerArc(BoxStyle widths)
        {
            // How big is the outer arc?
            int size = OuterArc.Length;

            if (InnerArc == null || InnerArc.Length != size)
            {
                // Create the set now:
                InnerArc = new Vector2[size];
            }

            // We're next going to be doing some polars here. Everything is clockwise.
            // We're essentially going to rotate around the virtual center of a circle, changing our radius as we go.

            // The current angle in radians:
            float currentAngle;

            // The virtual center of the circle, relative to the corner:
            float centerX;
            float centerY;

            // The source border width:
            float sourceWidth;
            // The target border width:
            float targetWidth;

            // Get radius as a float:
            float cornerRadius = CornerRadius;

            // The starting radius:
            float radius = cornerRadius;

            switch (Position)
            {
            case RoundCornerPosition.TopLeft:

                // The center is up on Y and up on X:
                centerX = radius;
                centerY = radius;

                // The angle starts at..
                currentAngle = Mathf.PI;

                // Get the widths:
                sourceWidth = widths.Left;
                targetWidth = widths.Top;

                break;

            case RoundCornerPosition.TopRight:

                // The center is up on Y and down on X:
                centerX = -radius;
                centerY = radius;

                // The angle starts at..
                currentAngle = Mathf.PI * 1.5f;

                // Get the widths:
                sourceWidth = widths.Top;
                targetWidth = widths.Right;

                break;

            case RoundCornerPosition.BottomRight:

                // The center is down on Y and down on X:
                centerX = -radius;
                centerY = -radius;

                // The angle starts at..
                currentAngle = 0f;

                // Get the widths:
                sourceWidth = widths.Right;
                targetWidth = widths.Bottom;

                break;

            default:
            case RoundCornerPosition.BottomLeft:

                // The center is down on Y and up on X:
                centerX = radius;
                centerY = -radius;

                // The angle starts at..
                currentAngle = Mathf.PI * 0.5f;

                // Get the widths:
                sourceWidth = widths.Bottom;
                targetWidth = widths.Left;

                break;
            }

            // Remove source width from radius:
            radius -= sourceWidth;

            // What's the maximum number of iterations?
            float maximumValue = (float)(size - 1);

            // Figure out delta angle (we'll be travelling through PI/2 degrees):
            float deltaAngle = (Mathf.PI * 0.5f) / maximumValue;

            // Figure out delta radius based on source/target:
            float deltaRadius = (sourceWidth - targetWidth) / maximumValue;

            // Next, for each point..
            for (int i = 0; i < size; i++)
            {
                // Get the cos/sin of the current angle:
                float cosAngle = Mathf.Cos(currentAngle);
                float sinAngle = Mathf.Sin(currentAngle);

                // And also the inner arc value:
                InnerArc[i] = new Vector2(centerX + (cosAngle * radius), centerY + (sinAngle * radius));

                // Move the angle along:
                currentAngle += deltaAngle;

                // Move the radius along:
                radius += deltaRadius;
            }
        }
        internal override void Layout(LayoutBox box, Renderman renderer)
        {
            if (Corners != null)
            {
                Corners.PreLayout();
            }

            ComputedStyle computed = RenderData.computedStyle;

            // Find the zIndex:
            // NB: At same depth as BGColour - right at the back.
            float zIndex = (computed.ZIndex - 0.006f);

            // Get the co-ord of the top edge:
            float top  = box.Y;
            float left = box.X;

            // Get the border widths:
            BoxStyle width = box.Border;

            // Move top by the widths:
            top  += width.Top;
            left += width.Left;

            // And the dimensions of the lines:
            float boxWidth  = box.PaddedWidth;
            float boxHeight = box.PaddedHeight;

            // Get the other dimensions:
            float topY    = top - width.Top;
            float right   = left + boxWidth;
            float rightX  = right + width.Right;
            float bottom  = top + boxHeight;
            float bottomY = bottom + width.Bottom;
            float leftX   = left - width.Left;
            int   segment = renderer.Segment;

            Transformation transform = renderer.Transform;

            BoxRegion screenRegion = new BoxRegion();

            // Get the default colour - that's the same as the text colour:
            Color colour = Color.black;

            // Is the border multicoloured?
            bool multiColour = false;

            // Does this border have a colour?
            if (BaseColour == null)
            {
                // Grab the text colour if there is one:
                if (RenderData.Text != null)
                {
                    // It's the same as the font colour:
                    colour = RenderData.Text.BaseColour * renderer.ColorOverlay;
                }
                else
                {
                    // Nope - We need to set alpha:
                    colour.a = renderer.ColorOverlay.a;
                }
            }
            else if (BaseColour.Count == 1)
            {
                colour = BaseColour[0].GetColour(RenderData, Css.Properties.BorderColor.GlobalProperty) * renderer.ColorOverlay;
            }
            else
            {
                multiColour = true;
            }

            // Handle border-radius:
            if (Corners != null)
            {
                for (int i = 0; i < 4; i++)
                {
                    if (multiColour)
                    {
                        colour = BaseColour[i].GetColour(RenderData, Css.Properties.BorderColor.GlobalProperty) * renderer.ColorOverlay;
                    }

                    Corners.Layout(colour, box, renderer, i);
                }
            }

            // Get clipper:
            BoxRegion clip = renderer.ClippingBoundary;

            float origLeftX   = leftX;
            float origTopY    = topY;
            float origBottomY = bottomY;
            float origRightX  = rightX;

            // top and topY:
            if (top < clip.Y)
            {
                top = clip.Y;
            }
            else if (top > clip.MaxY)
            {
                top = clip.MaxY;
            }

            if (topY < clip.Y)
            {
                topY = clip.Y;
            }

            // bottom and bottomY:
            if (bottom > clip.MaxY)
            {
                bottom = clip.MaxY;
            }
            else if (bottom < clip.Y)
            {
                bottom = clip.Y;
            }

            if (bottomY > clip.MaxY)
            {
                bottomY = clip.MaxY;
            }

            // right and rightX:
            if (right < clip.X)
            {
                right = clip.X;
            }
            else if (right > clip.MaxX)
            {
                right = clip.MaxX;
            }

            // rightX vs clip.MaxX
            if (rightX > clip.MaxX)
            {
                rightX = clip.MaxX;
            }

            // left and leftX:
            if (left < clip.X)
            {
                left = clip.X;
            }
            else if (left > clip.MaxX)
            {
                left = clip.MaxX;
            }

            if (leftX < clip.X)
            {
                leftX = clip.X;
            }

            float cornerPointA;
            float cornerPointB;

            for (int i = 0; i < 4; i++)
            {
                // Does this border have multiple colours?
                if (multiColour)
                {
                    colour = BaseColour[i].GetColour(RenderData, Css.Properties.BorderColor.GlobalProperty) * renderer.ColorOverlay;
                }

                // Add to region:
                switch (i)
                {
                case 0:
                    // Top.
                    screenRegion.SetPoints(leftX, topY, rightX, top);
                    break;

                case 1:
                    // Right.

                    // We only draw the right border if 'segment' includes 'end'
                    if ((segment & LineBoxSegment.End) == 0)
                    {
                        goto NextLine;
                    }

                    screenRegion.SetPoints(right, topY, rightX, bottomY);
                    break;

                case 2:
                    // Bottom.

                    screenRegion.SetPoints(leftX, bottom, rightX, bottomY);
                    break;

                case 3:
                    // Left.

                    // Similarly, we only draw left if segment includes 'start':
                    if ((segment & LineBoxSegment.Start) == 0)
                    {
                        goto NextLine;
                    }

                    screenRegion.SetPoints(leftX, topY, left, bottomY);
                    break;
                }

                if (screenRegion.Overlaps(clip))
                {
                    // It's visible.

                    // Ensure we have a batch (doesn't change graphics or font textures, thus both null):
                    renderer.SetupBatch(this, null, null);

                    // And get our block ready:
                    MeshBlock block = Add(renderer);

                    // Set the UV to that of the solid block colour pixel:
                    block.SetSolidColourUV();

                    // Set the border colour:
                    block.SetColour(colour);

                    // Apply verts:

                    switch (i)
                    {
                    case 0:

                        // Top:
                        if (Corners == null)
                        {
                            block.VertexTopLeft     = renderer.PixelToWorldUnit(leftX, topY, zIndex);
                            block.VertexTopRight    = renderer.PixelToWorldUnit(rightX, topY, zIndex);
                            block.VertexBottomLeft  = renderer.PixelToWorldUnit(left, top, zIndex);
                            block.VertexBottomRight = renderer.PixelToWorldUnit(right, top, zIndex);
                        }
                        else
                        {
                            // Top left/right corners:
                            cornerPointA = origLeftX + Corners.TopLeftRadius;
                            cornerPointB = origRightX - Corners.TopRightRadius;

                            if (cornerPointA < clip.X)
                            {
                                cornerPointA = clip.X;
                            }

                            if (cornerPointB > clip.MaxX)
                            {
                                cornerPointB = clip.MaxX;
                            }

                            // Note that we use leftX/rightX for all of them.
                            // That's because the corner has a 'straight' edge.
                            block.VertexTopLeft     = renderer.PixelToWorldUnit(cornerPointA, topY, zIndex);
                            block.VertexTopRight    = renderer.PixelToWorldUnit(cornerPointB, topY, zIndex);
                            block.VertexBottomLeft  = renderer.PixelToWorldUnit(cornerPointA, top, zIndex);
                            block.VertexBottomRight = renderer.PixelToWorldUnit(cornerPointB, top, zIndex);
                        }

                        break;

                    case 1:

                        // Right:
                        if (Corners == null)
                        {
                            block.VertexTopLeft     = renderer.PixelToWorldUnit(right, top, zIndex);
                            block.VertexTopRight    = renderer.PixelToWorldUnit(rightX, topY, zIndex);
                            block.VertexBottomLeft  = renderer.PixelToWorldUnit(right, bottom, zIndex);
                            block.VertexBottomRight = renderer.PixelToWorldUnit(rightX, bottomY, zIndex);
                        }
                        else
                        {
                            // Top right/ bottom right corners:
                            cornerPointA = origTopY + Corners.TopRightRadius;
                            cornerPointB = origBottomY - Corners.BottomRightRadius;


                            if (cornerPointA < clip.Y)
                            {
                                cornerPointA = clip.Y;
                            }

                            if (cornerPointB > clip.MaxY)
                            {
                                cornerPointB = clip.MaxY;
                            }

                            // Note that we use topY/bottomY for all of them.
                            block.VertexTopLeft     = renderer.PixelToWorldUnit(right, cornerPointA, zIndex);
                            block.VertexTopRight    = renderer.PixelToWorldUnit(rightX, cornerPointA, zIndex);
                            block.VertexBottomLeft  = renderer.PixelToWorldUnit(right, cornerPointB, zIndex);
                            block.VertexBottomRight = renderer.PixelToWorldUnit(rightX, cornerPointB, zIndex);
                        }

                        break;

                    case 2:

                        // Bottom:
                        if (Corners == null)
                        {
                            block.VertexTopLeft     = renderer.PixelToWorldUnit(left, bottom, zIndex);
                            block.VertexTopRight    = renderer.PixelToWorldUnit(right, bottom, zIndex);
                            block.VertexBottomLeft  = renderer.PixelToWorldUnit(leftX, bottomY, zIndex);
                            block.VertexBottomRight = renderer.PixelToWorldUnit(rightX, bottomY, zIndex);
                        }
                        else
                        {
                            // Bottom left/ bottom right corners:
                            // Note that we use leftX/rightX for all of them.
                            cornerPointA = origLeftX + Corners.BottomLeftRadius;
                            cornerPointB = origRightX - Corners.BottomRightRadius;

                            if (cornerPointA < clip.X)
                            {
                                cornerPointA = clip.X;
                            }

                            if (cornerPointB > clip.MaxX)
                            {
                                cornerPointB = clip.MaxX;
                            }

                            block.VertexTopLeft     = renderer.PixelToWorldUnit(cornerPointA, bottom, zIndex);
                            block.VertexTopRight    = renderer.PixelToWorldUnit(cornerPointB, bottom, zIndex);
                            block.VertexBottomLeft  = renderer.PixelToWorldUnit(cornerPointA, bottomY, zIndex);
                            block.VertexBottomRight = renderer.PixelToWorldUnit(cornerPointB, bottomY, zIndex);
                        }

                        break;

                    case 3:

                        // Left:
                        if (Corners == null)
                        {
                            block.VertexTopLeft     = renderer.PixelToWorldUnit(leftX, topY, zIndex);
                            block.VertexTopRight    = renderer.PixelToWorldUnit(left, top, zIndex);
                            block.VertexBottomLeft  = renderer.PixelToWorldUnit(leftX, bottomY, zIndex);
                            block.VertexBottomRight = renderer.PixelToWorldUnit(left, bottom, zIndex);
                        }
                        else
                        {
                            // Top right/ bottom right corners:
                            cornerPointA = origTopY + Corners.TopLeftRadius;
                            cornerPointB = origBottomY + width.Bottom - Corners.BottomLeftRadius;

                            if (cornerPointA < clip.Y)
                            {
                                cornerPointA = clip.Y;
                            }

                            if (cornerPointB > clip.MaxY)
                            {
                                cornerPointB = clip.MaxY;
                            }

                            block.VertexTopLeft     = renderer.PixelToWorldUnit(leftX, cornerPointA, zIndex);
                            block.VertexTopRight    = renderer.PixelToWorldUnit(left, cornerPointA, zIndex);
                            block.VertexBottomLeft  = renderer.PixelToWorldUnit(leftX, cornerPointB, zIndex);
                            block.VertexBottomRight = renderer.PixelToWorldUnit(left, cornerPointB, zIndex);
                        }

                        break;
                    }

                    // Done!
                    block.Done(transform);
                }

NextLine:
                continue;
            }
        }