Пример #1
0
        public DefaultTileCache(DefaultTerrain terrainInfo, Action <uint, string> onMissingImage = null)
        {
            sheetBuilders = new Cache <SheetType, SheetBuilder>(t => new SheetBuilder(t, terrainInfo.SheetSize));

            random = new MersenneTwister();

            var frameCache = new FrameCache(Game.ModData.DefaultFileSystem, Game.ModData.SpriteLoaders);

            foreach (var t in terrainInfo.Templates)
            {
                var variants     = new List <Sprite[]>();
                var templateInfo = (DefaultTerrainTemplateInfo)t.Value;

                for (var ii = 0; ii < templateInfo.Images.Length; ii++)
                {
                    var i = templateInfo.Images[ii];

                    ISpriteFrame[] allFrames;
                    ISpriteFrame[] depthFrames = null;

                    if (onMissingImage != null)
                    {
                        try
                        {
                            allFrames = frameCache[i];
                        }
                        catch (FileNotFoundException)
                        {
                            onMissingImage(t.Key, i);
                            continue;
                        }
                    }
                    else
                    {
                        allFrames = frameCache[i];
                    }

                    if (terrainInfo.EnableDepth && templateInfo.DepthImages != null && templateInfo.DepthImages.Length == templateInfo.Images.Length)
                    {
                        var di = templateInfo.DepthImages[ii];
                        if (onMissingImage != null)
                        {
                            try
                            {
                                depthFrames = frameCache[di];
                            }
                            catch (FileNotFoundException)
                            {
                                onMissingImage(t.Key, di);
                                continue;
                            }
                        }
                        else
                        {
                            depthFrames = frameCache[di];
                        }
                    }

                    var frameCount = terrainInfo.EnableDepth && depthFrames == null ? allFrames.Length / 2 : allFrames.Length;
                    var indices    = templateInfo.Frames != null ? templateInfo.Frames : Exts.MakeArray(t.Value.TilesCount, j => j);

                    var start = indices.Min();
                    var end   = indices.Max();
                    if (start < 0 || end >= frameCount)
                    {
                        throw new YamlException($"Template `{t.Key}` uses frames [{start}..{end}] of {i}, but only [0..{frameCount - 1}] actually exist");
                    }

                    variants.Add(indices.Select(j =>
                    {
                        var f    = allFrames[j];
                        var tile = t.Value.Contains(j) ? (DefaultTerrainTileInfo)t.Value[j] : null;

                        // The internal z axis is inverted from expectation (negative is closer)
                        var zOffset = tile != null ? -tile.ZOffset : 0;
                        var zRamp   = tile != null ? tile.ZRamp : 1f;
                        var offset  = new float3(f.Offset, zOffset);
                        var type    = SheetBuilder.FrameTypeToSheetType(f.Type);

                        var s = sheetBuilders[type].Allocate(f.Size, zRamp, offset);
                        OpenRA.Graphics.Util.FastCopyIntoChannel(s, f.Data, f.Type);

                        if (terrainInfo.EnableDepth)
                        {
                            var depthFrame = depthFrames != null ? depthFrames[j] : allFrames[j + frameCount];
                            var depthType  = SheetBuilder.FrameTypeToSheetType(depthFrame.Type);
                            var ss         = sheetBuilders[depthType].Allocate(depthFrame.Size, zRamp, offset);
                            OpenRA.Graphics.Util.FastCopyIntoChannel(ss, depthFrame.Data, depthFrame.Type);
                            s = new SpriteWithSecondaryData(s, ss.Sheet, ss.Bounds, ss.Channel);
                        }

                        return(s);
                    }).ToArray());
                }

                var allSprites = variants.SelectMany(s => s);

                // Ignore the offsets baked into R8 sprites
                if (terrainInfo.IgnoreTileSpriteOffsets)
                {
                    allSprites = allSprites.Select(s => new Sprite(s.Sheet, s.Bounds, s.ZRamp, new float3(float2.Zero, s.Offset.Z), s.Channel, s.BlendMode));
                }

                if (onMissingImage != null && !variants.Any())
                {
                    continue;
                }

                templates.Add(t.Value.Id, new TheaterTemplate(allSprites.ToArray(), variants.First().Count(), templateInfo.Images.Length));
            }

            // 1x1px transparent tile
            var missingDataLength = 1;
            var missingFrameType  = SpriteFrameType.Indexed8;
            var missingSheetType  = SheetType.Indexed;

            // Avoid creating an indexed sheet if all tiles are BGRA
            var missing = sheetBuilders.FirstOrDefault();

            if (missing.Value != null && missing.Key == SheetType.BGRA)
            {
                missingDataLength = 4;
                missingFrameType  = SpriteFrameType.Bgra32;
                missingSheetType  = SheetType.BGRA;
            }

            missingTile = sheetBuilders[missingSheetType].Add(new byte[missingDataLength], missingFrameType, new Size(1, 1));
            foreach (var sb in sheetBuilders.Values)
            {
                sb.Current.ReleaseBuffer();
            }
        }
