Beispiel #1
0
        public CursorSequence(SpriteCache cache, string cursorSrc, string palette, MiniYaml info)
        {
            sprites = cache[cursorSrc];
            var d = info.ToDictionary();

            start = Exts.ParseIntegerInvariant(d["start"].Value);
            this.palette = palette;

            if ((d.ContainsKey("length") && d["length"].Value == "*") || (d.ContainsKey("end") && d["end"].Value == "*"))
                length = sprites.Length - start;
            else if (d.ContainsKey("length"))
                length = Exts.ParseIntegerInvariant(d["length"].Value);
            else if (d.ContainsKey("end"))
                length = Exts.ParseIntegerInvariant(d["end"].Value) - start;
            else
                length = 1;

            if (d.ContainsKey("x"))
                Exts.TryParseIntegerInvariant(d["x"].Value, out Hotspot.X);
            if (d.ContainsKey("y"))
                Exts.TryParseIntegerInvariant(d["y"].Value, out Hotspot.Y);
        }
Beispiel #2
0
 public virtual ISpriteSequence CreateSequence(ModData modData, TileSet tileSet, SpriteCache cache, string sequence, string animation, MiniYaml info)
 {
     return(new DefaultSpriteSequence(modData, tileSet, cache, this, sequence, animation, info));
 }
Beispiel #3
0
        public IReadOnlyDictionary <string, ISpriteSequence> ParseSequences(ModData modData, TileSet tileSet, SpriteCache cache, MiniYamlNode node)
        {
            var sequences = new Dictionary <string, ISpriteSequence>();
            var nodes     = node.Value.ToDictionary();

            MiniYaml defaults;

            if (nodes.TryGetValue("Defaults", out defaults))
            {
                nodes.Remove("Defaults");
                nodes = nodes.ToDictionary(kv => kv.Key, kv => MiniYaml.Merge(kv.Value, defaults));

                // Merge 'Defaults' animation image value. An example follows.
                //
                // - Before -
                // stand:
                //  Facings: 8
                //
                // - After -
                // stand: e1
                //  Facings: 8
                foreach (var n in nodes)
                {
                    n.Value.Value = n.Value.Value ?? defaults.Value;
                }
            }

            foreach (var kvp in nodes)
            {
                using (new Support.PerfTimer("new Sequence(\"{0}\")".F(node.Key), 20))
                {
                    try
                    {
                        sequences.Add(kvp.Key, CreateSequence(modData, tileSet, cache, node.Key, kvp.Key, kvp.Value));
                    }
                    catch (FileNotFoundException ex)
                    {
                        // Eat the FileNotFound exceptions from missing sprites
                        OnMissingSpriteError(ex.Message);
                    }
                }
            }

            return(new ReadOnlyDictionary <string, ISpriteSequence>(sequences));
        }
Beispiel #4
0
 public override ISpriteSequence CreateSequence(ModData modData, string tileSet, SpriteCache cache, string sequence, string animation, MiniYaml info)
 {
     return(new ClassicSpriteSequence(modData, tileSet, cache, this, sequence, animation, info));
 }
