// IMPORTANT: This method is SLOOOOOOOWWWWWW.... void DebugEmitImages(GraphicsDevice graphicsDevice) { var loadHelper = new SimpleTextureLoadHelper(graphicsDevice); for (int i = 0; i < offsets.Length - 1; i++) { using (var bundle = new ImageBundle()) { bundle.ReadAllImages(texturePackageData, offsets[i], loadHelper); for (int t = 0; t < bundle.textures.Length; t++) { var path = Path.Combine("ImageBundles", names[i] + " (" + t + ").gif"); Directory.CreateDirectory(Path.GetDirectoryName(path)); Animation animation = Animation.CreateSingleSprite(new Sprite(bundle.textures[t])); using (var fs = File.Create(path)) { // Because Texture2D.SaveAsPng leaks memory. :( GifWriter gifWriter = new GifWriter(); gifWriter.SetStream(fs); gifWriter.WriteAnimation(animation); gifWriter.CloseStream(); } } } } }
private void LiveListEvict(int liveIndex) { Debug.Assert(liveIndex >= 0 && liveIndex < liveCount); ImageBundle bundle = liveListBundles[liveIndex]; Debug.Assert(bundle.liveIndex == liveIndex); Debug.WriteLine("Evicting image bundle: " + GetBundleName(bundle.bundleIndex)); // Recover the textures from the bundle being evicted for (int i = 0; i < bundle.textures.Length; i++) { int classification = ClassifyTexture(bundle.textures[i].Width, bundle.textures[i].Height); idleTextures[classification].Push(bundle.textures[i]); bundle.textures[i] = null; } // Move another live bundle into its slot (unordered removal): liveCount--; liveListBundles[liveIndex] = liveListBundles[liveCount]; liveListBundles[liveIndex].liveIndex = liveIndex; liveListBundles[liveCount] = null; // <- clear so the GC doesn't see it liveListState[liveIndex] = liveListState[liveCount]; // Set the bundle as dead: // NOTE: Must do this AFTER the above removal, as we may swap with ourself bundle.liveIndex = -1; }
internal void RegisterAlive(ImageBundle bundle) { Debug.Assert(bundle.liveIndex == -1); if (bundle.textures.Length == 0) { return; // <- skip bundles without textures, as they can never be reclaimed, and would just waste space in the live list } byte bucketFlags = 0; for (int i = 0; i < bundle.textures.Length; i++) { int classification = ClassifyTexture(bundle.textures[i].Width, bundle.textures[i].Height); bucketFlags |= (byte)(1u << classification); } LiveListEnsureCapacity(); liveListState[liveCount] = new BundleState { timeOut = 0, bucketFlags = bucketFlags }; liveListBundles[liveCount] = bundle; bundle.liveIndex = liveCount; liveCount++; }
internal void MakeBundleAlive(ImageBundle bundle) { Debug.Assert(canLoadTextures); Debug.Assert(bundle.liveIndex == -1); // Super-speedy: int finalOffset = bundle.ReadAllImages(texturePackageData, offsets[bundle.bundleIndex], this); Debug.Assert(finalOffset == -1 || finalOffset == offsets[bundle.bundleIndex + 1]); // <- Read the expected number of bytes! // https://www.youtube.com/watch?v=xos2MnVxe-c RegisterAlive(bundle); }
// This is hacky... /// <summary>Create a dummy reader for cases where we don't want to load the texture file (for tooling)</summary> /// <param name="imageCount">Pass in a huge value, it shouldn't matter...</param> public static ImageBundle CreateDummyBundle(int imageCount) { ImageBundle result = new ImageBundle(); result.manager = null; result.liveIndex = 0; // <- basically alive result.bundleIndex = -1; result.textures = new Texture2D[1]; // <- just index zero result.imageTextureIndicies = null; result.imageSourceRectangles = new Rectangle[imageCount]; // <- hopefully don't care about the contents... return(result); }
public static void Deserialize(DeserializeContext context, BinaryReader br, ref ImageBundle value) { throw new InvalidOperationException(); }
public static void Serialize(SerializeContext context, BinaryWriter bw, ImageBundle value) { throw new InvalidOperationException(); }