Пример #2
0
 public DeployedObject()
 {
     cacheValue = new FrameCache <ActorDeployedObject>(() => M.Read <ActorDeployedObject>(Address));
 }
        void IUtilityCommand.Run(Utility utility, string[] args)
        {
            // HACK: The engine code assumes that Game.modData is set.
            var modData = Game.ModData = utility.ModData;

            var imageField             = typeof(TerrainTemplateInfo).GetField("Image");
            var pickAnyField           = typeof(TerrainTemplateInfo).GetField("PickAny");
            var tileInfoField          = typeof(TerrainTemplateInfo).GetField("tileInfo", BindingFlags.NonPublic | BindingFlags.Instance);
            var terrainTypeField       = typeof(TerrainTileInfo).GetField("TerrainType");
            var terrainLeftColorField  = typeof(TerrainTileInfo).GetField("LeftColor");
            var terrainRightColorField = typeof(TerrainTileInfo).GetField("RightColor");
            var empty = new Size(0, 0);
            var single = new int2(1, 1);
            var exts = new[] { "" }.Concat(args[1].Split(','));

            foreach (var t in modData.Manifest.TileSets)
            {
                var ts         = new TileSet(modData.DefaultFileSystem, t);
                var frameCache = new FrameCache(modData.DefaultFileSystem, modData.SpriteLoaders);

                Console.WriteLine("Tileset: " + ts.Name);
                foreach (var template in ts.Templates.Values)
                {
                    // Find the sprite associated with this template
                    foreach (var ext in exts)
                    {
                        Stream s;
                        if (modData.DefaultFileSystem.TryOpen(template.Images[0] + ext, out s))
                        {
                            s.Dispose();
                        }
                        else
                        {
                            continue;
                        }

                        // Rewrite the template image (normally readonly) using reflection
                        imageField.SetValue(template, template.Images[0] + ext);

                        // Fetch the private tileInfo array so that we can write new entries
                        var tileInfo = (TerrainTileInfo[])tileInfoField.GetValue(template);

                        // Open the file and search for any implicit frames
                        var allFrames = frameCache[template.Images[0]];
                        var frames    = template.Frames != null?template.Frames.Select(f => allFrames[f]).ToArray() : allFrames;

                        // Resize array for new entries
                        if (frames.Length > template.TilesCount)
                        {
                            var ti = new TerrainTileInfo[frames.Length];
                            Array.Copy(tileInfo, ti, template.TilesCount);
                            tileInfoField.SetValue(template, ti);
                            tileInfo = ti;
                        }

                        for (var i = 0; i < template.TilesCount; i++)
                        {
                            if (template[i] == null && frames[i] != null && frames[i].Size != empty)
                            {
                                tileInfo[i] = new TerrainTileInfo();
                                var ti = ts.GetTerrainIndex("Clear");
                                terrainTypeField.SetValue(tileInfo[i], ti);
                                terrainLeftColorField.SetValue(tileInfo[i], ts[ti].Color);
                                terrainRightColorField.SetValue(tileInfo[i], ts[ti].Color);
                                Console.WriteLine("Fixing entry for {0}:{1}", template.Images[0], i);
                            }
                        }

                        if (template.TilesCount > 1 && template.Size == single)
                        {
                            pickAnyField.SetValue(template, true);
                        }
                    }
                }

                ts.Save(t);
            }
        }