Beispiel #5
0
        public DefaultSpriteSequence(ModData modData, TileSet tileSet, SpriteCache cache, ISpriteSequenceLoader loader, string sequence, string animation, MiniYaml info)
        {
            Name   = animation;
            Loader = loader;
            var d = info.ToDictionary();

            try
            {
                Start         = LoadField <int>(d, "Start", 0);
                ShadowStart   = LoadField <int>(d, "ShadowStart", -1);
                ShadowZOffset = LoadField <WDist>(d, "ShadowZOffset", DefaultShadowSpriteZOffset).Length;
                ZOffset       = LoadField <WDist>(d, "ZOffset", WDist.Zero).Length;
                Tick          = LoadField <int>(d, "Tick", 40);
                transpose     = LoadField <bool>(d, "Transpose", false);
                Frames        = LoadField <int[]>(d, "Frames", null);
                var flipX = LoadField <bool>(d, "FlipX", false);
                var flipY = LoadField <bool>(d, "FlipY", false);

                Facings = LoadField <int>(d, "Facings", 1);
                if (Facings < 0)
                {
                    reverseFacings = true;
                    Facings        = -Facings;
                }

                var offset    = LoadField <float2>(d, "Offset", float2.Zero);
                var blendMode = LoadField <BlendMode>(d, "BlendMode", BlendMode.Alpha);

                MiniYaml combine;
                if (d.TryGetValue("Combine", out combine))
                {
                    var combined = Enumerable.Empty <Sprite>();
                    foreach (var sub in combine.Nodes)
                    {
                        var sd = sub.Value.ToDictionary();

                        // Allow per-sprite offset, start, and length
                        var subStart  = LoadField <int>(sd, "Start", 0);
                        var subOffset = LoadField <float2>(sd, "Offset", float2.Zero);
                        var subFlipX  = LoadField <bool>(sd, "FlipX", false);
                        var subFlipY  = LoadField <bool>(sd, "FlipY", false);

                        var subSrc     = GetSpriteSrc(modData, tileSet, sequence, animation, sub.Key, sd);
                        var subSprites = cache[subSrc].Select(
                            s => new Sprite(s.Sheet, FlipRectangle(s.Bounds, subFlipX, subFlipY), s.Offset + subOffset + offset, s.Channel, blendMode));

                        var      subLength = 0;
                        MiniYaml subLengthYaml;
                        if (sd.TryGetValue("Length", out subLengthYaml) && subLengthYaml.Value == "*")
                        {
                            subLength = subSprites.Count() - subStart;
                        }
                        else
                        {
                            subLength = LoadField <int>(sd, "Length", 1);
                        }

                        combined = combined.Concat(subSprites.Skip(subStart).Take(subLength));
                    }

                    sprites = combined.ToArray();
                }
                else
                {
                    // Apply offset to each sprite in the sequence
                    // Different sequences may apply different offsets to the same frame
                    var src = GetSpriteSrc(modData, tileSet, sequence, animation, info.Value, d);
                    sprites = cache[src].Select(
                        s => new Sprite(s.Sheet, FlipRectangle(s.Bounds, flipX, flipY), s.Offset + offset, s.Channel, blendMode)).ToArray();
                }

                MiniYaml length;
                if (d.TryGetValue("Length", out length) && length.Value == "*")
                {
                    Length = sprites.Length - Start;
                }
                else
                {
                    Length = LoadField <int>(d, "Length", 1);
                }

                // Plays the animation forwards, and then in reverse
                if (LoadField <bool>(d, "Reverses", false))
                {
                    var frames = Frames ?? Exts.MakeArray(Length, i => Start + i);
                    Frames = frames.Concat(frames.Skip(1).Take(frames.Length - 2).Reverse()).ToArray();
                    Length = 2 * Length - 2;
                }

                Stride = LoadField <int>(d, "Stride", Length);

                if (Length > Stride)
                {
                    throw new InvalidOperationException(
                              "{0}: Sequence {1}.{2}: Length must be <= stride"
                              .F(info.Nodes[0].Location, sequence, animation));
                }

                if (Start < 0 || Start + Facings * Stride > sprites.Length)
                {
                    throw new InvalidOperationException(
                              "{5}: Sequence {0}.{1} uses frames [{2}..{3}], but only 0..{4} actually exist"
                              .F(sequence, animation, Start, Start + Facings * Stride - 1, sprites.Length - 1,
                                 info.Nodes[0].Location));
                }

                if (ShadowStart + Facings * Stride > sprites.Length)
                {
                    throw new InvalidOperationException(
                              "{5}: Sequence {0}.{1}'s shadow frames use frames [{2}..{3}], but only [0..{4}] actually exist"
                              .F(sequence, animation, ShadowStart, ShadowStart + Facings * Stride - 1, sprites.Length - 1,
                                 info.Nodes[0].Location));
                }
            }
            catch (FormatException f)
            {
                throw new FormatException("Failed to parse sequences for {0}.{1} at {2}:\n{3}".F(sequence, animation, info.Nodes[0].Location, f));
            }
        }
        public IReadOnlyDictionary <string, ISpriteSequence> ParseSequences(ModData modData, TileSet tileSet, SpriteCache cache, MiniYamlNode node)
        {
            var sequences = new Dictionary <string, ISpriteSequence>();
            var nodes     = node.Value.ToDictionary();

            MiniYaml defaults;

            if (nodes.TryGetValue("Defaults", out defaults))
            {
                nodes.Remove("Defaults");
                foreach (var n in nodes)
                {
                    n.Value.Nodes = MiniYaml.Merge(new[] { defaults.Nodes, n.Value.Nodes });
                    n.Value.Value = n.Value.Value ?? defaults.Value;
                }
            }

            foreach (var kvp in nodes)
            {
                using (new Support.PerfTimer("new Sequence(\"{0}\")".F(node.Key), 20))
                {
                    try
                    {
                        sequences.Add(kvp.Key, CreateSequence(modData, tileSet, cache, node.Key, kvp.Key, kvp.Value));
                    }
                    catch (FileNotFoundException ex)
                    {
                        // Eat the FileNotFound exceptions from missing sprites
                        OnMissingSpriteError(ex.Message);
                    }
                }
            }

            return(new ReadOnlyDictionary <string, ISpriteSequence>(sequences));
        }
