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); }
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 )); }