Пример #4
0
 protected override void OnAddressChange()
 {
     cachedValue = new FrameCache <MinimapIconOffsets>(() => M.Read <MinimapIconOffsets>(Address));
 }
Пример #5
0
 public HashNode()
 {
     frameCache = new FrameCache <NativeHashNode>(() => M.Read <NativeHashNode>(Address));
 }
Пример #6
0
 public Actor()
 {
     cacheValue = new FrameCache <ActorComponentOffsets>(() => M.Read <ActorComponentOffsets>(Address));
 }
Пример #7
0
 public ActionWrapper()
 {
     cacheValue = new FrameCache <ActionWrapperOffsets>(() => M.Read <ActionWrapperOffsets>(Address));
 }
Пример #8
0
 public SkillGem()
 {
     _cachedValue  = new FrameCache <SkillGemOffsets>(() => M.Read <SkillGemOffsets>(Address));
     _cachedValue2 = new FrameCache <GemInformation>(() => M.Read <GemInformation>(_cachedValue.Value.AdvanceInformation));
 }
Пример #9
0
        public CustomTileCache(CustomTerrain terrainInfo, Action <uint, string> onMissingImage = null)
        {
            sheetBuilders = new Cache <SheetType, SheetBuilder>(t => new SheetBuilder(t, terrainInfo.SheetSize));

            random = new MersenneTwister();

            var frameCache = new FrameCache(Game.ModData.DefaultFileSystem, Game.ModData.SpriteLoaders);

            foreach (var t in terrainInfo.Templates)
            {
                var variants     = new List <Sprite[]>();
                var templateInfo = (CustomTerrainTemplateInfo)t.Value;

                for (var ii = 0; ii < templateInfo.Images.Length; ii++)
                {
                    var i = templateInfo.Images[ii];

                    ISpriteFrame[] allFrames;

                    if (onMissingImage != null)
                    {
                        try
                        {
                            allFrames = frameCache[i];
                        }
                        catch (FileNotFoundException)
                        {
                            onMissingImage(t.Key, i);
                            continue;
                        }
                    }
                    else
                    {
                        allFrames = frameCache[i];
                    }

                    var frameCount = allFrames.Length;
                    var indices    = templateInfo.Frames != null ? templateInfo.Frames : Exts.MakeArray(t.Value.TilesCount, j => j);

                    var start = indices.Min();
                    var end   = indices.Max();
                    if (start < 0 || end >= frameCount)
                    {
                        throw new YamlException("Template `{0}` uses frames [{1}..{2}] of {3}, but only [0..{4}] actually exist"
                                                .F(t.Key, start, end, i, frameCount - 1));
                    }

                    variants.Add(indices.Select(j =>
                    {
                        var f    = allFrames[j];
                        var tile = t.Value.Contains(j) ? (CustomTerrainTileInfo)t.Value[j] : null;

                        // The internal z axis is inverted from expectation (negative is closer)
                        var zOffset = tile != null ? -tile.ZOffset : 0;
                        var zRamp   = tile != null ? tile.ZRamp : 1f;
                        var offset  = new float3(f.Offset, zOffset);
                        var type    = SheetBuilder.FrameTypeToSheetType(f.Type);

                        var s = sheetBuilders[type].Allocate(f.Size, zRamp, offset);
                        Util.FastCopyIntoChannel(s, f.Data, f.Type);

                        return(s);
                    }).ToArray());
                }

                var allSprites = variants.SelectMany(s => s);

                if (onMissingImage != null && !variants.Any())
                {
                    continue;
                }

                templates.Add(t.Value.Id, new TheaterTemplate(allSprites.ToArray(), variants.First().Length, templateInfo.Images.Length));
            }

            // 1x1px transparent tile
            var missingDataLength = 1;
            var missingFrameType  = SpriteFrameType.Indexed8;
            var missingSheetType  = SheetType.Indexed;

            missingTile = sheetBuilders[missingSheetType].Add(new byte[missingDataLength], missingFrameType, new Size(1, 1));
            foreach (var sb in sheetBuilders.Values)
            {
                sb.Current.ReleaseBuffer();
            }
        }