Beispiel #7
0
 public TilesetSpecificSpriteSequence(ModData modData, TileSet tileSet, SpriteCache cache, ISpriteSequenceLoader loader, string sequence, string animation, MiniYaml info)
     : base(modData, tileSet, cache, loader, sequence, animation, info)
 {
 }
        public DefaultSpriteSequence(ModData modData, TileSet tileSet, SpriteCache cache, ISpriteSequenceLoader loader, string sequence, string animation, MiniYaml info)
        {
            Name   = animation;
            Loader = loader;
            var d = info.ToDictionary();

            try
            {
                Start                 = LoadField(d, "Start", 0);
                ShadowStart           = LoadField(d, "ShadowStart", -1);
                ShadowZOffset         = LoadField(d, "ShadowZOffset", DefaultShadowSpriteZOffset).Length;
                ZOffset               = LoadField(d, "ZOffset", WDist.Zero).Length;
                ZRamp                 = LoadField(d, "ZRamp", 0);
                Tick                  = LoadField(d, "Tick", 40);
                transpose             = LoadField(d, "Transpose", false);
                Frames                = LoadField <int[]>(d, "Frames", null);
                useClassicFacingFudge = LoadField(d, "UseClassicFacingFudge", false);

                var flipX = LoadField(d, "FlipX", false);
                var flipY = LoadField(d, "FlipY", false);

                Facings = LoadField(d, "Facings", 1);
                if (Facings < 0)
                {
                    reverseFacings = true;
                    Facings        = -Facings;
                }

                if (useClassicFacingFudge && Facings != 32)
                {
                    throw new InvalidOperationException(
                              "{0}: Sequence {1}.{2}: UseClassicFacingFudge is only valid for 32 facings"
                              .F(info.Nodes[0].Location, sequence, animation));
                }

                var offset    = LoadField(d, "Offset", float3.Zero);
                var blendMode = LoadField(d, "BlendMode", BlendMode.Alpha);

                MiniYaml combine;
                if (d.TryGetValue("Combine", out combine))
                {
                    var combined = Enumerable.Empty <Sprite>();
                    foreach (var sub in combine.Nodes)
                    {
                        var sd = sub.Value.ToDictionary();

                        // Allow per-sprite offset, flipping, start, and length
                        var subStart  = LoadField(sd, "Start", 0);
                        var subOffset = LoadField(sd, "Offset", float3.Zero);
                        var subFlipX  = LoadField(sd, "FlipX", false);
                        var subFlipY  = LoadField(sd, "FlipY", false);

                        var subSrc     = GetSpriteSrc(modData, tileSet, sequence, animation, sub.Key, sd);
                        var subSprites = cache[subSrc].Select(
                            s => new Sprite(s.Sheet,
                                            FlipRectangle(s.Bounds, subFlipX, subFlipY), ZRamp,
                                            new float3(subFlipX ? -s.Offset.X : s.Offset.X, subFlipY ? -s.Offset.Y : s.Offset.Y, s.Offset.Z) + subOffset + offset,
                                            s.Channel, blendMode));

                        var      subLength = 0;
                        MiniYaml subLengthYaml;
                        if (sd.TryGetValue("Length", out subLengthYaml) && subLengthYaml.Value == "*")
                        {
                            subLength = subSprites.Count() - subStart;
                        }
                        else
                        {
                            subLength = LoadField(sd, "Length", 1);
                        }

                        combined = combined.Concat(subSprites.Skip(subStart).Take(subLength));
                    }

                    sprites = combined.ToArray();
                }
                else
                {
                    // Apply offset to each sprite in the sequence
                    // Different sequences may apply different offsets to the same frame
                    var src = GetSpriteSrc(modData, tileSet, sequence, animation, info.Value, d);
                    sprites = cache[src].Select(
                        s => new Sprite(s.Sheet,
                                        FlipRectangle(s.Bounds, flipX, flipY), ZRamp,
                                        new float3(flipX ? -s.Offset.X : s.Offset.X, flipY ? -s.Offset.Y : s.Offset.Y, s.Offset.Z) + offset,
                                        s.Channel, blendMode)).ToArray();
                }

                var depthSprite = LoadField <string>(d, "DepthSprite", null);
                if (!string.IsNullOrEmpty(depthSprite))
                {
                    var depthSpriteFrame = LoadField(d, "DepthSpriteFrame", 0);
                    var depthOffset      = LoadField(d, "DepthSpriteOffset", float2.Zero);
                    var depthSprites     = cache.AllCached(depthSprite)
                                           .Select(s => s[depthSpriteFrame]);

                    sprites = sprites.Select(s =>
                    {
                        // The depth sprite must live on the same sheet as the main sprite
                        var ds = depthSprites.FirstOrDefault(dss => dss.Sheet == s.Sheet);
                        if (ds == null)
                        {
                            // The sequence has probably overflowed onto a new sheet.
                            // Allocating a new depth sprite on this sheet will almost certainly work
                            ds           = cache.Reload(depthSprite)[depthSpriteFrame];
                            depthSprites = cache.AllCached(depthSprite)
                                           .Select(ss => ss[depthSpriteFrame]);

                            // If that doesn't work then we may be referencing a cached sprite from an earlier sheet
                            // TODO: We could try and reallocate the main sprite, but that requires more complicated code and a perf hit
                            // We'll only cross that bridge if this becomes a problem in reality
                            if (ds.Sheet != s.Sheet)
                            {
                                throw new SheetOverflowException("Cross-sheet depth sprite reference: {0}.{1}: {2}");
                            }
                        }

                        var cw = (ds.Bounds.Left + ds.Bounds.Right) / 2 + (int)(s.Offset.X + depthOffset.X);
                        var ch = (ds.Bounds.Top + ds.Bounds.Bottom) / 2 + (int)(s.Offset.Y + depthOffset.Y);
                        var w  = s.Bounds.Width / 2;
                        var h  = s.Bounds.Height / 2;

                        var r = Rectangle.FromLTRB(cw - w, ch - h, cw + w, ch + h);
                        return(new SpriteWithSecondaryData(s, r, ds.Channel));
                    }).ToArray();
                }

                MiniYaml length;
                if (d.TryGetValue("Length", out length) && length.Value == "*")
                {
                    Length = sprites.Length - Start;
                }
                else
                {
                    Length = LoadField(d, "Length", 1);
                }

                // Plays the animation forwards, and then in reverse
                if (LoadField(d, "Reverses", false))
                {
                    var frames = Frames ?? Exts.MakeArray(Length, i => Start + i);
                    Frames = frames.Concat(frames.Skip(1).Take(frames.Length - 2).Reverse()).ToArray();
                    Length = 2 * Length - 2;
                }

                Stride = LoadField(d, "Stride", Length);

                if (Length > Stride)
                {
                    throw new InvalidOperationException(
                              "{0}: Sequence {1}.{2}: Length must be <= stride"
                              .F(info.Nodes[0].Location, sequence, animation));
                }

                if (Frames != null && Length > Frames.Length)
                {
                    throw new InvalidOperationException(
                              "{0}: Sequence {1}.{2}: Length must be <= Frames.Length"
                              .F(info.Nodes[0].Location, sequence, animation));
                }

                if (Start < 0 || Start + Facings * Stride > sprites.Length)
                {
                    throw new InvalidOperationException(
                              "{5}: Sequence {0}.{1} uses frames [{2}..{3}], but only 0..{4} actually exist"
                              .F(sequence, animation, Start, Start + Facings * Stride - 1, sprites.Length - 1,
                                 info.Nodes[0].Location));
                }

                if (ShadowStart + Facings * Stride > sprites.Length)
                {
                    throw new InvalidOperationException(
                              "{5}: Sequence {0}.{1}'s shadow frames use frames [{2}..{3}], but only [0..{4}] actually exist"
                              .F(sequence, animation, ShadowStart, ShadowStart + Facings * Stride - 1, sprites.Length - 1,
                                 info.Nodes[0].Location));
                }
            }
            catch (FormatException f)
            {
                throw new FormatException("Failed to parse sequences for {0}.{1} at {2}:\n{3}".F(sequence, animation, info.Nodes[0].Location, f));
            }
        }
