Exemple #1
0
            public Batch Combine(Batch lhs, Batch rhs)
            {
                var bl = (BitmapBatch)lhs;
                var br = (BitmapBatch)rhs;

                using (var b = br._DrawCalls.GetBuffer(false)) {
                    var drawCallsRhsBuffer = b.Data;

                    for (int i = 0, l = b.Count; i < l; i++)
                    {
                        if (!BitmapDrawCall.CheckValid(ref drawCallsRhsBuffer[i + b.Offset]))
                        {
                            // FIXME
                            // throw new Exception("Invalid draw call in batch");
                            continue;
                        }

                        bl._DrawCalls.Add(ref drawCallsRhsBuffer[i + b.Offset]);
                    }
                }

                br._DrawCalls.Clear();
                rhs.SetCombined(true);
                if (CaptureStackTraces)
                {
                    if (lhs.BatchesCombinedIntoThisOne == null)
                    {
                        lhs.BatchesCombinedIntoThisOne = new UnorderedList <Batch>();
                    }

                    lhs.BatchesCombinedIntoThisOne.Add(rhs);
                }

                return(lhs);
            }
Exemple #2
0
        public static void DrawCursor(Game game, ref ImperativeRenderer renderer, Vector2 itemPosition, Vector2 menuSize, Vector2 itemSize)
        {
            var time = (float)Time.Seconds;
            var scale = Vector2.One;
            var offset = Arithmetic.Pulse(time, 0.6f, 0.75f);
            var origin = new Vector2(0.5f, 0.5f);
            var bounds = new Bounds(Vector2.Zero, Vector2.One);

            itemPosition.X -= (game.Cursor.Width * offset);
            itemPosition.Y += (itemSize.Y / 2.0f);
            var drawCall = new Squared.Render.BitmapDrawCall(
                game.Cursor, itemPosition, bounds, Color.White, scale, origin
            );

            renderer.Draw(ref drawCall);

            itemPosition.X += menuSize.X + (game.Cursor.Width * offset * 2.0f);
            drawCall.Position = itemPosition;
            drawCall.Mirror(true, false);

            renderer.Draw(ref drawCall);
        }
        public static StringLayout LayoutString(
            this SpriteFont font, AbstractString text, ArraySegment <BitmapDrawCall>?buffer = null,
            Vector2?position         = null, Color?color     = null, float scale = 1, float sortKey = 0,
            int characterSkipCount   = 0, int characterLimit = int.MaxValue,
            float xOffsetOfFirstLine = 0, float?lineBreakAtX = null,
            bool alignToPixels       = false,
            Dictionary <char, KerningAdjustment> kerningAdjustments = null
            )
        {
            if (text.IsNull)
            {
                throw new ArgumentNullException("text");
            }

            ArraySegment <BitmapDrawCall> _buffer;

            if (buffer.HasValue)
            {
                _buffer = buffer.Value;
            }
            else
            {
                _buffer = new ArraySegment <BitmapDrawCall>(new BitmapDrawCall[text.Length]);
            }

            if (_buffer.Count < text.Length)
            {
                throw new ArgumentException("buffer too small", "buffer");
            }

            if (kerningAdjustments == null)
            {
                kerningAdjustments = StringLayout.GetDefaultKerningAdjustments(font);
            }

            var spacing     = font.Spacing;
            var lineSpacing = font.LineSpacing;
            var glyphSource = font.GetGlyphSource();

            var actualPosition  = position.GetValueOrDefault(Vector2.Zero);
            var characterOffset = new Vector2(xOffsetOfFirstLine, 0);
            var totalSize       = Vector2.Zero;

            Bounds firstCharacterBounds = default(Bounds), lastCharacterBounds = default(Bounds);

            var drawCall = new BitmapDrawCall(
                glyphSource.Texture, default(Vector2), default(Bounds), color.GetValueOrDefault(Color.White), scale
                );

            drawCall.SortKey = sortKey;

            float rectScaleX = 1f / glyphSource.Texture.Width;
            float rectScaleY = 1f / glyphSource.Texture.Height;

            int bufferWritePosition = _buffer.Offset;
            int drawCallsWritten    = 0;

            bool firstCharacterEver   = true;
            bool firstCharacterOfLine = true;

            for (int i = 0, l = text.Length; i < l; i++)
            {
                var ch = text[i];

                var lineBreak = false;
                if (ch == '\r')
                {
                    if (((i + 1) < l) && (text[i + 1] == '\n'))
                    {
                        i += 1;
                    }

                    lineBreak = true;
                }
                else if (ch == '\n')
                {
                    lineBreak = true;
                }

                bool deadGlyph;

                Glyph glyph;
                deadGlyph = !glyphSource.GetGlyph(ch, out glyph);

                KerningAdjustment kerningAdjustment;
                if ((kerningAdjustments != null) && kerningAdjustments.TryGetValue(ch, out kerningAdjustment))
                {
                    glyph.LeftSideBearing  += kerningAdjustment.LeftSideBearing;
                    glyph.Width            += kerningAdjustment.Width;
                    glyph.RightSideBearing += kerningAdjustment.RightSideBearing;
                }

                if (!deadGlyph)
                {
                    var x = characterOffset.X + glyph.LeftSideBearing + glyph.RightSideBearing + glyph.Width + spacing;
                    if (x >= lineBreakAtX)
                    {
                        lineBreak = true;
                    }
                }

                if (lineBreak)
                {
                    characterOffset.X    = 0;
                    characterOffset.Y   += lineSpacing;
                    firstCharacterOfLine = true;
                }

                if (deadGlyph)
                {
                    characterSkipCount--;
                    characterLimit--;
                    continue;
                }

                characterOffset.X += spacing;

                lastCharacterBounds = Bounds.FromPositionAndSize(
                    characterOffset, new Vector2(
                        glyph.LeftSideBearing + glyph.Width + glyph.RightSideBearing,
                        font.LineSpacing
                        )
                    );

                if (firstCharacterEver)
                {
                    firstCharacterBounds = lastCharacterBounds;
                    firstCharacterEver   = false;
                }

                characterOffset.X += glyph.LeftSideBearing;

                if (firstCharacterOfLine)
                {
                    characterOffset.X    = Math.Max(characterOffset.X, 0);
                    firstCharacterOfLine = false;
                }

                if (characterSkipCount <= 0)
                {
                    if (characterLimit <= 0)
                    {
                        break;
                    }

                    var glyphPosition = new Vector2(
                        actualPosition.X + (glyph.Cropping.X + characterOffset.X) * scale,
                        actualPosition.Y + (glyph.Cropping.Y + characterOffset.Y) * scale
                        );

                    drawCall.TextureRegion = glyphSource.Texture.BoundsFromRectangle(ref glyph.BoundsInTexture);
                    if (alignToPixels)
                    {
                        drawCall.Position = glyphPosition.Floor();
                    }
                    else
                    {
                        drawCall.Position = glyphPosition;
                    }

                    _buffer.Array[bufferWritePosition] = drawCall;

                    bufferWritePosition += 1;
                    drawCallsWritten    += 1;

                    characterLimit--;
                }
                else
                {
                    characterSkipCount--;
                }

                characterOffset.X += (glyph.Width + glyph.RightSideBearing);

                totalSize.X = Math.Max(totalSize.X, characterOffset.X);
                totalSize.Y = Math.Max(totalSize.Y, characterOffset.Y + font.LineSpacing);
            }

            var segment = new ArraySegment <BitmapDrawCall>(
                _buffer.Array, _buffer.Offset, drawCallsWritten
                );

            if (segment.Count > text.Length)
            {
                throw new InvalidDataException();
            }

            return(new StringLayout(
                       position.GetValueOrDefault(), totalSize, font.LineSpacing,
                       firstCharacterBounds, lastCharacterBounds,
                       segment
                       ));
        }