Пример #10
0
        public DefaultTileCache(DefaultTerrain terrainInfo, Action <uint, string> onMissingImage = null)
        {
            var allocated = false;

            Func <Sheet> allocate = () =>
            {
                if (allocated)
                {
                    throw new SheetOverflowException("Terrain sheet overflow. Try increasing the tileset SheetSize parameter.");
                }
                allocated = true;

                return(new Sheet(SheetType.Indexed, new Size(terrainInfo.SheetSize, terrainInfo.SheetSize)));
            };

            random = new MersenneTwister();

            var frameCache = new FrameCache(Game.ModData.DefaultFileSystem, Game.ModData.SpriteLoaders);

            foreach (var t in terrainInfo.Templates)
            {
                var variants     = new List <Sprite[]>();
                var templateInfo = (DefaultTerrainTemplateInfo)t.Value;

                foreach (var i in templateInfo.Images)
                {
                    ISpriteFrame[] allFrames;
                    if (onMissingImage != null)
                    {
                        try
                        {
                            allFrames = frameCache[i];
                        }
                        catch (FileNotFoundException)
                        {
                            onMissingImage(t.Key, i);
                            continue;
                        }
                    }
                    else
                    {
                        allFrames = frameCache[i];
                    }

                    var frameCount = terrainInfo.EnableDepth ? allFrames.Length / 2 : allFrames.Length;
                    var indices    = templateInfo.Frames != null ? templateInfo.Frames : Exts.MakeArray(t.Value.TilesCount, j => j);

                    var start = indices.Min();
                    var end   = indices.Max();
                    if (start < 0 || end >= frameCount)
                    {
                        throw new YamlException("Template `{0}` uses frames [{1}..{2}] of {3}, but only [0..{4}] actually exist"
                                                .F(t.Key, start, end, i, frameCount - 1));
                    }

                    variants.Add(indices.Select(j =>
                    {
                        var f    = allFrames[j];
                        var tile = t.Value.Contains(j) ? (DefaultTerrainTileInfo)t.Value[j] : null;

                        // The internal z axis is inverted from expectation (negative is closer)
                        var zOffset = tile != null ? -tile.ZOffset : 0;
                        var zRamp   = tile != null ? tile.ZRamp : 1f;
                        var offset  = new float3(f.Offset, zOffset);
                        var type    = SheetBuilder.FrameTypeToSheetType(f.Type);

                        // Defer SheetBuilder creation until we know what type of frames we are loading!
                        // TODO: Support mixed indexed and BGRA frames
                        if (sheetBuilder == null)
                        {
                            sheetBuilder = new SheetBuilder(SheetBuilder.FrameTypeToSheetType(f.Type), allocate);
                        }
                        else if (type != sheetBuilder.Type)
                        {
                            throw new YamlException("Sprite type mismatch. Terrain sprites must all be either Indexed or RGBA.");
                        }

                        var s = sheetBuilder.Allocate(f.Size, zRamp, offset);
                        OpenRA.Graphics.Util.FastCopyIntoChannel(s, f.Data, f.Type);

                        if (terrainInfo.EnableDepth)
                        {
                            var depthFrame = allFrames[j + frameCount];
                            var ss         = sheetBuilder.Allocate(f.Size, zRamp, offset);
                            OpenRA.Graphics.Util.FastCopyIntoChannel(ss, depthFrame.Data, depthFrame.Type);

                            // s and ss are guaranteed to use the same sheet
                            // because of the custom terrain sheet allocation
                            s = new SpriteWithSecondaryData(s, s.Sheet, ss.Bounds, ss.Channel);
                        }

                        return(s);
                    }).ToArray());
                }

                var allSprites = variants.SelectMany(s => s);

                // Ignore the offsets baked into R8 sprites
                if (terrainInfo.IgnoreTileSpriteOffsets)
                {
                    allSprites = allSprites.Select(s => new Sprite(s.Sheet, s.Bounds, s.ZRamp, new float3(float2.Zero, s.Offset.Z), s.Channel, s.BlendMode));
                }

                if (onMissingImage != null && !variants.Any())
                {
                    continue;
                }

                templates.Add(t.Value.Id, new TheaterTemplate(allSprites.ToArray(), variants.First().Count(), templateInfo.Images.Length));
            }

            // 1x1px transparent tile
            if (sheetBuilder.Type == SheetType.BGRA)
            {
                missingTile = sheetBuilder.Add(new byte[4], SpriteFrameType.Bgra32, new Size(1, 1));
            }
            else
            {
                missingTile = sheetBuilder.Add(new byte[1], SpriteFrameType.Indexed8, new Size(1, 1));
            }

            Sheet.ReleaseBuffer();
        }
        /// <summary>
        /// A function that returns the new MdbgFrame. The function is expected to be overriden by derived implementations.
        /// </summary>
        /// <param name="index">0 based index from top of the stack</param>
        /// <returns>frame from the stack</returns>
        protected override MDbgFrame GetFrameImpl(int index)
        {
            if (index < FrameCache.Count)
            {
                return(FrameCache[index]);
            }

            MDbgFrame frameToReturn;

            if (index == 0)
            {
                // special case the first frame
                frameToReturn = ReturnLeafFrame();
            }
            else
            {
                // use recursion...
                MDbgFrame prevFrame = GetFrameImpl(index - 1);
                if (prevFrame == null)
                {
                    throw new ArgumentException();
                }

                frameToReturn = GetFrameCaller(prevFrame);
                if (frameToReturn == null)
                {
                    // we need to get the next frame from the following chain

                    CorChain chain = GetFrameChain(prevFrame);
                    Debug.Assert(chain != null);
                    // 1. find next chain
                    while (true)
                    {
                        chain = chain.Caller;
                        if (chain == null)
                        {
                            break;
                        }

                        if (chain.IsManaged)
                        {
                            CorFrame f = chain.ActiveFrame;
                            if (f != null)
                            {
                                frameToReturn = new MDbgILFrame(Thread, f);
                                break;
                            }
                        }
                        else
                        {
                            frameToReturn = FillAndGetLeafFrameFromNativeChain(chain);
                            if (frameToReturn != null)
                            {
                                break;
                            }
                        }
                    }
                }
            }

            // store and return frameToReturn
            if (frameToReturn != null)
            {
                Debug.Assert(FrameCache.Count >= index);
                if (FrameCache.Count == index)
                {
                    FrameCache.Add(frameToReturn);
                }
                else
                {
                    Debug.Assert(FrameCache[index] == frameToReturn, "List of frames pre-filled with incorrect frame");
                }
            }
            return(frameToReturn);
        }
Пример #12
0
 public SkillGem()
 {
     _Info         = new FrameCache <SkillGemOffsets>(() => M.Read <SkillGemOffsets>(Address));
     _AdvancedInfo = new FrameCache <GemInformation>(() => M.Read <GemInformation>(_Info.Value.AdvanceInformation));
 }