Beispiel #9
0
        public DefaultSpriteSequence(ModData modData, TileSet tileSet, SpriteCache cache, ISpriteSequenceLoader loader, string sequence, string animation, MiniYaml info)
        {
            this.sequence = sequence;
            Name          = animation;
            Loader        = loader;
            var d = info.ToDictionary();

            try
            {
                Start           = LoadField(d, "Start", 0);
                ShadowStart     = LoadField(d, "ShadowStart", -1);
                ShadowZOffset   = LoadField(d, "ShadowZOffset", DefaultShadowSpriteZOffset).Length;
                ZOffset         = LoadField(d, "ZOffset", WDist.Zero).Length;
                ZRamp           = LoadField(d, "ZRamp", 0);
                Tick            = LoadField(d, "Tick", 40);
                transpose       = LoadField(d, "Transpose", false);
                Frames          = LoadField <int[]>(d, "Frames", null);
                IgnoreWorldTint = LoadField(d, "IgnoreWorldTint", false);

                var flipX = LoadField(d, "FlipX", false);
                var flipY = LoadField(d, "FlipY", false);

                Facings = LoadField(d, "Facings", 1);
                if (Facings < 0)
                {
                    reverseFacings = true;
                    Facings        = -Facings;
                }

                var offset    = LoadField(d, "Offset", float3.Zero);
                var blendMode = LoadField(d, "BlendMode", BlendMode.Alpha);

                Func <int, IEnumerable <int> > getUsedFrames = frameCount =>
                {
                    MiniYaml length;
                    if (d.TryGetValue("Length", out length) && length.Value == "*")
                    {
                        Length = Frames != null ? Frames.Length : frameCount - Start;
                    }
                    else
                    {
                        Length = LoadField(d, "Length", 1);
                    }

                    // Plays the animation forwards, and then in reverse
                    if (LoadField(d, "Reverses", false))
                    {
                        var frames = Frames != null?Frames.Skip(Start).Take(Length).ToArray() : Exts.MakeArray(Length, i => Start + i);

                        Frames = frames.Concat(frames.Skip(1).Take(Length - 2).Reverse()).ToArray();
                        Length = 2 * Length - 2;
                        Start  = 0;
                    }

                    Stride = LoadField(d, "Stride", Length);

                    if (Length > Stride)
                    {
                        throw new InvalidOperationException(
                                  "{0}: Sequence {1}.{2}: Length must be <= stride"
                                  .F(info.Nodes[0].Location, sequence, animation));
                    }

                    if (Frames != null && Length > Frames.Length)
                    {
                        throw new InvalidOperationException(
                                  "{0}: Sequence {1}.{2}: Length must be <= Frames.Length"
                                  .F(info.Nodes[0].Location, sequence, animation));
                    }

                    var end = Start + (Facings - 1) * Stride + Length - 1;
                    if (Frames != null)
                    {
                        foreach (var f in Frames)
                        {
                            if (f < 0 || f >= frameCount)
                            {
                                throw new InvalidOperationException(
                                          "{5}: Sequence {0}.{1} defines a Frames override that references frame {4}, but only [{2}..{3}] actually exist"
                                          .F(sequence, animation, Start, end, f, info.Nodes[0].Location));
                            }
                        }

                        if (Start < 0 || end >= Frames.Length)
                        {
                            throw new InvalidOperationException(
                                      "{5}: Sequence {0}.{1} uses indices [{2}..{3}] of the Frames list, but only {4} frames are defined"
                                      .F(sequence, animation, Start, end, Frames.Length, info.Nodes[0].Location));
                        }
                    }
                    else if (Start < 0 || end >= frameCount)
                    {
                        throw new InvalidOperationException(
                                  "{5}: Sequence {0}.{1} uses frames [{2}..{3}], but only 0..{4} actually exist"
                                  .F(sequence, animation, Start, end, frameCount - 1, info.Nodes[0].Location));
                    }

                    if (ShadowStart >= 0 && ShadowStart + (Facings - 1) * Stride + Length > frameCount)
                    {
                        throw new InvalidOperationException(
                                  "{5}: Sequence {0}.{1}'s shadow frames use frames [{2}..{3}], but only [0..{4}] actually exist"
                                  .F(sequence, animation, ShadowStart, ShadowStart + (Facings - 1) * Stride + Length - 1, frameCount - 1,
                                     info.Nodes[0].Location));
                    }

                    var usedFrames = new List <int>();
                    for (var facing = 0; facing < Facings; facing++)
                    {
                        for (var frame = 0; frame < Length; frame++)
                        {
                            var i = transpose ? (frame % Length) * Facings + facing :
                                    (facing * Stride) + (frame % Length);

                            usedFrames.Add(Frames != null ? Frames[i] : Start + i);
                        }
                    }

                    if (ShadowStart >= 0)
                    {
                        return(usedFrames.Concat(usedFrames.Select(i => i + ShadowStart - Start)));
                    }

                    return(usedFrames);
                };

                MiniYaml combine;
                if (d.TryGetValue("Combine", out combine))
                {
                    var combined = Enumerable.Empty <Sprite>();
                    foreach (var sub in combine.Nodes)
                    {
                        var sd = sub.Value.ToDictionary();

                        // Allow per-sprite offset, flipping, start, and length
                        var subStart  = LoadField(sd, "Start", 0);
                        var subOffset = LoadField(sd, "Offset", float3.Zero);
                        var subFlipX  = LoadField(sd, "FlipX", false);
                        var subFlipY  = LoadField(sd, "FlipY", false);
                        var subFrames = LoadField <int[]>(sd, "Frames", null);
                        var subLength = 0;

                        Func <int, IEnumerable <int> > subGetUsedFrames = subFrameCount =>
                        {
                            MiniYaml subLengthYaml;
                            if (sd.TryGetValue("Length", out subLengthYaml) && subLengthYaml.Value == "*")
                            {
                                subLength = subFrames != null ? subFrames.Length : subFrameCount - subStart;
                            }
                            else
                            {
                                subLength = LoadField(sd, "Length", 1);
                            }

                            return(subFrames != null?subFrames.Skip(subStart).Take(subLength) : Enumerable.Range(subStart, subLength));
                        };

                        var subSrc     = GetSpriteSrc(modData, tileSet, sequence, animation, sub.Key, sd);
                        var subSprites = cache[subSrc, subGetUsedFrames].Select(
                            s => s != null ? new Sprite(s.Sheet,
                                                        FlipRectangle(s.Bounds, subFlipX, subFlipY), ZRamp,
                                                        new float3(subFlipX ? -s.Offset.X : s.Offset.X, subFlipY ? -s.Offset.Y : s.Offset.Y, s.Offset.Z) + subOffset + offset,
                                                        s.Channel, blendMode) : null).ToList();

                        var frames = subFrames != null?subFrames.Skip(subStart).Take(subLength).ToArray() : Exts.MakeArray(subLength, i => subStart + i);

                        combined = combined.Concat(frames.Select(i => subSprites[i]));
                    }

                    sprites = combined.ToArray();
                    getUsedFrames(sprites.Length);
                }
                else
                {
                    // Apply offset to each sprite in the sequence
                    // Different sequences may apply different offsets to the same frame
                    var src = GetSpriteSrc(modData, tileSet, sequence, animation, info.Value, d);
                    sprites = cache[src, getUsedFrames].Select(
                        s => s != null ? new Sprite(s.Sheet,
                                                    FlipRectangle(s.Bounds, flipX, flipY), ZRamp,
                                                    new float3(flipX ? -s.Offset.X : s.Offset.X, flipY ? -s.Offset.Y : s.Offset.Y, s.Offset.Z) + offset,
                                                    s.Channel, blendMode) : null).ToArray();
                }

                var depthSprite = LoadField <string>(d, "DepthSprite", null);
                if (!string.IsNullOrEmpty(depthSprite))
                {
                    var depthSpriteFrame = LoadField(d, "DepthSpriteFrame", 0);
                    var depthOffset      = LoadField(d, "DepthSpriteOffset", float2.Zero);
                    Func <int, IEnumerable <int> > getDepthFrame = _ => new int[] { depthSpriteFrame };
                    var ds = cache[depthSprite, getDepthFrame][depthSpriteFrame];

                    sprites = sprites.Select(s =>
                    {
                        if (s == null)
                        {
                            return(null);
                        }

                        var cw = (ds.Bounds.Left + ds.Bounds.Right) / 2 + (int)(s.Offset.X + depthOffset.X);
                        var ch = (ds.Bounds.Top + ds.Bounds.Bottom) / 2 + (int)(s.Offset.Y + depthOffset.Y);
                        var w  = s.Bounds.Width / 2;
                        var h  = s.Bounds.Height / 2;

                        var r = Rectangle.FromLTRB(cw - w, ch - h, cw + w, ch + h);
                        return(new SpriteWithSecondaryData(s, ds.Sheet, r, ds.Channel));
                    }).ToArray();
                }

                var exportPalette = LoadField <string>(d, "EmbeddedPalette", null);
                if (exportPalette != null)
                {
                    var src = GetSpriteSrc(modData, tileSet, sequence, animation, info.Value, d);

                    var metadata = cache.FrameMetadata(src);
                    var i        = Frames != null ? Frames[0] : Start;
                    var palettes = metadata != null?metadata.GetOrDefault <EmbeddedSpritePalette>() : null;

                    if (palettes == null || !palettes.TryGetPaletteForFrame(i, out EmbeddedPalette))
                    {
                        throw new YamlException("Cannot export palettes from {0}: frame {1} does not define an embedded palette".F(src, i));
                    }
                }

                var boundSprites = SpriteBounds(sprites, Frames, Start, Facings, Length, Stride, transpose);
                if (ShadowStart > 0)
                {
                    boundSprites = boundSprites.Concat(SpriteBounds(sprites, Frames, ShadowStart, Facings, Length, Stride, transpose));
                }

                Bounds = boundSprites.Union();
            }
            catch (FormatException f)
            {
                throw new FormatException("Failed to parse sequences for {0}.{1} at {2}:\n{3}".F(sequence, animation, info.Nodes[0].Location, f));
            }
        }
