public override void Draw(IDrawDevice device) { if (gameobj == null) { return; } float timeMult = Time.TimeMult; for (int j = 0; j < circleEffectData.Length; j++) { ref CircleEffect circle = ref circleEffectData[j]; if (circle.Alpha <= 0f) { continue; } int segmentNum = MathF.Clamp(MathF.RoundToInt(MathF.Pow(circle.Radius, 0.65f) * 2.5f), 4, 32); float angle = 0.0f; for (int i = 0; i < segmentNum; i++) { vertices[i].Pos.X = circle.Pos.X + (float)Math.Sin(angle) * circle.Radius; vertices[i].Pos.Y = circle.Pos.Y - (float)Math.Cos(angle) * circle.Radius; vertices[i].Pos.Z = circle.Pos.Z - 10f; vertices[i].Color = new ColorRgba(1f, circle.Alpha); angle += (MathF.TwoPi / segmentNum); } device.AddVertices(material, VertexMode.LineLoop, vertices, 0, segmentNum); circle.Radius -= timeMult * 0.8f; circle.Alpha -= timeMult * 0.03f; }
private void RenderTexturedBackground(IDrawDevice device) { if (!cachedTexturedBackground.IsAvailable) { return; } float timeMult = Time.TimeMult; backgroundX += timeMult * 1.2f; backgroundY += timeMult * -0.2f + timeMult * MathF.Sin(backgroundPhase) * 0.6f; backgroundPhase += timeMult * 0.001f; Vector3 renderPos = new Vector3(0, 0, 600); // Fit the target rect to actual pixel coordinates to avoid unnecessary filtering offsets renderPos.X = MathF.Round(renderPos.X); renderPos.Y = MathF.Round(renderPos.Y); if (MathF.RoundToInt(device.TargetSize.X) != (MathF.RoundToInt(device.TargetSize.X) / 2) * 2) { renderPos.X += 0.5f; } if (MathF.RoundToInt(device.TargetSize.Y) != (MathF.RoundToInt(device.TargetSize.Y) / 2) * 2) { // AMD Bugfix? renderPos.Y -= 0.004f; } // Reserve the required space for vertex data in our locally cached buffer int neededVertices = 4; if (cachedVertices == null || cachedVertices.Length < neededVertices) { cachedVertices = new VertexC1P3T2[neededVertices]; } // Render it as world-space fullscreen quad cachedVertices[0].Pos = new Vector3(renderPos.X, renderPos.Y, renderPos.Z); cachedVertices[1].Pos = new Vector3(renderPos.X + device.TargetSize.X, renderPos.Y, renderPos.Z); cachedVertices[2].Pos = new Vector3(renderPos.X + device.TargetSize.X, renderPos.Y + device.TargetSize.Y, renderPos.Z); cachedVertices[3].Pos = new Vector3(renderPos.X, renderPos.Y + device.TargetSize.Y, renderPos.Z); cachedVertices[0].TexCoord = new Vector2(0.0f, 0.0f); cachedVertices[1].TexCoord = new Vector2(1f, 0.0f); cachedVertices[2].TexCoord = new Vector2(1f, 1f); cachedVertices[3].TexCoord = new Vector2(0.0f, 1f); cachedVertices[0].Color = cachedVertices[1].Color = cachedVertices[2].Color = cachedVertices[3].Color = ColorRgba.White; // Setup custom pixel shader BatchInfo material = device.RentMaterial(); material.Technique = texturedBackgroundShader; material.MainTexture = cachedTexturedBackground; material.SetValue("horizonColor", horizonColor); material.SetValue("shift", new Vector2(backgroundX, backgroundY)); material.SetValue("parallaxStarsEnabled", 0f); device.AddVertices(material, VertexMode.Quads, cachedVertices, 0, 4); }
private void DrawLayer(IDrawDevice device, ref TileMapLayer layer, int cacheIndex) { if (!layer.Visible) { return; } Vector2 viewSize = device.TargetSize; Vector3 viewCenter = device.ViewerPos; Point2 tileCount = new Point2(layer.LayoutWidth, layer.Layout.Length / layer.LayoutWidth); Vector2 tileSize = new Vector2(tileset.TileSize, tileset.TileSize); // Update offsets for moving layers if (MathF.Abs(layer.AutoSpeedX) > 0) { layer.OffsetX += layer.AutoSpeedX * Time.TimeMult; if (layer.RepeatX) { if (layer.AutoSpeedX > 0) { while (layer.OffsetX > (tileCount.X * 32)) { layer.OffsetX -= (tileCount.X * 32); } } else { while (layer.OffsetX < 0) { layer.OffsetX += (tileCount.X * 32); } } } } if (MathF.Abs(layer.AutoSpeedY) > 0) { layer.OffsetY += layer.AutoSpeedY * Time.TimeMult; if (layer.RepeatY) { if (layer.AutoSpeedY > 0) { while (layer.OffsetY > (tileCount.Y * 32)) { layer.OffsetY -= (tileCount.Y * 32); } } else { while (layer.OffsetY < 0) { layer.OffsetY += (tileCount.Y * 32); } } } } // Get current layer offsets and speeds float loX = layer.OffsetX; float loY = layer.OffsetY - (layer.UseInherentOffset ? (viewSize.Y - 200) / 2 : 0); // Find out coordinates for a tile from outside the boundaries from topleft corner of the screen float x1 = viewCenter.X - 70 - (viewSize.X * 0.5f); float y1 = viewCenter.Y - 70 - (viewSize.Y * 0.5f); if (layer.BackgroundStyle != BackgroundStyle.Plain && tileCount.Y == 8 && tileCount.X == 8) { const float PerspectiveSpeedX = 0.4f; const float PerspectiveSpeedY = 0.16f; RenderTexturedBackground(device, ref layer, cacheIndex, (x1 * PerspectiveSpeedX + loX), (y1 * PerspectiveSpeedY + loY)); } else { // Figure out the floating point offset from the calculated coordinates and the actual tile // corner coordinates float xt = TranslateCoordinate(x1, layer.SpeedX, loX, false, viewSize.Y, viewSize.X); float yt = TranslateCoordinate(y1, layer.SpeedY, loY, true, viewSize.Y, viewSize.X); float remX = xt % 32f; float remY = yt % 32f; // Calculate the index (on the layer map) of the first tile that needs to be drawn to the // position determined earlier int tileX, tileY, tileAbsX, tileAbsY; // Get the actual tile coords on the layer layout if (xt > 0) { tileAbsX = (int)Math.Floor(xt / 32f); tileX = tileAbsX % tileCount.X; } else { tileAbsX = (int)Math.Ceiling(xt / 32f); tileX = tileAbsX % tileCount.X; while (tileX < 0) { tileX += tileCount.X; } } if (yt > 0) { tileAbsY = (int)Math.Floor(yt / 32f); tileY = tileAbsY % tileCount.Y; } else { tileAbsY = (int)Math.Ceiling(yt / 32f); tileY = tileAbsY % tileCount.Y; while (tileY < 0) { tileY += tileCount.Y; } } // update x1 and y1 with the remainder so that we start at the tile boundary // minus 1 because indices are updated in the beginning of the loops x1 -= remX - 32f; y1 -= remY - 32f; // Save the tile Y at the left border so that we can roll back to it at the start of // every row iteration int tileYs = tileY; // Calculate the last coordinates we want to draw to float x3 = x1 + 100 + viewSize.X; float y3 = y1 + 100 + viewSize.Y; Material material = null; Texture texture = null; ColorRgba mainColor = ColorRgba.White; // Reserve the required space for vertex data in our locally cached buffer int neededVertices = (int)((((x3 - x1) / 32) + 1) * (((y3 - y1) / 32) + 1) * 4); if (cachedVertices == null || cachedVertices.Length < neededVertices) { cachedVertices = new VertexC1P3T2[neededVertices]; } int vertexIndex = 0; int tile_xo = -1; for (float x2 = x1; x2 < x3; x2 += 32) { tileX = (tileX + 1) % tileCount.X; tile_xo++; if (!layer.RepeatX) { // If the current tile isn't in the first iteration of the layer horizontally, don't draw this column if (tileAbsX + tile_xo + 1 < 0 || tileAbsX + tile_xo + 1 >= tileCount.X) { continue; } } tileY = tileYs; int tile_yo = -1; for (float y2 = y1; y2 < y3; y2 += 32) { tileY = (tileY + 1) % tileCount.Y; tile_yo++; LayerTile tile = layer.Layout[tileX + tileY * layer.LayoutWidth]; if (!layer.RepeatY) { // If the current tile isn't in the first iteration of the layer vertically, don't draw it if (tileAbsY + tile_yo + 1 < 0 || tileAbsY + tile_yo + 1 >= tileCount.Y) { continue; } } Point2 offset; bool isFlippedX, isFlippedY; if (tile.IsAnimated) { if (tile.TileID < animatedTiles.Count) { offset = animatedTiles[tile.TileID].CurrentTile.MaterialOffset; isFlippedX = (animatedTiles[tile.TileID].CurrentTile.IsFlippedX != tile.IsFlippedX); isFlippedY = (animatedTiles[tile.TileID].CurrentTile.IsFlippedY != tile.IsFlippedY); //mainColor.A = tile.MaterialAlpha; mainColor.A = animatedTiles[tile.TileID].CurrentTile.MaterialAlpha; } else { continue; } } else { offset = tile.MaterialOffset; isFlippedX = tile.IsFlippedX; isFlippedY = tile.IsFlippedY; mainColor.A = tile.MaterialAlpha; } if (material != tile.Material) { // Submit all the vertices as one draw batch device.AddVertices( material, VertexMode.Quads, cachedVertices, 0, vertexIndex); vertexIndex = 0; material = tile.Material.Res; texture = material.MainTexture.Res; } Rect uvRect = new Rect( offset.X * texture.UVRatio.X / texture.ContentWidth, offset.Y * texture.UVRatio.Y / texture.ContentHeight, tileset.TileSize * texture.UVRatio.X / texture.ContentWidth, tileset.TileSize * texture.UVRatio.Y / texture.ContentHeight ); // ToDo: Flip normal map somehow if (isFlippedX) { uvRect.X += uvRect.W; uvRect.W *= -1; } if (isFlippedY) { uvRect.Y += uvRect.H; uvRect.H *= -1; } Vector3 renderPos = new Vector3(x2, y2, layer.Depth); renderPos.X = MathF.Round(renderPos.X); renderPos.Y = MathF.Round(renderPos.Y); if (MathF.RoundToInt(device.TargetSize.X) != (MathF.RoundToInt(device.TargetSize.X) / 2) * 2) { renderPos.X += 0.5f; } if (MathF.RoundToInt(device.TargetSize.Y) != (MathF.RoundToInt(device.TargetSize.Y) / 2) * 2) { renderPos.Y += 0.5f; } cachedVertices[vertexIndex + 0].Pos.X = renderPos.X; cachedVertices[vertexIndex + 0].Pos.Y = renderPos.Y; cachedVertices[vertexIndex + 0].Pos.Z = renderPos.Z; cachedVertices[vertexIndex + 0].TexCoord.X = uvRect.X; cachedVertices[vertexIndex + 0].TexCoord.Y = uvRect.Y; cachedVertices[vertexIndex + 0].Color = mainColor; cachedVertices[vertexIndex + 1].Pos.X = renderPos.X; cachedVertices[vertexIndex + 1].Pos.Y = renderPos.Y + tileSize.Y; cachedVertices[vertexIndex + 1].Pos.Z = renderPos.Z; cachedVertices[vertexIndex + 1].TexCoord.X = uvRect.X; cachedVertices[vertexIndex + 1].TexCoord.Y = uvRect.Y + uvRect.H; cachedVertices[vertexIndex + 1].Color = mainColor; cachedVertices[vertexIndex + 2].Pos.X = renderPos.X + tileSize.X; cachedVertices[vertexIndex + 2].Pos.Y = renderPos.Y + tileSize.Y; cachedVertices[vertexIndex + 2].Pos.Z = renderPos.Z; cachedVertices[vertexIndex + 2].TexCoord.X = uvRect.X + uvRect.W; cachedVertices[vertexIndex + 2].TexCoord.Y = uvRect.Y + uvRect.H; cachedVertices[vertexIndex + 2].Color = mainColor; cachedVertices[vertexIndex + 3].Pos.X = renderPos.X + tileSize.X; cachedVertices[vertexIndex + 3].Pos.Y = renderPos.Y; cachedVertices[vertexIndex + 3].Pos.Z = renderPos.Z; cachedVertices[vertexIndex + 3].TexCoord.X = uvRect.X + uvRect.W; cachedVertices[vertexIndex + 3].TexCoord.Y = uvRect.Y; cachedVertices[vertexIndex + 3].Color = mainColor; vertexIndex += 4; } } // Submit all the vertices as one draw batch device.AddVertices( material, VertexMode.Quads, cachedVertices, 0, vertexIndex); } }
private void RecreateTexturedBackground(TileSet levelTileset, ref TileMapLayer layer) { int w = layer.LayoutWidth; int h = layer.Layout.Length / w; Texture targetTexture; if (cachedTexturedBackground.IsAvailable) { targetTexture = cachedTexturedBackground.Res; } else { targetTexture = new Texture(w * 32, h * 32, TextureSizeMode.NonPowerOfTwo, TextureMagFilter.Linear, TextureMinFilter.Linear, TextureWrapMode.Repeat, TextureWrapMode.Repeat); } using (DrawDevice device = new DrawDevice()) { device.VisibilityMask = VisibilityFlag.AllFlags; device.Projection = ProjectionMode.Screen; using (RenderTarget target = new RenderTarget(AAQuality.Off, false, targetTexture)) { device.Target = target; device.TargetSize = new Vector2(w * 32, h * 32); device.ViewportRect = new Rect(device.TargetSize); device.PrepareForDrawcalls(); // ToDo Material material = levelTileset.GetDefaultTile(0).Material.Res; Texture texture = material.MainTexture.Res; // Reserve the required space for vertex data in our locally cached buffer int neededVertices = 4 * w * h; if (cachedVertices == null || cachedVertices.Length < neededVertices) { cachedVertices = new VertexC1P3T2[neededVertices]; } int vertexIndex = 0; for (int x = 0; x < w; x++) { for (int y = 0; y < h; y++) { LayerTile tile = layer.Layout[x + y * layer.LayoutWidth]; if (tile.IsAnimated) { continue; } Point2 offset = tile.MaterialOffset; bool isFlippedX = tile.IsFlippedX; bool isFlippedY = tile.IsFlippedY; Rect uvRect = new Rect( offset.X * texture.UVRatio.X / texture.ContentWidth, offset.Y * texture.UVRatio.Y / texture.ContentHeight, levelTileset.TileSize * texture.UVRatio.X / texture.ContentWidth, levelTileset.TileSize * texture.UVRatio.Y / texture.ContentHeight ); if (isFlippedX) { uvRect.X += uvRect.W; uvRect.W *= -1; } if (isFlippedY) { uvRect.Y += uvRect.H; uvRect.H *= -1; } Vector3 renderPos = new Vector3(x * 32, y * 32, 0); renderPos.X = MathF.Round(renderPos.X); renderPos.Y = MathF.Round(renderPos.Y); if (MathF.RoundToInt(device.TargetSize.X) != (MathF.RoundToInt(device.TargetSize.X) / 2) * 2) { renderPos.X += 0.5f; } if (MathF.RoundToInt(device.TargetSize.Y) != (MathF.RoundToInt(device.TargetSize.Y) / 2) * 2) { renderPos.Y += 0.5f; } Vector2 tileXStep = new Vector2(32, 0); Vector2 tileYStep = new Vector2(0, 32); cachedVertices[vertexIndex + 0].Pos.X = renderPos.X; cachedVertices[vertexIndex + 0].Pos.Y = renderPos.Y; cachedVertices[vertexIndex + 0].Pos.Z = renderPos.Z; cachedVertices[vertexIndex + 0].TexCoord.X = uvRect.X; cachedVertices[vertexIndex + 0].TexCoord.Y = uvRect.Y; cachedVertices[vertexIndex + 0].Color = ColorRgba.White; cachedVertices[vertexIndex + 1].Pos.X = renderPos.X + tileYStep.X; cachedVertices[vertexIndex + 1].Pos.Y = renderPos.Y + tileYStep.Y; cachedVertices[vertexIndex + 1].Pos.Z = renderPos.Z; cachedVertices[vertexIndex + 1].TexCoord.X = uvRect.X; cachedVertices[vertexIndex + 1].TexCoord.Y = uvRect.Y + uvRect.H; cachedVertices[vertexIndex + 1].Color = ColorRgba.White; cachedVertices[vertexIndex + 2].Pos.X = renderPos.X + tileXStep.X + tileYStep.X; cachedVertices[vertexIndex + 2].Pos.Y = renderPos.Y + tileXStep.Y + tileYStep.Y; cachedVertices[vertexIndex + 2].Pos.Z = renderPos.Z; cachedVertices[vertexIndex + 2].TexCoord.X = uvRect.X + uvRect.W; cachedVertices[vertexIndex + 2].TexCoord.Y = uvRect.Y + uvRect.H; cachedVertices[vertexIndex + 2].Color = ColorRgba.White; cachedVertices[vertexIndex + 3].Pos.X = renderPos.X + tileXStep.X; cachedVertices[vertexIndex + 3].Pos.Y = renderPos.Y + tileXStep.Y; cachedVertices[vertexIndex + 3].Pos.Z = renderPos.Z; cachedVertices[vertexIndex + 3].TexCoord.X = uvRect.X + uvRect.W; cachedVertices[vertexIndex + 3].TexCoord.Y = uvRect.Y; cachedVertices[vertexIndex + 3].Color = ColorRgba.White; vertexIndex += 4; } } device.AddVertices(material, VertexMode.Quads, cachedVertices, 0, vertexIndex); device.Render(); } } cachedTexturedBackground = targetTexture; }
public unsafe void DrawString(ref int charOffset, string text, float x, float y, Alignment alignment, ColorRgba? color = null, float scale = 1f, float angleOffset = 0f, float varianceX = 4f, float varianceY = 4f, float speed = 4f, float charSpacing = 1f, float lineSpacing = 1f) { const int MaxColorizeIndex = 7; if (string.IsNullOrEmpty(text)) { return; } float phase = (float)Time.GameTimer.TotalSeconds * speed; bool hasColor = false; // Pre-compute text size //int lines = 1; float totalWidth = 0f, lastWidth = 0f, totalHeight = 0f; float charSpacingPre = charSpacing; float scalePre = scale; for (int i = 0; i < text.Length; i++) { if (text[i] == '\n') { if (lastWidth < totalWidth) { lastWidth = totalWidth; } totalWidth = 0f; totalHeight += (charHeight * scale * lineSpacing); //lines++; continue; } else if (text[i] == '\f' && text[i + 1] == '[') { i += 2; int formatIndex = i; while (text[i] != ']') { i++; } if (text[formatIndex + 1] == ':') { int paramInt; switch (text[formatIndex]) { case 'c': // Color hasColor = true; break; case 's': // Scale if (int.TryParse(text.Substring(formatIndex + 2, i - (formatIndex + 2)), out paramInt)) { scalePre = paramInt * 0.01f; } break; case 'w': // Char spacing if (int.TryParse(text.Substring(formatIndex + 2, i - (formatIndex + 2)), out paramInt)) { charSpacingPre = paramInt * 0.01f; } break; } } continue; } Rect uvRect; if (!unicodeChars.TryGetValue(text[i], out uvRect)) { byte ascii = (byte)text[i]; if (ascii < 128) { uvRect = asciiChars[ascii]; } else { uvRect = new Rect(); } } if (uvRect.W > 0 && uvRect.H > 0) { totalWidth += (uvRect.W + baseSpacing) * charSpacingPre * scalePre; } } if (lastWidth < totalWidth) { lastWidth = totalWidth; } totalHeight += (charHeight * scale * lineSpacing); VertexC1P3T2[] vertexData = canvas.RentVertices(text.Length * 4); // Set default material bool colorize, allowColorChange; ContentRef<Material> material; ColorRgba mainColor; if (color.HasValue) { mainColor = color.Value; if (mainColor == ColorRgba.TransparentBlack) { if (hasColor) { material = materialColor; mainColor = new ColorRgba(0.46f, 0.46f, 0.4f, 0.5f); } else { material = materialPlain; mainColor = ColorRgba.White; } } else { material = materialColor; } colorize = false; if (mainColor.R == 0 && mainColor.G == 0 && mainColor.B == 0) { allowColorChange = false; } else { allowColorChange = true; } } else { material = materialColor; mainColor = ColorRgba.White; colorize = true; allowColorChange = false; } Vector2 uvRatio = new Vector2( 1f / materialPlain.Res.MainTexture.Res.ContentWidth, 1f / materialPlain.Res.MainTexture.Res.ContentHeight ); int vertexIndex = 0; Vector2 originPos = new Vector2(x, y); alignment.ApplyTo(ref originPos, new Vector2(lastWidth, totalHeight)); float lineStart = originPos.X; for (int i = 0; i < text.Length; i++) { if (text[i] == '\n') { // New line originPos.X = lineStart; originPos.Y += (charHeight * scale * lineSpacing); continue; } else if (text[i] == '\f' && text[i + 1] == '[') { // Format i += 2; int formatIndex = i; while (text[i] != ']') { i++; } if (text[formatIndex + 1] == ':') { int paramInt; switch (text[formatIndex]) { case 'c': // Color if (allowColorChange && int.TryParse(text.Substring(formatIndex + 2, i - (formatIndex + 2)), out paramInt)) { if (paramInt == -1) { colorize = true; } else { colorize = false; mainColor = colors[paramInt % colors.Length]; } } break; case 's': // Scale if (int.TryParse(text.Substring(formatIndex + 2, i - (formatIndex + 2)), out paramInt)) { scale = paramInt * 0.01f; } break; case 'w': // Char spacing if (int.TryParse(text.Substring(formatIndex + 2, i - (formatIndex + 2)), out paramInt)) { charSpacing = paramInt * 0.01f; } break; default: // Unknown formatting break; } } continue; } Rect uvRect; if (!unicodeChars.TryGetValue(text[i], out uvRect)) { byte ascii = (byte)text[i]; if (ascii < 128) { uvRect = asciiChars[ascii]; } else { uvRect = new Rect(); } } if (uvRect.W > 0 && uvRect.H > 0) { if (colorize) { mainColor = colors[charOffset % MaxColorizeIndex]; } Vector3 pos = new Vector3(originPos); if (angleOffset > 0f) { float currentPhase = (phase + charOffset) * angleOffset * MathF.Pi; if (speed > 0f && charOffset % 2 == 1) { currentPhase = -currentPhase; } pos.X += MathF.Cos(currentPhase) * varianceX * scale; pos.Y += MathF.Sin(currentPhase) * varianceY * scale; } pos.X = MathF.Round(pos.X); pos.Y = MathF.Round(pos.Y); float x2 = MathF.Round(pos.X + uvRect.W * scale); float y2 = MathF.Round(pos.Y + uvRect.H * scale); vertexData[vertexIndex + 0].Pos = pos; vertexData[vertexIndex + 0].TexCoord.X = uvRect.X; vertexData[vertexIndex + 0].TexCoord.Y = uvRect.Y; vertexData[vertexIndex + 0].Color = mainColor; vertexData[vertexIndex + 1].Pos.X = pos.X; vertexData[vertexIndex + 1].Pos.Y = y2; vertexData[vertexIndex + 1].Pos.Z = pos.Z; vertexData[vertexIndex + 1].TexCoord.X = uvRect.X; vertexData[vertexIndex + 1].TexCoord.Y = uvRect.Y + uvRect.H * uvRatio.Y; vertexData[vertexIndex + 1].Color = mainColor; vertexData[vertexIndex + 2].Pos.X = x2; vertexData[vertexIndex + 2].Pos.Y = y2; vertexData[vertexIndex + 2].Pos.Z = pos.Z; vertexData[vertexIndex + 2].TexCoord.X = uvRect.X + uvRect.W * uvRatio.X; vertexData[vertexIndex + 2].TexCoord.Y = uvRect.Y + uvRect.H * uvRatio.Y; vertexData[vertexIndex + 2].Color = mainColor; vertexData[vertexIndex + 3].Pos.X = x2; vertexData[vertexIndex + 3].Pos.Y = pos.Y; vertexData[vertexIndex + 3].Pos.Z = pos.Z; vertexData[vertexIndex + 3].TexCoord.X = uvRect.X + uvRect.W * uvRatio.X; vertexData[vertexIndex + 3].TexCoord.Y = uvRect.Y; vertexData[vertexIndex + 3].Color = mainColor; if (MathF.RoundToInt(canvas.DrawDevice.TargetSize.X) != (MathF.RoundToInt(canvas.DrawDevice.TargetSize.X) / 2) * 2) { float align = 0.5f / canvas.DrawDevice.TargetSize.X; vertexData[vertexIndex + 0].Pos.X += align; vertexData[vertexIndex + 1].Pos.X += align; vertexData[vertexIndex + 2].Pos.X += align; vertexData[vertexIndex + 3].Pos.X += align; } if (MathF.RoundToInt(canvas.DrawDevice.TargetSize.Y) != (MathF.RoundToInt(canvas.DrawDevice.TargetSize.Y) / 2) * 2) { float align = 0.5f * scale / canvas.DrawDevice.TargetSize.Y; vertexData[vertexIndex + 0].Pos.Y += align; vertexData[vertexIndex + 1].Pos.Y += align; vertexData[vertexIndex + 2].Pos.Y += align; vertexData[vertexIndex + 3].Pos.Y += align; } vertexIndex += 4; originPos.X += ((uvRect.W + baseSpacing) * scale * charSpacing); } charOffset++; } charOffset++; // Submit all the vertices as one draw batch canvas.DrawDevice.AddVertices( material, VertexMode.Quads, vertexData, 0, vertexIndex); }
protected void PrepareVerticesSmooth(ref VertexC1P3T4A1[] vertices, IDrawDevice device, float curAnimFrameFade, ColorRgba mainClr, Rect uvRect, Rect uvRectNext) { Vector3 pos = this.gameobj.Transform.Pos; Vector2 xDot, yDot; MathF.GetTransformDotVec(this.gameobj.Transform.Angle, this.gameobj.Transform.Scale, out xDot, out yDot); Rect rectTemp = rect.Transformed(gameobj.Transform.Scale, gameobj.Transform.Scale); Vector2 edge1 = rectTemp.TopLeft; Vector2 edge2 = rectTemp.BottomLeft; Vector2 edge3 = rectTemp.BottomRight; Vector2 edge4 = rectTemp.TopRight; MathF.TransformDotVec(ref edge1, ref xDot, ref yDot); MathF.TransformDotVec(ref edge2, ref xDot, ref yDot); MathF.TransformDotVec(ref edge3, ref xDot, ref yDot); MathF.TransformDotVec(ref edge4, ref xDot, ref yDot); float left = uvRect.X; float right = uvRect.RightX; float top = uvRect.Y; float bottom = uvRect.BottomY; float nextLeft = uvRectNext.X; float nextRight = uvRectNext.RightX; float nextTop = uvRectNext.Y; float nextBottom = uvRectNext.BottomY; if ((flipMode & FlipMode.Horizontal) != FlipMode.None) { edge1.X = -edge1.X; edge2.X = -edge2.X; edge3.X = -edge3.X; edge4.X = -edge4.X; } if ((flipMode & FlipMode.Vertical) != FlipMode.None) { edge1.Y = -edge1.Y; edge2.Y = -edge2.Y; edge3.Y = -edge3.Y; edge4.Y = -edge4.Y; } if (vertices == null /*|| vertices.Length != 4*/) { vertices = new VertexC1P3T4A1[4]; } vertices[0].Pos.X = pos.X + edge1.X; vertices[0].Pos.Y = pos.Y + edge1.Y; vertices[0].Pos.Z = pos.Z + VertexZOffset; vertices[0].TexCoord.X = left; vertices[0].TexCoord.Y = top; vertices[0].TexCoord.Z = nextLeft; vertices[0].TexCoord.W = nextTop; vertices[0].Color = mainClr; vertices[0].Attrib = curAnimFrameFade; vertices[1].Pos.X = pos.X + edge2.X; vertices[1].Pos.Y = pos.Y + edge2.Y; vertices[1].Pos.Z = pos.Z + VertexZOffset; vertices[1].TexCoord.X = left; vertices[1].TexCoord.Y = bottom; vertices[1].TexCoord.Z = nextLeft; vertices[1].TexCoord.W = nextBottom; vertices[1].Color = mainClr; vertices[1].Attrib = curAnimFrameFade; vertices[2].Pos.X = pos.X + edge3.X; vertices[2].Pos.Y = pos.Y + edge3.Y; vertices[2].Pos.Z = pos.Z + VertexZOffset; vertices[2].TexCoord.X = right; vertices[2].TexCoord.Y = bottom; vertices[2].TexCoord.Z = nextRight; vertices[2].TexCoord.W = nextBottom; vertices[2].Color = mainClr; vertices[2].Attrib = curAnimFrameFade; vertices[3].Pos.X = pos.X + edge4.X; vertices[3].Pos.Y = pos.Y + edge4.Y; vertices[3].Pos.Z = pos.Z + VertexZOffset; vertices[3].TexCoord.X = right; vertices[3].TexCoord.Y = top; vertices[3].TexCoord.Z = nextRight; vertices[3].TexCoord.W = nextTop; vertices[3].Color = mainClr; vertices[3].Attrib = curAnimFrameFade; if (pixelGrid) { vertices[0].Pos.X = MathF.Round(vertices[0].Pos.X); vertices[1].Pos.X = MathF.Round(vertices[1].Pos.X); vertices[2].Pos.X = MathF.Round(vertices[2].Pos.X); vertices[3].Pos.X = MathF.Round(vertices[3].Pos.X); if (MathF.RoundToInt(device.TargetSize.X) != (MathF.RoundToInt(device.TargetSize.X) / 2) * 2) { vertices[0].Pos.X += 0.5f; vertices[1].Pos.X += 0.5f; vertices[2].Pos.X += 0.5f; vertices[3].Pos.X += 0.5f; } vertices[0].Pos.Y = MathF.Round(vertices[0].Pos.Y); vertices[1].Pos.Y = MathF.Round(vertices[1].Pos.Y); vertices[2].Pos.Y = MathF.Round(vertices[2].Pos.Y); vertices[3].Pos.Y = MathF.Round(vertices[3].Pos.Y); if (MathF.RoundToInt(device.TargetSize.Y) != (MathF.RoundToInt(device.TargetSize.Y) / 2) * 2) { vertices[0].Pos.Y += 0.5f; vertices[1].Pos.Y += 0.5f; vertices[2].Pos.Y += 0.5f; vertices[3].Pos.Y += 0.5f; } } }