public Theater(TileSet tileset) { 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(new Size(tileset.SheetSize, tileset.SheetSize), true); }; sheetBuilder = new SheetBuilder(SheetType.Indexed, allocate); templates = new Dictionary<ushort, Sprite[]>(); var frameCache = new FrameCache(Game.modData.SpriteLoaders, tileset.Extensions); foreach (var t in tileset.Templates) { var allFrames = frameCache[t.Value.Image]; var frames = t.Value.Frames != null ? t.Value.Frames.Select(f => allFrames[f]).ToArray() : allFrames; templates.Add(t.Value.Id, frames.Select(f => sheetBuilder.Add(f)).ToArray()); } // 1x1px transparent tile missingTile = sheetBuilder.Add(new byte[1], new Size(1, 1)); Sheet.ReleaseBuffer(); }
Sprite[] LoadTemplate(string filename, string[] exts, Dictionary <string, ISpriteSource> sourceCache, int[] frames) { ISpriteSource source; if (!sourceCache.ContainsKey(filename)) { using (var s = GlobalFileSystem.OpenWithExts(filename, exts)) source = SpriteSource.LoadSpriteSource(s, filename); if (source.CacheWhenLoadingTileset) { sourceCache.Add(filename, source); } } else { source = sourceCache[filename]; } if (frames != null) { var ret = new List <Sprite>(); var srcFrames = source.Frames.ToArray(); foreach (var i in frames) { ret.Add(sheetBuilder.Add(srcFrames[i])); } return(ret.ToArray()); } return(source.Frames.Select(f => sheetBuilder.Add(f)).ToArray()); }
public Theater(TileSet tileset) { 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(new Size(tileset.SheetSize, tileset.SheetSize), true)); }; sheetBuilder = new SheetBuilder(SheetType.Indexed, allocate); templates = new Dictionary <ushort, Sprite[]>(); var frameCache = new FrameCache(Game.modData.SpriteLoaders, tileset.Extensions); foreach (var t in tileset.Templates) { var allFrames = frameCache[t.Value.Image]; var frames = t.Value.Frames != null?t.Value.Frames.Select(f => allFrames[f]).ToArray() : allFrames; templates.Add(t.Value.Id, frames.Select(f => sheetBuilder.Add(f)).ToArray()); } // 1x1px transparent tile missingTile = sheetBuilder.Add(new byte[1], new Size(1, 1)); Sheet.ReleaseBuffer(); }
public Theater(TileSet tileset) { this.tileset = tileset; 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(new Size(tileset.SheetSize, tileset.SheetSize))); }; sheetBuilder = new SheetBuilder(SheetType.Indexed, allocate); random = new MersenneTwister(); var frameCache = new FrameCache(Game.ModData.SpriteLoaders); foreach (var t in tileset.Templates) { var variants = new List <Sprite[]>(); foreach (var i in t.Value.Images) { var allFrames = frameCache[i]; var frames = t.Value.Frames != null?t.Value.Frames.Select(f => allFrames[f]).ToArray() : allFrames; variants.Add(frames.Select(f => sheetBuilder.Add(f)).ToArray()); } var allSprites = variants.SelectMany(s => s); // Ignore the offsets baked into R8 sprites if (tileset.IgnoreTileSpriteOffsets) { allSprites = allSprites.Select(s => new Sprite(s.Sheet, s.Bounds, float2.Zero, s.Channel, s.BlendMode)); } templates.Add(t.Value.Id, new TheaterTemplate(allSprites.ToArray(), variants.First().Count(), t.Value.Images.Length)); } // 1x1px transparent tile missingTile = sheetBuilder.Add(new byte[1], new Size(1, 1)); Sheet.ReleaseBuffer(); }
public Theater(TileSet tileset) { 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(new Size(tileset.SheetSize, tileset.SheetSize), true)); }; var sourceCache = new Dictionary <string, ISpriteSource>(); templates = new Dictionary <ushort, Sprite[]>(); sheetBuilder = new SheetBuilder(SheetType.Indexed, allocate); foreach (var t in tileset.Templates) { templates.Add(t.Value.Id, LoadTemplate(t.Value.Image, tileset.Extensions, sourceCache, t.Value.Frames)); } // 1x1px transparent tile missingTile = sheetBuilder.Add(new byte[1], new Size(1, 1)); Sheet.ReleaseBuffer(); }
public Theater(TileSet tileset) { 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(new Size(tileset.SheetSize, tileset.SheetSize))); }; var r8Cache = new Cache <string, R8Reader>(s => new R8Reader(FileSystem.OpenWithExts(s, ".R8"))); templates = new Dictionary <ushort, Sprite[]>(); sheetBuilder = new SheetBuilder(SheetType.Indexed, allocate); foreach (var t in tileset.Templates) { templates.Add(t.Value.Id, LoadTemplate(t.Value.Image, tileset.Extensions, r8Cache, t.Value.Frames)); } // 1x1px transparent tile missingTile = sheetBuilder.Add(new byte[1], new Size(1, 1)); }
public HardwareCursor(CursorProvider cursorProvider) { this.cursorProvider = cursorProvider; paletteReferences = new Cache <string, PaletteReference>(CreatePaletteReference); foreach (var p in cursorProvider.Palettes) { hardwarePalette.AddPalette(p.Key, p.Value, false); } hardwarePalette.Initialize(); sheetBuilder = new SheetBuilder(SheetType.Indexed); foreach (var kv in cursorProvider.Cursors) { var palette = cursorProvider.Palettes[kv.Value.Palette]; var hc = kv.Value.Frames .Select(f => CreateCursor(f, palette, kv.Key, kv.Value)) .ToArray(); hardwareCursors.Add(kv.Key, hc); var s = kv.Value.Frames.Select(a => sheetBuilder.Add(a)).ToArray(); sprites.Add(kv.Key, s); } sheetBuilder.Current.ReleaseBuffer(); Update(); }
Sprite[] CacheSpriteFrames(string filename) { using (var stream = GlobalFileSystem.OpenWithExts(filename, exts)) return(SpriteSource.LoadSpriteSource(stream, filename).Frames .Select(a => SheetBuilder.Add(a)) .ToArray()); }
public HardwareCursor(CursorProvider cursorProvider) { this.cursorProvider = cursorProvider; paletteReferences = new Cache <string, PaletteReference>(CreatePaletteReference); foreach (var p in cursorProvider.Palettes) { hardwarePalette.AddPalette(p.Key, p.Value, false); } hardwarePalette.Initialize(); sheetBuilder = new SheetBuilder(SheetType.Indexed); foreach (var kv in cursorProvider.Cursors) { var frames = kv.Value.Frames; var palette = cursorProvider.Palettes[kv.Value.Palette]; // Hardware cursors have a number of odd platform-specific bugs/limitations. // Reduce the number of edge cases by padding the individual frames such that: // - the hotspot is inside the frame bounds (enforced by SDL) // - all frames within a sequence have the same size (needed for macOS 10.15) // - the frame size is a multiple of 8 (needed for Windows) var sequenceBounds = Rectangle.FromLTRB(0, 0, 1, 1); var frameHotspots = new int2[frames.Length]; for (var i = 0; i < frames.Length; i++) { // Hotspot relative to the center of the frame frameHotspots[i] = kv.Value.Hotspot - frames[i].Offset.ToInt2() + new int2(frames[i].Size) / 2; // Bounds relative to the hotspot sequenceBounds = Rectangle.Union(sequenceBounds, new Rectangle(-frameHotspots[i], frames[i].Size)); } // Pad bottom-right edge to make the frame size a multiple of 8 var paddedSize = 8 * new int2((sequenceBounds.Width + 7) / 8, (sequenceBounds.Height + 7) / 8); var cursors = new IHardwareCursor[frames.Length]; var frameSprites = new Sprite[frames.Length]; for (var i = 0; i < frames.Length; i++) { // Software rendering is used when the cursor is locked frameSprites[i] = sheetBuilder.Add(frames[i].Data, frames[i].Size, 0, frames[i].Offset); // Calculate the padding to position the frame within sequenceBounds var paddingTL = -(sequenceBounds.Location + frameHotspots[i]); var paddingBR = paddedSize - new int2(frames[i].Size) - paddingTL; cursors[i] = CreateCursor(kv.Key, frames[i], palette, paddingTL, paddingBR, -sequenceBounds.Location); } hardwareCursors.Add(kv.Key, cursors); sprites.Add(kv.Key, frameSprites); } sheetBuilder.Current.ReleaseBuffer(); Update(); }
public Theater(TileSet tileset) { this.tileset = tileset; 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(new Size(tileset.SheetSize, tileset.SheetSize)); }; sheetBuilder = new SheetBuilder(SheetType.Indexed, allocate); random = new MersenneTwister(); var frameCache = new FrameCache(Game.ModData.SpriteLoaders); foreach (var t in tileset.Templates) { var variants = new List<Sprite[]>(); foreach (var i in t.Value.Images) { var allFrames = frameCache[i]; var frames = t.Value.Frames != null ? t.Value.Frames.Select(f => allFrames[f]).ToArray() : allFrames; variants.Add(frames.Select(f => sheetBuilder.Add(f)).ToArray()); } var allSprites = variants.SelectMany(s => s); // Ignore the offsets baked into R8 sprites if (tileset.IgnoreTileSpriteOffsets) allSprites = allSprites.Select(s => new Sprite(s.Sheet, s.Bounds, float2.Zero, s.Channel, s.BlendMode)); templates.Add(t.Value.Id, new TheaterTemplate(allSprites.ToArray(), variants.First().Count(), t.Value.Images.Length)); } // 1x1px transparent tile missingTile = sheetBuilder.Add(new byte[1], new Size(1, 1)); Sheet.ReleaseBuffer(); }
public CursorManager(CursorProvider cursorProvider) { hardwareCursorsDisabled = Game.Settings.Graphics.DisableHardwareCursors; graphicSettings = Game.Settings.Graphics; sheetBuilder = new SheetBuilder(SheetType.BGRA); foreach (var kv in cursorProvider.Cursors) { var frames = kv.Value.Frames; var palette = !string.IsNullOrEmpty(kv.Value.Palette) ? cursorProvider.Palettes[kv.Value.Palette] : null; var c = new Cursor { Name = kv.Key, Bounds = Rectangle.FromLTRB(0, 0, 1, 1), Length = 0, Sprites = new Sprite[frames.Length], Cursors = new IHardwareCursor[frames.Length] }; // Hardware cursors have a number of odd platform-specific bugs/limitations. // Reduce the number of edge cases by padding the individual frames such that: // - the hotspot is inside the frame bounds (enforced by SDL) // - all frames within a sequence have the same size (needed for macOS 10.15) // - the frame size is a multiple of 8 (needed for Windows) foreach (var f in frames) { // Hotspot is specified relative to the center of the frame var hotspot = f.Offset.ToInt2() - kv.Value.Hotspot - new int2(f.Size) / 2; // SheetBuilder expects data in BGRA var data = FrameToBGRA(kv.Key, f, palette); c.Sprites[c.Length++] = sheetBuilder.Add(data, f.Size, 0, hotspot); // Bounds relative to the hotspot c.Bounds = Rectangle.Union(c.Bounds, new Rectangle(hotspot, f.Size)); } // Pad bottom-right edge to make the frame size a multiple of 8 c.PaddedSize = 8 * new int2((c.Bounds.Width + 7) / 8, (c.Bounds.Height + 7) / 8); cursors.Add(kv.Key, c); } CreateOrUpdateHardwareCursors(); foreach (var s in sheetBuilder.AllSheets) { s.ReleaseBuffer(); } Update(); }
/// <summary> /// Returns the first set of sprites with the given filename. /// If getUsedFrames is defined then the indices returned by the function call /// are guaranteed to be loaded. The value of other indices in the returned /// array are undefined and should never be accessed. /// </summary> public Sprite[] this[string filename, Func <int, IEnumerable <int> > getUsedFrames = null] { get { var allSprites = sprites.GetOrAdd(filename); var sprite = allSprites.FirstOrDefault(); ISpriteFrame[] unloaded; if (!unloadedFrames.TryGetValue(filename, out unloaded)) { unloaded = null; } // This is the first time that the file has been requested // Load all of the frames into the unused buffer and initialize // the loaded cache (initially empty) if (sprite == null) { TypeDictionary fileMetadata = null; unloaded = FrameLoader.GetFrames(fileSystem, filename, loaders, out fileMetadata); unloadedFrames[filename] = unloaded; metadata[filename] = fileMetadata; sprite = new Sprite[unloaded.Length]; allSprites.Add(sprite); } // HACK: The sequency code relies on side-effects from getUsedFrames var indices = getUsedFrames != null?getUsedFrames(sprite.Length) : Enumerable.Range(0, sprite.Length); // Load any unused frames into the SheetBuilder if (unloaded != null) { foreach (var i in indices) { if (unloaded[i] != null) { sprite[i] = SheetBuilder.Add(unloaded[i]); unloaded[i] = null; } } // All frames have been loaded if (unloaded.All(f => f == null)) { unloadedFrames.Remove(filename); } } return(sprite); } }
Sprite[] LoadSprites(string filename) { // TODO: Cleanly abstract file type detection if (filename.ToLower().EndsWith("r8")) { var r8 = new R8Reader(FileSystem.Open(filename)); return(r8.Select(a => SheetBuilder.Add(a.Image, a.Size, a.Offset)).ToArray()); } BinaryReader reader = new BinaryReader(FileSystem.OpenWithExts(filename, exts)); var ImageCount = reader.ReadUInt16(); if (ImageCount == 0) { var shp = new ShpTSReader(FileSystem.OpenWithExts(filename, exts)); return(shp.Select(a => SheetBuilder.Add(a.Image, shp.Size)).ToArray()); } else { var shp = new ShpReader(FileSystem.OpenWithExts(filename, exts)); return(shp.Frames.Select(a => SheetBuilder.Add(a.Image, shp.Size)).ToArray()); } }
Sprite[] LoadTemplate(string filename, string[] exts, Cache <string, R8Reader> r8Cache, int[] frames) { if (exts.Contains(".R8") && FileSystem.Exists(filename + ".R8")) { return(frames.Select(f => { if (f < 0) { return null; } var image = r8Cache[filename][f]; return sheetBuilder.Add(image.Image, new Size(image.Size.Width, image.Size.Height)); }).ToArray()); } using (var s = FileSystem.OpenWithExts(filename, exts)) { var t = new Terrain(s); return(t.TileBitmapBytes .Select(b => b != null ? sheetBuilder.Add(b, new Size(t.Width, t.Height)) : null) .ToArray()); } }
public SoftwareCursor(CursorProvider cursorProvider) { this.cursorProvider = cursorProvider; paletteReferences = new Cache<string, PaletteReference>(CreatePaletteReference); foreach (var p in cursorProvider.Palettes) palette.AddPalette(p.Key, p.Value, false); palette.Initialize(); sheetBuilder = new SheetBuilder(SheetType.Indexed); foreach (var kv in cursorProvider.Cursors) { var s = kv.Value.Frames.Select(a => sheetBuilder.Add(a)).ToArray(); sprites.Add(kv.Key, s); } sheetBuilder.Current.ReleaseBuffer(); Game.Renderer.Device.SetHardwareCursor(null); }
public Theater(TileSet tileset) { 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(new Size(tileset.SheetSize, tileset.SheetSize)); }; var sourceCache = new Dictionary<string, ISpriteSource>(); templates = new Dictionary<ushort, Sprite[]>(); sheetBuilder = new SheetBuilder(SheetType.Indexed, allocate); foreach (var t in tileset.Templates) templates.Add(t.Value.Id, LoadTemplate(t.Value.Image, tileset.Extensions, sourceCache, t.Value.Frames)); // 1x1px transparent tile missingTile = sheetBuilder.Add(new byte[1], new Size(1, 1)); }
public SoftwareCursor(CursorProvider cursorProvider) { this.cursorProvider = cursorProvider; paletteReferences = new Cache <string, PaletteReference>(CreatePaletteReference); foreach (var p in cursorProvider.Palettes) { palette.AddPalette(p.Key, p.Value, false); } palette.Initialize(); sheetBuilder = new SheetBuilder(SheetType.Indexed); foreach (var kv in cursorProvider.Cursors) { var s = kv.Value.Frames.Select(a => sheetBuilder.Add(a)).ToArray(); sprites.Add(kv.Key, s); } sheetBuilder.Current.ReleaseBuffer(); Game.Renderer.Window.SetHardwareCursor(null); }
public static Sprite[] GetSprites(string filename, ISpriteLoader[] loaders, SheetBuilder sheetBuilder) { return(GetFrames(filename, loaders).Select(a => sheetBuilder.Add(a)).ToArray()); }
public override void Init(ModData modData, Dictionary<string, string> info) { // Avoid standard loading mechanisms so we // can display the loadscreen as early as possible r = Game.Renderer; if (r == null) return; if (info.ContainsKey("Text")) messages = info["Text"].Split(','); if (info.ContainsKey("Palette")) { using (var stream = modData.DefaultFileSystem.Open(info["Palette"])) { palette = new ImmutablePalette(stream, new int[] { }); } hardwarePalette = new HardwarePalette(); hardwarePalette.AddPalette("loadscreen", palette, false); hardwarePalette.Initialize(); r.SetPalette(hardwarePalette); } if (info.ContainsKey("Image")) { using (var stream = modData.DefaultFileSystem.Open(info["Image"])) { CpsD2Loader loader = new CpsD2Loader(); if (!loader.TryParseSprite(stream, out frames)) return; } if (frames.Length == 0) return; sheetBuilder = new SheetBuilder(SheetType.Indexed, 512); logo = sheetBuilder.Add(frames[0]); logoPos = new float2((r.Resolution.Width - logo.Size.X) / 2, (r.Resolution.Height - logo.Size.Y) / 2); } }
public static Sprite[] GetSprites(IReadOnlyFileSystem fileSystem, string filename, ISpriteLoader[] loaders, SheetBuilder sheetBuilder) { return GetFrames(fileSystem, filename, loaders).Select(a => sheetBuilder.Add(a)).ToArray(); }
public Theater(TileSet tileset, Action <uint, string> onMissingImage = null) { this.tileset = tileset; 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(tileset.SheetSize, tileset.SheetSize))); }; random = new MersenneTwister(); var frameCache = new FrameCache(Game.ModData.DefaultFileSystem, Game.ModData.SpriteLoaders); foreach (var t in tileset.Templates) { var variants = new List <Sprite[]>(); foreach (var i in t.Value.Images) { ISpriteFrame[] allFrames; if (onMissingImage != null) { try { allFrames = frameCache[i]; } catch (FileNotFoundException) { onMissingImage(t.Key, i); continue; } } else { allFrames = frameCache[i]; } var frameCount = tileset.EnableDepth ? allFrames.Length / 2 : allFrames.Length; var indices = t.Value.Frames != null ? t.Value.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) ? 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); Util.FastCopyIntoChannel(s, f.Data); if (tileset.EnableDepth) { var ss = sheetBuilder.Allocate(f.Size, zRamp, offset); Util.FastCopyIntoChannel(ss, allFrames[j + frameCount].Data); // 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 (tileset.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(), t.Value.Images.Length)); } // 1x1px transparent tile missingTile = sheetBuilder.Add(new byte[sheetBuilder.Type == SheetType.BGRA ? 4 : 1], new Size(1, 1)); Sheet.ReleaseBuffer(); }
public ModBrowserLogic(Widget widget) { modChooserPanel = widget; loadButton = modChooserPanel.Get<ButtonWidget>("LOAD_BUTTON"); loadButton.OnClick = () => LoadMod(selectedMod); loadButton.IsDisabled = () => selectedMod.Id == Game.ModData.Manifest.Mod.Id; modChooserPanel.Get<ButtonWidget>("QUIT_BUTTON").OnClick = Game.Exit; modList = modChooserPanel.Get("MOD_LIST"); modTemplate = modList.Get<ButtonWidget>("MOD_TEMPLATE"); modChooserPanel.Get<LabelWidget>("MOD_DESC").GetText = () => selectedDescription; modChooserPanel.Get<LabelWidget>("MOD_TITLE").GetText = () => selectedMod.Title; modChooserPanel.Get<LabelWidget>("MOD_AUTHOR").GetText = () => selectedAuthor; modChooserPanel.Get<LabelWidget>("MOD_VERSION").GetText = () => selectedMod.Version; var prevMod = modChooserPanel.Get<ButtonWidget>("PREV_MOD"); prevMod.OnClick = () => { modOffset -= 1; RebuildModList(); }; prevMod.IsVisible = () => modOffset > 0; var nextMod = modChooserPanel.Get<ButtonWidget>("NEXT_MOD"); nextMod.OnClick = () => { modOffset += 1; RebuildModList(); }; nextMod.IsVisible = () => modOffset + 5 < allMods.Length; modChooserPanel.Get<RGBASpriteWidget>("MOD_PREVIEW").GetSprite = () => { Sprite ret = null; previews.TryGetValue(selectedMod.Id, out ret); return ret; }; sheetBuilder = new SheetBuilder(SheetType.BGRA); allMods = ModMetadata.AllMods.Values.Where(m => !m.Hidden) .OrderBy(m => m.Title) .ToArray(); // Load preview images, and eat any errors foreach (var mod in allMods) { try { using (var preview = new Bitmap(Platform.ResolvePath(".", "mods", mod.Id, "preview.png"))) if (preview.Width == 296 && preview.Height == 196) previews.Add(mod.Id, sheetBuilder.Add(preview)); } catch (Exception) { } try { using (var logo = new Bitmap(Platform.ResolvePath(".", "mods", mod.Id, "logo.png"))) if (logo.Width == 96 && logo.Height == 96) logos.Add(mod.Id, sheetBuilder.Add(logo)); } catch (Exception) { } } modInstallStatus = new Cache<ModMetadata, bool>(IsModInstalled); ModMetadata initialMod; ModMetadata.AllMods.TryGetValue(Game.Settings.Game.PreviousMod, out initialMod); SelectMod(initialMod != null && initialMod.Id != "modchooser" ? initialMod : ModMetadata.AllMods["ra"]); RebuildModList(); }
public Theater(TileSet tileset) { this.tileset = tileset; var allocated = false; var type = tileset.EnableDepth ? SheetType.DualIndexed : SheetType.Indexed; Func<Sheet> allocate = () => { if (allocated) throw new SheetOverflowException("Terrain sheet overflow. Try increasing the tileset SheetSize parameter."); allocated = true; return new Sheet(type, new Size(tileset.SheetSize, tileset.SheetSize)); }; sheetBuilder = new SheetBuilder(type, allocate); random = new MersenneTwister(); var frameCache = new FrameCache(Game.ModData.SpriteLoaders); foreach (var t in tileset.Templates) { var variants = new List<Sprite[]>(); foreach (var i in t.Value.Images) { var allFrames = frameCache[i]; var frameCount = tileset.EnableDepth ? allFrames.Length / 2 : allFrames.Length; var indices = t.Value.Frames != null ? t.Value.Frames : Enumerable.Range(0, frameCount); variants.Add(indices.Select(j => { var f = allFrames[j]; var s = sheetBuilder.Allocate(f.Size, f.Offset); Util.FastCopyIntoChannel(s, 0, f.Data); if (tileset.EnableDepth) Util.FastCopyIntoChannel(s, 1, allFrames[j + frameCount].Data); return s; }).ToArray()); } var allSprites = variants.SelectMany(s => s); // Ignore the offsets baked into R8 sprites if (tileset.IgnoreTileSpriteOffsets) allSprites = allSprites.Select(s => new Sprite(s.Sheet, s.Bounds, float2.Zero, s.Channel, s.BlendMode)); templates.Add(t.Value.Id, new TheaterTemplate(allSprites.ToArray(), variants.First().Count(), t.Value.Images.Length)); } // 1x1px transparent tile missingTile = sheetBuilder.Add(new byte[1], new Size(1, 1)); Sheet.ReleaseBuffer(); }
public ModBrowserLogic(Widget widget) { var panel = widget; var loadButton = panel.Get<ButtonWidget>("LOAD_BUTTON"); loadButton.OnClick = () => LoadMod(selectedMod); loadButton.IsDisabled = () => selectedMod.Id == Game.modData.Manifest.Mod.Id; panel.Get<ButtonWidget>("QUIT_BUTTON").OnClick = Game.Exit; modList = panel.Get("MOD_LIST"); modTemplate = modList.Get<ButtonWidget>("MOD_TEMPLATE"); panel.Get<LabelWidget>("MOD_DESC").GetText = () => selectedDescription; panel.Get<LabelWidget>("MOD_TITLE").GetText = () => selectedMod.Title; panel.Get<LabelWidget>("MOD_AUTHOR").GetText = () => selectedAuthor; panel.Get<LabelWidget>("MOD_VERSION").GetText = () => selectedMod.Version; var prevMod = panel.Get<ButtonWidget>("PREV_MOD"); prevMod.OnClick = () => { modOffset -= 1; RebuildModList(); }; prevMod.IsVisible = () => modOffset > 0; var nextMod = panel.Get<ButtonWidget>("NEXT_MOD"); nextMod.OnClick = () => { modOffset += 1; RebuildModList(); }; nextMod.IsVisible = () => modOffset + 5 < allMods.Length; panel.Get<RGBASpriteWidget>("MOD_PREVIEW").GetSprite = () => { Sprite ret = null; previews.TryGetValue(selectedMod.Id, out ret); return ret; }; var sheetBuilder = new SheetBuilder(SheetType.BGRA); previews = new Dictionary<string, Sprite>(); logos = new Dictionary<string, Sprite>(); allMods = ModMetadata.AllMods.Values.Where(m => m.Id != "modchooser") .OrderBy(m => m.Title) .ToArray(); // Load preview images, and eat any errors foreach (var mod in allMods) { try { var preview = new Bitmap(new[] { "mods", mod.Id, "preview.png" }.Aggregate(Path.Combine)); if (preview.Width != 296 || preview.Height != 196) continue; previews.Add(mod.Id, sheetBuilder.Add(preview)); } catch (Exception) { } try { var logo = new Bitmap(new[] { "mods", mod.Id, "logo.png" }.Aggregate(Path.Combine)); if (logo.Width != 96 || logo.Height != 96) continue; logos.Add(mod.Id, sheetBuilder.Add(logo)); } catch (Exception) { } } ModMetadata initialMod = null; ModMetadata.AllMods.TryGetValue(Game.Settings.Game.PreviousMod, out initialMod); SelectMod(initialMod ?? ModMetadata.AllMods["ra"]); RebuildModList(); }
Sprite[] LoadSprites(string filename) { var shp = new ShpReader(FileSystem.OpenWithExts(filename, exts)); return(shp.Select(a => SheetBuilder.Add(a.Image, shp.Size)).ToArray()); }
public Theater(TileSet tileset) { this.tileset = tileset; 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(tileset.SheetSize, tileset.SheetSize)); }; sheetBuilder = new SheetBuilder(SheetType.Indexed, allocate); random = new MersenneTwister(); var frameCache = new FrameCache(Game.ModData.DefaultFileSystem, Game.ModData.SpriteLoaders); foreach (var t in tileset.Templates) { var variants = new List<Sprite[]>(); foreach (var i in t.Value.Images) { var allFrames = frameCache[i]; var frameCount = tileset.EnableDepth ? allFrames.Length / 2 : allFrames.Length; var indices = t.Value.Frames != null ? t.Value.Frames : Enumerable.Range(0, frameCount); variants.Add(indices.Select(j => { var f = allFrames[j]; var tile = t.Value.Contains(j) ? 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 s = sheetBuilder.Allocate(f.Size, zRamp, offset); Util.FastCopyIntoChannel(s, f.Data); if (tileset.EnableDepth) { var ss = sheetBuilder.Allocate(f.Size, zRamp, offset); Util.FastCopyIntoChannel(ss, allFrames[j + frameCount].Data); // s and ss are guaranteed to use the same sheet // because of the custom terrain sheet allocation s = new SpriteWithSecondaryData(s, ss.Bounds, ss.Channel); } return s; }).ToArray()); } var allSprites = variants.SelectMany(s => s); // Ignore the offsets baked into R8 sprites if (tileset.IgnoreTileSpriteOffsets) allSprites = allSprites.Select(s => new Sprite(s.Sheet, s.Bounds, s.ZRamp, new float3(float2.Zero, s.Offset.Z), s.Channel, s.BlendMode)); templates.Add(t.Value.Id, new TheaterTemplate(allSprites.ToArray(), variants.First().Count(), t.Value.Images.Length)); } // 1x1px transparent tile missingTile = sheetBuilder.Add(new byte[1], new Size(1, 1)); Sheet.ReleaseBuffer(); }
public Theater(TileSet tileset) { this.tileset = tileset; 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(tileset.SheetSize, tileset.SheetSize))); }; sheetBuilder = new SheetBuilder(SheetType.Indexed, allocate); random = new MersenneTwister(); var frameCache = new FrameCache(Game.ModData.DefaultFileSystem, Game.ModData.SpriteLoaders); foreach (var t in tileset.Templates) { var variants = new List <Sprite[]>(); foreach (var i in t.Value.Images) { var allFrames = frameCache[i]; var frameCount = tileset.EnableDepth ? allFrames.Length / 2 : allFrames.Length; var indices = t.Value.Frames != null ? t.Value.Frames : Enumerable.Range(0, frameCount); variants.Add(indices.Select(j => { var f = allFrames[j]; var tile = t.Value.Contains(j) ? 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 s = sheetBuilder.Allocate(f.Size, zRamp, offset); Util.FastCopyIntoChannel(s, f.Data); if (tileset.EnableDepth) { var ss = sheetBuilder.Allocate(f.Size, zRamp, offset); Util.FastCopyIntoChannel(ss, allFrames[j + frameCount].Data); // s and ss are guaranteed to use the same sheet // because of the custom terrain sheet allocation s = new SpriteWithSecondaryData(s, ss.Bounds, ss.Channel); } return(s); }).ToArray()); } var allSprites = variants.SelectMany(s => s); // Ignore the offsets baked into R8 sprites if (tileset.IgnoreTileSpriteOffsets) { allSprites = allSprites.Select(s => new Sprite(s.Sheet, s.Bounds, s.ZRamp, new float3(float2.Zero, s.Offset.Z), s.Channel, s.BlendMode)); } templates.Add(t.Value.Id, new TheaterTemplate(allSprites.ToArray(), variants.First().Count(), t.Value.Images.Length)); } // 1x1px transparent tile missingTile = sheetBuilder.Add(new byte[1], new Size(1, 1)); Sheet.ReleaseBuffer(); }
public ModBrowserLogic(Widget widget, ModData modData) { modChooserPanel = widget; loadButton = modChooserPanel.Get<ButtonWidget>("LOAD_BUTTON"); loadButton.OnClick = () => LoadMod(selectedMod); loadButton.IsDisabled = () => selectedMod.Id == modData.Manifest.Id; var contentButton = modChooserPanel.Get<ButtonWidget>("CONFIGURE_BUTTON"); contentButton.OnClick = () => { var widgetArgs = new WidgetArgs { { "mod", selectedMod }, { "content", content[selectedMod] }, { "onCancel", () => { } } }; Ui.OpenWindow("CONTENT_PANEL", widgetArgs); }; modChooserPanel.Get<ButtonWidget>("QUIT_BUTTON").OnClick = Game.Exit; modList = modChooserPanel.Get("MOD_LIST"); modTemplate = modList.Get<ButtonWidget>("MOD_TEMPLATE"); modChooserPanel.Get<LabelWidget>("MOD_DESC").GetText = () => selectedDescription; modChooserPanel.Get<LabelWidget>("MOD_TITLE").GetText = () => selectedMod.Metadata.Title; modChooserPanel.Get<LabelWidget>("MOD_AUTHOR").GetText = () => selectedAuthor; modChooserPanel.Get<LabelWidget>("MOD_VERSION").GetText = () => selectedMod.Metadata.Version; var prevMod = modChooserPanel.Get<ButtonWidget>("PREV_MOD"); prevMod.OnClick = () => { modOffset -= 1; RebuildModList(); }; prevMod.IsVisible = () => modOffset > 0; var nextMod = modChooserPanel.Get<ButtonWidget>("NEXT_MOD"); nextMod.OnClick = () => { modOffset += 1; RebuildModList(); }; nextMod.IsVisible = () => modOffset + 5 < allMods.Length; modChooserPanel.Get<RGBASpriteWidget>("MOD_PREVIEW").GetSprite = () => { Sprite ret = null; previews.TryGetValue(selectedMod.Id, out ret); return ret; }; sheetBuilder = new SheetBuilder(SheetType.BGRA); allMods = Game.Mods.Values.Where(m => !m.Metadata.Hidden) .OrderBy(m => m.Metadata.Title) .ToArray(); // Load preview images, and eat any errors foreach (var mod in allMods) { try { using (var stream = mod.Package.GetStream("preview.png")) using (var preview = new Bitmap(stream)) if (preview.Width == 296 && preview.Height == 196) previews.Add(mod.Id, sheetBuilder.Add(preview)); } catch (Exception) { } try { using (var stream = mod.Package.GetStream("logo.png")) using (var logo = new Bitmap(stream)) if (logo.Width == 96 && logo.Height == 96) logos.Add(mod.Id, sheetBuilder.Add(logo)); } catch (Exception) { } } Manifest initialMod; Game.Mods.TryGetValue(Game.Settings.Game.PreviousMod, out initialMod); SelectMod(initialMod != null && initialMod.Id != "modchooser" ? initialMod : Game.Mods["ra"]); RebuildModList(); }
public Theater(TileSet tileset) { this.tileset = tileset; var allocated = false; var type = tileset.EnableDepth ? SheetType.DualIndexed : SheetType.Indexed; Func <Sheet> allocate = () => { if (allocated) { throw new SheetOverflowException("Terrain sheet overflow. Try increasing the tileset SheetSize parameter."); } allocated = true; return(new Sheet(type, new Size(tileset.SheetSize, tileset.SheetSize))); }; sheetBuilder = new SheetBuilder(type, allocate); random = new MersenneTwister(); var frameCache = new FrameCache(Game.ModData.DefaultFileSystem, Game.ModData.SpriteLoaders); foreach (var t in tileset.Templates) { var variants = new List <Sprite[]>(); foreach (var i in t.Value.Images) { var allFrames = frameCache[i]; var frameCount = tileset.EnableDepth ? allFrames.Length / 2 : allFrames.Length; var indices = t.Value.Frames != null ? t.Value.Frames : Enumerable.Range(0, frameCount); variants.Add(indices.Select(j => { var f = allFrames[j]; var s = sheetBuilder.Allocate(f.Size, f.Offset); Util.FastCopyIntoChannel(s, 0, f.Data); if (tileset.EnableDepth) { Util.FastCopyIntoChannel(s, 1, allFrames[j + frameCount].Data); } return(s); }).ToArray()); } var allSprites = variants.SelectMany(s => s); // Ignore the offsets baked into R8 sprites if (tileset.IgnoreTileSpriteOffsets) { allSprites = allSprites.Select(s => new Sprite(s.Sheet, s.Bounds, float2.Zero, s.Channel, s.BlendMode)); } templates.Add(t.Value.Id, new TheaterTemplate(allSprites.ToArray(), variants.First().Count(), t.Value.Images.Length)); } // 1x1px transparent tile missingTile = sheetBuilder.Add(new byte[1], new Size(1, 1)); Sheet.ReleaseBuffer(); }
public static Sprite[] GetSprites(string filename, string[] exts, ISpriteLoader[] loaders, SheetBuilder sheetBuilder) { return GetFrames(filename, exts, loaders).Select(a => sheetBuilder.Add(a)).ToArray(); }