Beispiel #10
0
 public void drawSpriteCache(SpriteCache sc, int i)
 {
     throw new System.NotImplementedException();
 }
Beispiel #11
0
 public override ISpriteSequence CreateSequence(ModData modData, TileSet tileSet, SpriteCache cache, string sequence, string animation, MiniYaml info)
 {
     return(new ExtendedTilesetSpecificSpriteSequence(modData, tileSet, cache, this, sequence, animation, info));
 }
Beispiel #12
0
        private static ScreenBuffer AmbientOcclusion(AABB view, Layer layer, Light[] lights, AABB[] obstacles, int pixelSize)
        {
            var data  = SpriteCache.Get(layer.DataMapId);
            var color = SpriteCache.Get(layer.ColorMapId);

            var viewMin  = view.Min.Round();
            var viewSize = view.Size.Round();

            var sdl2Renderer = Renderer.Instance as SDL2Renderer;

            // ambient occlusion
            var aoSize         = viewSize / pixelSize;
            var aoBuffer       = sdl2Renderer.CreateScreenBuffer(BufferEnum.AmbientOcclusion1, aoSize);
            var aoBufferLength = aoBuffer.Data.Length / 4;

            Parallel.For(0, aoBufferLength, (i, loopState) =>
            {
                var aoPixel     = new Vector2i(i % aoSize.X, i / aoSize.X);
                var aoIndex     = ((aoSize.Y - aoPixel.Y - 1) * aoSize.X + aoPixel.X) * 4;
                var screenPixel = aoPixel * pixelSize + new Vector2i(pixelSize / 2);

                var pixelColor = RayTracing.AmbientOcclusion(viewMin + screenPixel, obstacles,
                                                             probeDistance: 128, rayCount: 4);

                var finalColor             = new Color4b(pixelColor);
                aoBuffer.Data[aoIndex + 0] = finalColor.A;
                aoBuffer.Data[aoIndex + 1] = finalColor.B;
                aoBuffer.Data[aoIndex + 2] = finalColor.G;
                aoBuffer.Data[aoIndex + 3] = finalColor.R;
            });

            // ambient occlusion & color
            var viewBuffer       = sdl2Renderer.CreateScreenBuffer(BufferEnum.AmbientOcclusion1, viewSize);
            var viewBufferLength = viewBuffer.Data.Length / 4;

            Parallel.For(0, viewBufferLength, (i, loopState) =>
            {
                var viewPixel = new Vector2i(i % viewSize.X, i / viewSize.X);
                var viewIndex = ((viewSize.Y - viewPixel.Y - 1) * viewSize.X + viewPixel.X) * 4;

                var colorIndex = (viewMin.Y + viewPixel.Y) * data.Size.X + viewMin.X + viewPixel.X;
                if (color.Data[colorIndex + 0] > 0)
                {
                    var aoPixel = viewPixel / pixelSize;
                    var aoIndex = ((aoSize.Y - aoPixel.Y - 1) * aoSize.X + aoPixel.X) * 4;

                    var pixelColor = new Color4f(color.Data[colorIndex]);
                    var aoColor    = new Color4f(new Color4b(
                                                     aoBuffer.Data[aoIndex + 3],
                                                     aoBuffer.Data[aoIndex + 2],
                                                     aoBuffer.Data[aoIndex + 1],
                                                     aoBuffer.Data[aoIndex + 0]).AsUint);

                    var finalColor = new Color4b(pixelColor * aoColor);
                    viewBuffer.Data[viewIndex + 0] = finalColor.A;
                    viewBuffer.Data[viewIndex + 1] = finalColor.B;
                    viewBuffer.Data[viewIndex + 2] = finalColor.G;
                    viewBuffer.Data[viewIndex + 3] = finalColor.R;
                }
                else
                {
                    // just alpha channel
                    viewBuffer.Data[viewIndex] = 0;
                }
            });

            return(viewBuffer);
        }
        public IReadOnlyDictionary <string, ISpriteSequence> ParseSequences(ModData modData, string tileSet, SpriteCache cache, MiniYamlNode node)
        {
            var sequences = new Dictionary <string, ISpriteSequence>();
            var nodes     = node.Value.ToDictionary();

            try
            {
                if (nodes.TryGetValue("Defaults", out var defaults))
                {
                    nodes.Remove("Defaults");
                    foreach (var n in nodes)
                    {
                        n.Value.Nodes = MiniYaml.Merge(new[] { defaults.Nodes, n.Value.Nodes });
                        n.Value.Value = n.Value.Value ?? defaults.Value;
                    }
                }
            }
            catch (Exception e)
            {
                throw new InvalidDataException($"Error occurred while parsing {node.Key}", e);
            }

            foreach (var kvp in nodes)
            {
                using (new Support.PerfTimer($"new Sequence(\"{node.Key}\")", 20))
                {
                    try
                    {
                        sequences.Add(kvp.Key, CreateSequence(modData, tileSet, cache, node.Key, kvp.Key, kvp.Value));
                    }
                    catch (FileNotFoundException ex)
                    {
                        // Defer exception until something tries to access the sequence
                        // This allows the asset installer and OpenRA.Utility to load the game without having the actor assets
                        sequences.Add(kvp.Key, new FileNotFoundSequence(ex));
                    }
                }
            }

            return(new ReadOnlyDictionary <string, ISpriteSequence>(sequences));
        }
