Beispiel #1
0
            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;
                }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        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);
            }
        }
Beispiel #4
0
        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;
        }
Beispiel #5
0
        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);
        }
Beispiel #6
0
        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;
                }
            }
        }