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(); } }
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); } }
protected override void OnAddressChange() { cachedValue = new FrameCache <MinimapIconOffsets>(() => M.Read <MinimapIconOffsets>(Address)); }
public HashNode() { frameCache = new FrameCache <NativeHashNode>(() => M.Read <NativeHashNode>(Address)); }
public Actor() { cacheValue = new FrameCache <ActorComponentOffsets>(() => M.Read <ActorComponentOffsets>(Address)); }
public ActionWrapper() { cacheValue = new FrameCache <ActionWrapperOffsets>(() => M.Read <ActionWrapperOffsets>(Address)); }
public SkillGem() { _cachedValue = new FrameCache <SkillGemOffsets>(() => M.Read <SkillGemOffsets>(Address)); _cachedValue2 = new FrameCache <GemInformation>(() => M.Read <GemInformation>(_cachedValue.Value.AdvanceInformation)); }
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(); } }
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); }
public SkillGem() { _Info = new FrameCache <SkillGemOffsets>(() => M.Read <SkillGemOffsets>(Address)); _AdvancedInfo = new FrameCache <GemInformation>(() => M.Read <GemInformation>(_Info.Value.AdvanceInformation)); }