Beispiel #14
0
    void Start()
    {
        show(uiMain);
        // 给主界面按钮加事件
        string canvasPath = "main/ui/uiMain/Canvas/buttons/";

        levelButton = GameObject.Find(canvasPath + "level2").GetComponent <Button>();
        levelButton.onClick.AddListener(delegate() {
            // 打开level 界面
//			Debug.Log("open level window");
            Sound.playSound(SoundType.Click);
            openLevelWindow();
        });
        unlimitButton = GameObject.Find(canvasPath + "unlimit2").GetComponent <Button>();
        unlimitButton.onClick.AddListener(delegate() {
            // 打开unlimit 界面
            Debug.Log("open unlimit window");
            Sound.playSound(SoundType.Click);
            openUnlimitWindow();
        });
        onlineButton = GameObject.Find(canvasPath + "online2").GetComponent <Button>();
        onlineButton.onClick.AddListener(delegate() {
            //Job.startJob(Params.energyJobKey, delegate() {
            //	Debug.Log("sdfsdfsdfs");
            //},10);
            // 打开online 界面
            Debug.Log("open online window");
            Sound.playSound(SoundType.Click);
            openOnlineWindow();
        });
        // uiLevel 关闭按钮
        GameObject closeGo     = GameObject.Find("main/ui/uiLevel/Canvas/close");
        Button     closeButton = closeGo.GetComponent <Button> ();

        closeButton.onClick.AddListener(delegate() {
            Sound.playSound(SoundType.Click);
            show(uiMain);
        });
        // uiUnlimit 关闭按钮和进入按钮
        Button go = GameObject.Find("main/ui/uiUnlimit/Canvas/go").GetComponent <Button>();

        go.onClick.AddListener(delegate() {
            Sound.playSound(SoundType.Click);
            CSUnlimitedGo unlimitedGo = new CSUnlimitedGo();
            SocketManager.SendMessageAsyc((int)MiGongOpcode.CSUnlimitedGo, CSUnlimitedGo.SerializeToBytes(unlimitedGo), delegate(int opcode, byte[] data) {
                ui.SetActive(false);
                SCUnlimitedGo ret = SCUnlimitedGo.Deserialize(data);
                // 剩余精力
                Params.startEnergySchedule(ret.Energy.Energy, ret.Energy.RefreshTime);
                int[] stars = { ret.Star1, ret.Star2, ret.Star3, ret.Star4 };
                createMap(MapMode.Unlimited, ret.Map.ToArray(), ret.Beans, ret.Time, ret.Speed, ret.Start, ret.End, ret.Pass, ret.EnemyCount, null, stars, null, null);
            });
        });
        closeButton = GameObject.Find("main/ui/uiUnlimit/Canvas/close").GetComponent <Button>();
        closeButton.onClick.AddListener(delegate() {
            Sound.playSound(SoundType.Click);
            show(uiMain);
        });
        // uiOnline 关闭按钮和进入按钮
        go = GameObject.Find("main/ui/uiOnline/Canvas/go").GetComponent <Button>();
        go.onClick.AddListener(delegate() {
            Sound.playSound(SoundType.Click);
            OnPvpClick();
        });
        closeButton = GameObject.Find("main/ui/uiOnline/Canvas/close").GetComponent <Button>();
        closeButton.onClick.AddListener(delegate() {
            Sound.playSound(SoundType.Click);
            show(uiMain);
        });
        // 获取登陆基本信息
        CSBaseInfo baseInfo = new CSBaseInfo();

        SocketManager.SendMessageAsyc((int)MiGongOpcode.CSBaseInfo, CSBaseInfo.SerializeToBytes(baseInfo), delegate(int opcode, byte[] data) {
            SCBaseInfo ret = SCBaseInfo.Deserialize(data);
            // TODO 显示精力
            // 系统参数
            foreach (PBSysPara sp in ret.SysParas)
            {
                sysParas.Add(sp.Key, sp.Value);
            }
            Params.sysParas = sysParas;

            Params.energyRecoverTime = int.Parse(sysParas["energyRecoverTime"]);
            // 精力相关
            Params.startEnergySchedule(ret.Energy.Energy, ret.Energy.RefreshTime);

            foreach (PBNewGuide newGuide in ret.NewGuide)
            {
                guideStep.Add(newGuide.Id, newGuide.Step);
            }
            this.openPass = ret.OpenPass;
            // 道具表
            Params.init(ret);
            // 无尽版和pvp是否开启
            doShowLock();
            // 初始化无尽版的每日星数奖励
            //string para = sysParas["unlimitedAwardStar"];
            //string[] paras = para.Split(';');
            Slider slider       = unlimitedAwardGo.transform.Find("starSlider").GetComponent <Slider>();
            RectTransform buRec = unlimitedAwardGo.transform.Find("starSlider").GetComponent <RectTransform> ();
            int len             = ret.UnlimitedRewardTable.Count;
            slider.maxValue     = ret.UnlimitedRewardTable[len - 1].Star;
            Object ob           = Resources.Load("chest");

            unlimitedAwardSegs = new UnlimitedAwardSeg[len];
            for (int i = 0; i < len; i++)
            {
                GameObject chestGo = Instantiate(ob) as GameObject;
                chestGo.transform.localPosition = new Vector3(
                    buRec.rect.width / slider.maxValue * ret.UnlimitedRewardTable[i].Star - buRec.rect.width / 2, 0, 0);
                chestGo.transform.SetParent(unlimitedAwardGo.transform, false);
                UnlimitedAwardSeg unlimitedAward = unlimitedAwardSegs[i] = new UnlimitedAwardSeg();
                unlimitedAward.star          = ret.UnlimitedRewardTable[i].Star;
                unlimitedAward.image         = chestGo.GetComponent <Image>();
                Button bt                    = chestGo.GetComponent <Button>();
                int index                    = i;
                PBUnlimitedRewardTable table = ret.UnlimitedRewardTable[i];
                bt.onClick.AddListener(delegate
                {
                    Sound.playSound(SoundType.Click);
                    // 如果达到了,就直接领取了,然后就是确定,否则就是显示,然后是确定
                    if (unlimitedAward.state == 1)
                    {
                        // 领取
                        Sound.playSound(SoundType.Click);
                        CSUnlimitedAward award = new CSUnlimitedAward();
                        award.Index            = index;
                        SocketManager.SendMessageAsyc((int)MiGongOpcode.CSUnlimitedAward, CSUnlimitedAward.SerializeToBytes(award), (opcode2, data2) => {
                            SCUnlimitedAward retAward   = SCUnlimitedAward.Deserialize(data2);
                            unlimitedAward.image.sprite = SpriteCache.getSprite("box/open");
                            unlimitedAward.state        = 2;
                            // 显示
                            WarnDialog.reward(Message.getText("gainReward"), Message.getText("ok"), table.Gold, table.Reward, null);
                        });
                    }
                    else
                    {
                        // 显示
                        WarnDialog.reward(Message.getText("dailyReward"), Message.getText("ok"), table.Gold, table.Reward, null);
                    }
                });
            }
        });

        // 账号,分享,帮助

        Button accountButton = GameObject.Find(canvasPath + "more/account").GetComponent <Button>();

        accountButton.onClick.AddListener(delegate() {
            Debug.Log("account");
            Sound.playSound(SoundType.Click);
            closeMorePanel();
            doAccount();
        });
        ssdk.showUserHandler = GetUserInfoResultHandler;
        Button shareButton = GameObject.Find(canvasPath + "more/share").GetComponent <Button>();

        shareButton.onClick.AddListener(delegate() {
            Debug.Log("share");
//			doShare();
            Sound.playSound(SoundType.Click);
            closeMorePanel();
            shareWeChat1.transform.parent.gameObject.SetActive(true);
        });
        ssdk.shareHandler = ShareResultHandler;
        // 分享的三个按钮就
        shareWeChat1.onClick.AddListener(delegate() {
            Debug.Log("share WeChat");
            Sound.playSound(SoundType.Click);
            doShare(PlatformType.WeChat);
        });
        shareWeChat2.onClick.AddListener(delegate() {
            Debug.Log("share WeChatMoments");
            Sound.playSound(SoundType.Click);
            doShare(PlatformType.WeChatMoments);
        });
        closeShare.onClick.AddListener(delegate() {
            Sound.playSound(SoundType.Click);
            shareWeChat1.transform.parent.gameObject.SetActive(false);
        });

        exit.onClick.AddListener(delegate() {
            Sound.playSound(SoundType.Click);
            Application.Quit();
        });

        // show more
        Button moreButton = GameObject.Find(canvasPath + "moreBt").GetComponent <Button>();

        moreButton.onClick.AddListener(delegate() {
            GameObject moreGo = GameObject.Find(canvasPath + "more");
            moreGo.SetActive(!moreGo.activeSelf);
        });
        // hide more
        Button hideMoreButton = GameObject.Find(canvasPath + "more/clickPanel").GetComponent <Button>();

        hideMoreButton.onClick.AddListener(delegate() {
            closeMorePanel();
        });
        //
        Button helpButton = GameObject.Find(canvasPath + "more/help").GetComponent <Button>();

        helpButton.onClick.AddListener(delegate() {
            Debug.Log("help");
//			WarnDialog.showWarnDialog("test",null,false,10,20);
            Sound.playSound(SoundType.Click);
            closeMorePanel();
            Help guideControl = uiHelp.GetComponent <Help>();
            guideControl.showHelp();
        });

        // 背包,商店
        Button packetButton = GameObject.Find(canvasPath + "packet").GetComponent <Button>();

        packetButton.onClick.AddListener(delegate() {
            Debug.Log("backet");
            Sound.playSound(SoundType.Click);
            uiPacket.GetComponent <Packet>().showPacket();
        });
        Button shopButton = GameObject.Find(canvasPath + "shop").GetComponent <Button>();

        shopButton.onClick.AddListener(delegate() {
            Debug.Log("shop");
            Sound.playSound(SoundType.Click);
            uiShop.GetComponent <Shop>().showShop();
        });

        // 对战中显示奖励界面的进入地图按钮
        Button showRewardOk = uiLevel.transform.Find("Canvas/showReward/dialog/ok").GetComponent <Button>();

        showRewardOk.onClick.AddListener(delegate() {
            Sound.playSound(SoundType.Click);
            onIntoPassClick();
        });
        Button showRewardClose = uiLevel.transform.Find("Canvas/showReward/dialog/close").GetComponent <Button>();

        showRewardClose.onClick.AddListener(delegate() {
            Sound.playSound(SoundType.Click);
            uiLevel.transform.Find("Canvas/showReward").gameObject.SetActive(false);
        });

        // 联网对战按钮
        //
        SocketManager.AddServerSendReceive((int)MiGongOpcode.SCMatchingSuccess, matchSuccess);
        SocketManager.AddServerSendReceive((int)MiGongOpcode.SCMatchingFail, delegate(int opcode, byte[] receiveData) {
            Debug.Log("");
            matching.matchFail();
        });
        SocketManager.AddServerSendReceive((int)MiGongOpcode.SCBegin, delegate(int opcode, byte[] receiveData) {
            Debug.Log("");
        });
        SocketManager.AddServerSendReceive((int)AccountOpcode.SCBeTakePlace, delegate(int opcode, byte[] receiveData) {
            WarnDialog.showWarnDialog("你的账号在其它地方登录!", delegate() {
                Application.Quit();
            }, true);
        });
    }
Beispiel #15
0
    private void openUnlimitWindow()
    {
        //
        //获取按钮游戏对象
        Object button = Resources.Load("UnlimitItem");

        GameObject content = GameObject.Find("main/ui/uiUnlimit/Canvas/scrollView/Viewport/Content");

        for (int i = 0; i < content.transform.childCount; i++)
        {
            Destroy(content.transform.GetChild(i).gameObject);
        }
        // 获取当前关卡
        CSUnlimitedInfo unlimitedInfo = new CSUnlimitedInfo();

        SocketManager.SendMessageAsyc((int)MiGongOpcode.CSUnlimitedInfo, CSUnlimitedInfo.SerializeToBytes(unlimitedInfo), delegate(int opcode, byte[] data) {
            show(uiUnlimit);
            SCUnlimitedInfo ret = SCUnlimitedInfo.Deserialize(data);

            //
            Text passText = GameObject.Find("main/ui/uiUnlimit/Canvas/pass").GetComponent <Text>();
            passText.text = Message.getText("unlimitRankSelf", ret.Pass, ret.Star, ret.Rank);
            //
            //GameObject energyTextGo = GameObject.Find ("main/ui/uiUnlimit/Canvas/energy/Text");
            //Text energyText = energyTextGo.GetComponent<Text>();
            //energyText.text = Params.energy.ToString();
            // 每日星数奖励
            //ret.TodayStar
            Slider slider = unlimitedAwardGo.transform.Find("starSlider").GetComponent <Slider>();
            slider.value  = ret.TodayStar;
            float step    = slider.maxValue / unlimitedAwardSegs.Length;

            string[] isLight = null;
            if (ret.Award.Length > 0)
            {
                isLight = ret.Award.Split(';');
            }

            for (int i = 0; i < unlimitedAwardSegs.Length; i++)
            {
                //Debug.Log(ret.TodayStar + "," + unlimitedAwardSegs[i].star);
                // 是否还没点亮
                if (ret.TodayStar < unlimitedAwardSegs[i].star)
                {
                    unlimitedAwardSegs[i].image.sprite = SpriteCache.getSprite("box/unreach");
                    unlimitedAwardSegs[i].state        = 0;
                }
                else if (isLight != null && int.Parse(isLight[i]) > 0)
                {
                    unlimitedAwardSegs[i].image.sprite = SpriteCache.getSprite("box/open");
                    unlimitedAwardSegs[i].state        = 2;
                }
                else
                {
                    unlimitedAwardSegs[i].image.sprite = SpriteCache.getSprite("box/reach");
                    unlimitedAwardSegs[i].state        = 1;
                }
            }


            // 列表
            int count = ret.UnlimitedRankInfo.Count;
            float dis = 0f;

            GameObject up       = Instantiate(button) as GameObject;
            RectTransform buRec = up.GetComponent <RectTransform> ();
            Destroy(up);

            RectTransform contentTrans = content.GetComponent <RectTransform> ();
            contentTrans.sizeDelta     = new Vector2(0, (buRec.rect.height + dis) * count + dis);

            for (int i = 0; i < count; i++)
            {
                PBUnlimitedRankInfo info = ret.UnlimitedRankInfo[i];
                up = Instantiate(button) as GameObject;
                up.transform.localPosition = new Vector3(0, -((buRec.rect.height + dis) * i + dis), 0);
                up.transform.localScale    = new Vector3(1, 1, 1);
                up.transform.SetParent(content.transform, false);
                // 生成各个玩家的排名item
                GameObject textGo = up.transform.Find("rank").gameObject;
                Text text         = textGo.GetComponent <Text> ();
                text.text         = info.Rank + "";
                //text.text = Message.getText("unlimitRankItem",info.Rank,info.UserName,info.Star);
                textGo    = up.transform.Find("name").gameObject;
                text      = textGo.GetComponent <Text>();
                text.text = info.UserName + "";
                textGo    = up.transform.Find("pass").gameObject;
                text      = textGo.GetComponent <Text>();
                text.text = info.Pass + "";
                textGo    = up.transform.Find("star").gameObject;
                text      = textGo.GetComponent <Text>();
                text.text = info.Star + "";
            }
        });
    }
Beispiel #16
0
 public ClientImpl()
 {
     this.spriteCache = new SpriteCache();
 }