From 0b3124750d291c5566b53b9984f4d28fb32212c3 Mon Sep 17 00:00:00 2001 From: Tim Sarbin Date: Sun, 9 Dec 2018 14:55:01 -0500 Subject: [PATCH] Lots of optimizations. --- .../Interfaces/Drawing/IRenderWindow.cs | 4 +- OpenDiablo2.Common/Interfaces/ICache.cs | 3 + OpenDiablo2.Common/Models/BitStream.cs | 2 + OpenDiablo2.Common/Models/ImageSet.cs | 13 +-- OpenDiablo2.Core/Cache.cs | 7 ++ OpenDiablo2.Core/GameEngine.cs | 8 +- OpenDiablo2.Core/UI/Button.cs | 2 +- OpenDiablo2.Core/UI/CharacterPanel.cs | 2 +- OpenDiablo2.Core/UI/GameHUD.cs | 6 +- OpenDiablo2.Core/UI/InventoryPanel.cs | 2 +- OpenDiablo2.Core/UI/ItemContainer.cs | 4 +- OpenDiablo2.Core/UI/MiniPanel.cs | 2 +- OpenDiablo2.Core/UI/PanelFrame.cs | 2 +- OpenDiablo2.Core/UI/TextBox.cs | 2 +- OpenDiablo2.SDL2/SDL2Font.cs | 2 +- OpenDiablo2.SDL2/SDL2Label.cs | 4 +- OpenDiablo2.SDL2/SDL2MusicProvider.cs | 3 + OpenDiablo2.SDL2/SDL2RenderWindow.cs | 14 +-- OpenDiablo2.SDL2/SDL2Sprite.cs | 110 +++++++++++++----- OpenDiablo2.Scenes/AutofacModule.cs | 2 +- OpenDiablo2.Scenes/SelectHeroClass.cs | 14 ++- 21 files changed, 137 insertions(+), 71 deletions(-) diff --git a/OpenDiablo2.Common/Interfaces/Drawing/IRenderWindow.cs b/OpenDiablo2.Common/Interfaces/Drawing/IRenderWindow.cs index 5fdb0fe5..5d3fe613 100644 --- a/OpenDiablo2.Common/Interfaces/Drawing/IRenderWindow.cs +++ b/OpenDiablo2.Common/Interfaces/Drawing/IRenderWindow.cs @@ -15,8 +15,8 @@ namespace OpenDiablo2.Common.Interfaces void Sync(); void Quit(); uint GetTicks(); - ISprite LoadSprite(string resourcePath, string palette, Point location); - ISprite LoadSprite(string resourcePath, string palette); + ISprite LoadSprite(string resourcePath, string palette, Point location, bool cacheFrames = false); + ISprite LoadSprite(string resourcePath, string palette, bool cacheFrames = false); IFont LoadFont(string resourcePath, string palette); ILabel CreateLabel(IFont font); ILabel CreateLabel(IFont font, string text); diff --git a/OpenDiablo2.Common/Interfaces/ICache.cs b/OpenDiablo2.Common/Interfaces/ICache.cs index 3c0e6f1a..e04c3a43 100644 --- a/OpenDiablo2.Common/Interfaces/ICache.cs +++ b/OpenDiablo2.Common/Interfaces/ICache.cs @@ -35,5 +35,8 @@ namespace OpenDiablo2.Common.Interfaces /// Pass in a new policy to control how this item is handled. Typically you can leave this null. /// The item requested T AddOrGetExisting(string key, Func valueFactory, CacheItemPolicy cacheItemPolicy = null); + bool Exists(string key); + T GetExisting(string key) where T : class, new(); + void Add(string key, T value, CacheItemPolicy cacheItemPolicy = null); } } diff --git a/OpenDiablo2.Common/Models/BitStream.cs b/OpenDiablo2.Common/Models/BitStream.cs index a17217e1..6a06d737 100644 --- a/OpenDiablo2.Common/Models/BitStream.cs +++ b/OpenDiablo2.Common/Models/BitStream.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Runtime.CompilerServices; namespace OpenDiablo2.Common.Models { @@ -33,6 +34,7 @@ namespace OpenDiablo2.Common.Models return _current & 0xff; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool EnsureBits(int bitCount) { if (bitCount <= _bitCount) return true; diff --git a/OpenDiablo2.Common/Models/ImageSet.cs b/OpenDiablo2.Common/Models/ImageSet.cs index ae0bd506..c1be91c4 100644 --- a/OpenDiablo2.Common/Models/ImageSet.cs +++ b/OpenDiablo2.Common/Models/ImageSet.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Linq; +using System.Runtime.CompilerServices; namespace OpenDiablo2.Common.Models { @@ -22,17 +23,11 @@ namespace OpenDiablo2.Common.Models ImageData = null; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public UInt32 GetColor(int x, int y, Palette palette) { - var i = x + (y * Width); - if (i >= ImageData.Length) - return 0; - - var index = ImageData[i]; - if (index == -1) - return 0; - - return palette.Colors[index]; + var index = ImageData[x + (y * Width)]; + return index == -1 ? 0 : palette.Colors[index]; } } diff --git a/OpenDiablo2.Core/Cache.cs b/OpenDiablo2.Core/Cache.cs index c99a78e7..f9e8ddd2 100644 --- a/OpenDiablo2.Core/Cache.cs +++ b/OpenDiablo2.Core/Cache.cs @@ -40,5 +40,12 @@ namespace OpenDiablo2.Core throw; } } + + public bool Exists(string key) => _cache.Contains(key); + + public T GetExisting(string key) where T : class, new() => (_cache.Get(key) as Lazy)?.Value; + + public void Add(string key, T value, CacheItemPolicy cacheItemPolicy = null) => _cache.Add(key, value, cacheItemPolicy ?? new CacheItemPolicy()); + } } diff --git a/OpenDiablo2.Core/GameEngine.cs b/OpenDiablo2.Core/GameEngine.cs index 45c9aa83..adc1b2f1 100644 --- a/OpenDiablo2.Core/GameEngine.cs +++ b/OpenDiablo2.Core/GameEngine.cs @@ -22,9 +22,7 @@ namespace OpenDiablo2.Core private IScene currentScene; private IScene nextScene = null; - - private readonly MPQ[] MPQs; - + private readonly Dictionary soundTable = new Dictionary(); public Dictionary PaletteTable { get; private set; } = new Dictionary(); @@ -92,7 +90,9 @@ namespace OpenDiablo2.Core if (ms < 33) { Thread.Sleep(33 - (int)ms); - continue; + } else + { + log.Info($"Full frame time used - {ms} milliseconds to frame"); } // Prevent falco-punch updates diff --git a/OpenDiablo2.Core/UI/Button.cs b/OpenDiablo2.Core/UI/Button.cs index ad8d6396..a61a42a2 100644 --- a/OpenDiablo2.Core/UI/Button.cs +++ b/OpenDiablo2.Core/UI/Button.cs @@ -82,7 +82,7 @@ namespace OpenDiablo2.Core.UI font = renderWindow.LoadFont(ResourcePaths.FontExocet10, Palettes.Units); label = renderWindow.CreateLabel(font); - sprite = renderWindow.LoadSprite(buttonLayout.ResourceName, buttonLayout.PaletteName); + sprite = renderWindow.LoadSprite(buttonLayout.ResourceName, buttonLayout.PaletteName, true); // TODO: Less stupid way of doing this would be nice buttonWidth = 0; diff --git a/OpenDiablo2.Core/UI/CharacterPanel.cs b/OpenDiablo2.Core/UI/CharacterPanel.cs index 8d726cc5..2fdbb50b 100644 --- a/OpenDiablo2.Core/UI/CharacterPanel.cs +++ b/OpenDiablo2.Core/UI/CharacterPanel.cs @@ -38,7 +38,7 @@ namespace OpenDiablo2.Core.UI { this.renderWindow = renderWindow; - sprite = renderWindow.LoadSprite(ResourcePaths.InventoryCharacterPanel, Palettes.Act1, FrameType.GetOffset()); + sprite = renderWindow.LoadSprite(ResourcePaths.InventoryCharacterPanel, Palettes.Act1, FrameType.GetOffset(), true); closeButton = createButton(eButtonType.Close); closeButton.Location = sprite.Location + new Size(128, 388); diff --git a/OpenDiablo2.Core/UI/GameHUD.cs b/OpenDiablo2.Core/UI/GameHUD.cs index abdad65f..1472c18d 100644 --- a/OpenDiablo2.Core/UI/GameHUD.cs +++ b/OpenDiablo2.Core/UI/GameHUD.cs @@ -62,9 +62,9 @@ namespace OpenDiablo2.Core.UI menuButton.OnToggle = minipanel.OnMenuToggle; menuButton.Toggle(); - panelSprite = renderWindow.LoadSprite(ResourcePaths.GamePanels, Palettes.Act1); - healthManaSprite = renderWindow.LoadSprite(ResourcePaths.HealthMana, Palettes.Act1); - gameGlobeOverlapSprite = renderWindow.LoadSprite(ResourcePaths.GameGlobeOverlap, Palettes.Act1); + panelSprite = renderWindow.LoadSprite(ResourcePaths.GamePanels, Palettes.Act1, true); + healthManaSprite = renderWindow.LoadSprite(ResourcePaths.HealthMana, Palettes.Act1, true); + gameGlobeOverlapSprite = renderWindow.LoadSprite(ResourcePaths.GameGlobeOverlap, Palettes.Act1, true); } public IPanel LeftPanel { get; private set; } diff --git a/OpenDiablo2.Core/UI/InventoryPanel.cs b/OpenDiablo2.Core/UI/InventoryPanel.cs index f59743b6..46f258ec 100644 --- a/OpenDiablo2.Core/UI/InventoryPanel.cs +++ b/OpenDiablo2.Core/UI/InventoryPanel.cs @@ -51,7 +51,7 @@ namespace OpenDiablo2.Core.UI { this.renderWindow = renderWindow; - sprite = renderWindow.LoadSprite(ResourcePaths.InventoryCharacterPanel, Palettes.Units, FrameType.GetOffset()); + sprite = renderWindow.LoadSprite(ResourcePaths.InventoryCharacterPanel, Palettes.Units, FrameType.GetOffset(), true); closeButton = createButton(eButtonType.Close); closeButton.Location = sprite.Location + new Size(18, 384); diff --git a/OpenDiablo2.Core/UI/ItemContainer.cs b/OpenDiablo2.Core/UI/ItemContainer.cs index e1866ca6..874e0819 100644 --- a/OpenDiablo2.Core/UI/ItemContainer.cs +++ b/OpenDiablo2.Core/UI/ItemContainer.cs @@ -47,7 +47,7 @@ namespace OpenDiablo2.Core.UI this.itemContainerLayout = itemContainerLayout; this.mouseInfoProvider = mouseInfoProvider; - placeholderSprite = renderWindow.LoadSprite(itemContainerLayout.ResourceName, itemContainerLayout.PaletteName); + placeholderSprite = renderWindow.LoadSprite(itemContainerLayout.ResourceName, itemContainerLayout.PaletteName, true); placeholderSprite.Location = new Point(location.X, location.Y + placeholderSprite.LocalFrameSize.Height); this.Size = placeholderSprite.FrameSize; // For all but generic size is equal to the placeholder size. Source: me. } @@ -58,7 +58,7 @@ namespace OpenDiablo2.Core.UI if (ContainedItem != null) { - sprite = renderWindow.LoadSprite(ResourcePaths.GeneratePathForItem(this.ContainedItem.InvFile), Palettes.Units); + sprite = renderWindow.LoadSprite(ResourcePaths.GeneratePathForItem(this.ContainedItem.InvFile), Palettes.Units, true); sprite.Location = new Point(location.X, location.Y + sprite.LocalFrameSize.Height); } } diff --git a/OpenDiablo2.Core/UI/MiniPanel.cs b/OpenDiablo2.Core/UI/MiniPanel.cs index 6c58cfaf..59a29d7c 100644 --- a/OpenDiablo2.Core/UI/MiniPanel.cs +++ b/OpenDiablo2.Core/UI/MiniPanel.cs @@ -35,7 +35,7 @@ namespace OpenDiablo2.Core.UI this.gameState = gameState; this.panels = panels; - sprite = renderWindow.LoadSprite(ResourcePaths.MinipanelSmall, Palettes.Units); + sprite = renderWindow.LoadSprite(ResourcePaths.MinipanelSmall, Palettes.Units, true); buttons = panelButtons.Select((x, i) => { diff --git a/OpenDiablo2.Core/UI/PanelFrame.cs b/OpenDiablo2.Core/UI/PanelFrame.cs index 62efa386..abe0ffda 100644 --- a/OpenDiablo2.Core/UI/PanelFrame.cs +++ b/OpenDiablo2.Core/UI/PanelFrame.cs @@ -19,7 +19,7 @@ namespace OpenDiablo2.Core.UI this.renderWindow = renderWindow; this.panelFrameType = panelFrameType; - sprite = renderWindow.LoadSprite(ResourcePaths.Frame, Palettes.Units, new Point(0, 0)); + sprite = renderWindow.LoadSprite(ResourcePaths.Frame, Palettes.Units, new Point(0, 0), true); Location = new Point(0, 0); diff --git a/OpenDiablo2.Core/UI/TextBox.cs b/OpenDiablo2.Core/UI/TextBox.cs index 4329c508..3d4a226e 100644 --- a/OpenDiablo2.Core/UI/TextBox.cs +++ b/OpenDiablo2.Core/UI/TextBox.cs @@ -75,7 +75,7 @@ namespace OpenDiablo2.Core.UI { this.renderWindow = renderWindow; - sprite = renderWindow.LoadSprite(ResourcePaths.TextBox2, Palettes.Units); + sprite = renderWindow.LoadSprite(ResourcePaths.TextBox2, Palettes.Units, true); font = renderWindow.LoadFont(ResourcePaths.FontFormal11, Palettes.Units); label = renderWindow.CreateLabel(font); linebar = renderWindow.CreateLabel(font); diff --git a/OpenDiablo2.SDL2/SDL2Font.cs b/OpenDiablo2.SDL2/SDL2Font.cs index 8c0db7fe..ba7f4cff 100644 --- a/OpenDiablo2.SDL2/SDL2Font.cs +++ b/OpenDiablo2.SDL2/SDL2Font.cs @@ -36,7 +36,7 @@ namespace OpenDiablo2.SDL2_ { this.font = font; - sprite = new SDL2Sprite(font.FontImageSet, renderer); + sprite = new SDL2Sprite(font.FontImageSet, renderer, true); } public void Dispose() diff --git a/OpenDiablo2.SDL2/SDL2Label.cs b/OpenDiablo2.SDL2/SDL2Label.cs index 77d825cb..af5f8fd3 100644 --- a/OpenDiablo2.SDL2/SDL2Label.cs +++ b/OpenDiablo2.SDL2/SDL2Label.cs @@ -210,8 +210,8 @@ namespace OpenDiablo2.SDL2_ }; font.sprite.Frame = character; - SDL.SDL_SetTextureColorMod(font.sprite.texture, TextColor.R, TextColor.G, TextColor.B); - SDL.SDL_RenderCopy(renderer, font.sprite.texture, IntPtr.Zero, ref rect); + SDL.SDL_SetTextureColorMod(font.sprite.Texture, TextColor.R, TextColor.G, TextColor.B); + SDL.SDL_RenderCopy(renderer, font.sprite.Texture, IntPtr.Zero, ref rect); } diff --git a/OpenDiablo2.SDL2/SDL2MusicProvider.cs b/OpenDiablo2.SDL2/SDL2MusicProvider.cs index 5605a444..360271ac 100644 --- a/OpenDiablo2.SDL2/SDL2MusicProvider.cs +++ b/OpenDiablo2.SDL2/SDL2MusicProvider.cs @@ -75,6 +75,9 @@ namespace OpenDiablo2.SDL2_ public int PlaySfx(byte[] data) { + if (data == null || data.Length == 0) + return -1; + var sound = SDL_mixer.Mix_QuickLoad_WAV(data); return SDL_mixer.Mix_PlayChannel(-1, sound, 0); } diff --git a/OpenDiablo2.SDL2/SDL2RenderWindow.cs b/OpenDiablo2.SDL2/SDL2RenderWindow.cs index dcc69be4..68219e62 100644 --- a/OpenDiablo2.SDL2/SDL2RenderWindow.cs +++ b/OpenDiablo2.SDL2/SDL2RenderWindow.cs @@ -242,7 +242,7 @@ namespace OpenDiablo2.SDL2_ public void Draw(ISprite sprite) { var spr = sprite as SDL2Sprite; - if (spr.texture == IntPtr.Zero) + if (spr.Texture == IntPtr.Zero) return; var loc = spr.GetRenderPoint(); @@ -254,7 +254,7 @@ namespace OpenDiablo2.SDL2_ w = spr.FrameSize.Width, h = spr.FrameSize.Height }; - SDL.SDL_RenderCopy(renderer, spr.texture, IntPtr.Zero, ref destRect); + SDL.SDL_RenderCopy(renderer, spr.Texture, IntPtr.Zero, ref destRect); } @@ -276,15 +276,15 @@ namespace OpenDiablo2.SDL2_ w = spr.FrameSize.Width, h = spr.FrameSize.Height }; - SDL.SDL_RenderCopy(renderer, spr.texture, IntPtr.Zero, ref destRect); + SDL.SDL_RenderCopy(renderer, spr.Texture, IntPtr.Zero, ref destRect); } } } - public ISprite LoadSprite(string resourcePath, string palette) => LoadSprite(resourcePath, palette, Point.Empty); - public ISprite LoadSprite(string resourcePath, string palette, Point location) + public ISprite LoadSprite(string resourcePath, string palette, bool cacheFrames = false) => LoadSprite(resourcePath, palette, Point.Empty, cacheFrames); + public ISprite LoadSprite(string resourcePath, string palette, Point location, bool cacheFrames = false) { - var result = new SDL2Sprite(resourceManager.GetImageSet(resourcePath), renderer) + var result = new SDL2Sprite(resourceManager.GetImageSet(resourcePath), renderer, cacheFrames) { CurrentPalette = paletteProvider.PaletteTable[palette], Location = location @@ -437,7 +437,7 @@ namespace OpenDiablo2.SDL2_ SDL.SDL_SetTextureBlendMode(texId, SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND); SDL.SDL_SetRenderTarget(renderer, texId); - SDL.SDL_RenderCopy(renderer, (sprite as SDL2Sprite).texture, IntPtr.Zero, IntPtr.Zero); + SDL.SDL_RenderCopy(renderer, (sprite as SDL2Sprite).Texture, IntPtr.Zero, IntPtr.Zero); SDL.SDL_SetRenderTarget(renderer, IntPtr.Zero); return new SDL2MouseCursor diff --git a/OpenDiablo2.SDL2/SDL2Sprite.cs b/OpenDiablo2.SDL2/SDL2Sprite.cs index fcf587b7..2a288cff 100644 --- a/OpenDiablo2.SDL2/SDL2Sprite.cs +++ b/OpenDiablo2.SDL2/SDL2Sprite.cs @@ -28,7 +28,23 @@ namespace OpenDiablo2.SDL2_ { internal readonly ImageSet source; private readonly IntPtr renderer; - internal IntPtr texture = IntPtr.Zero; + private readonly bool cacheFrames; + + private bool disposed = false; + + private IntPtr[] texture; + private bool[] frameLoaded; + + public IntPtr Texture + { + get + { + if (!frameLoaded[TextureIndex]) + LoadFrame(); + + return texture[TextureIndex]; + } + } public Point Location { get; set; } public Size FrameSize { get; set; } @@ -43,21 +59,25 @@ namespace OpenDiablo2.SDL2_ if (darken == value) return; darken = value; - LoadFrame(frame); + ClearAllFrames(); } } - private int frame = -1; + private int frame; public int Frame { get => frame; set { - if (frame == value && texture != IntPtr.Zero) + if (frame == value) return; frame = Math.Max(0, Math.Min(value, TotalFrames)); - LoadFrame(frame); + + if (cacheFrames) + return; + + frameLoaded[TextureIndex] = false; } } public int TotalFrames { get; internal set; } @@ -69,7 +89,16 @@ namespace OpenDiablo2.SDL2_ set { blend = value; - SDL.SDL_SetTextureBlendMode(texture, blend ? SDL.SDL_BlendMode.SDL_BLENDMODE_ADD : SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND); + if (cacheFrames) + { + for (var i = 0; i < TotalFrames; i++) + if (texture[i] != IntPtr.Zero) + SDL.SDL_SetTextureBlendMode(texture[i], blend ? SDL.SDL_BlendMode.SDL_BLENDMODE_ADD : SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND); + } + else + if (texture[TextureIndex] != IntPtr.Zero) + SDL.SDL_SetTextureBlendMode(texture[TextureIndex], blend ? SDL.SDL_BlendMode.SDL_BLENDMODE_ADD : SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND); + } } @@ -80,23 +109,31 @@ namespace OpenDiablo2.SDL2_ set { palette = value; - UpdateTextureData(); + ClearAllFrames(); } } + private int TextureIndex => cacheFrames ? frame : 0; - public SDL2Sprite(ImageSet source, IntPtr renderer) + public SDL2Sprite(ImageSet source, IntPtr renderer, bool cacheFrames = false) { this.source = source; this.renderer = renderer; + this.cacheFrames = cacheFrames; - + texture = new IntPtr[cacheFrames ? source.Frames.Count() : 1]; + frameLoaded = new bool[cacheFrames ? source.Frames.Count() : 1]; TotalFrames = source.Frames.Count(); + + ClearAllFrames(); + Location = Point.Empty; FrameSize = new Size(Pow2((int)source.Frames.Max(x => x.Width)), Pow2((int)source.Frames.Max(x => x.Height))); + + Frame = 0; } - + internal Point GetRenderPoint() { return source == null @@ -108,31 +145,30 @@ namespace OpenDiablo2.SDL2_ private void UpdateTextureData() { - if (texture == IntPtr.Zero) - { - texture = SDL.SDL_CreateTexture(renderer, SDL.SDL_PIXELFORMAT_ARGB8888, (int)SDL.SDL_TextureAccess.SDL_TEXTUREACCESS_STREAMING, Pow2(FrameSize.Width), Pow2(FrameSize.Height)); - - if (texture == IntPtr.Zero) - throw new OpenDiablo2Exception("Unaple to initialize texture."); - - Frame = 0; - } + Frame = 0; } - private unsafe void LoadFrame(int index) + private unsafe void LoadFrame() { - var sourceFrame = source.Frames[index]; - //var fullRect = new SDL.SDL_Rect { x = 0, y = 0, w = FrameSize.Width, h = FrameSize.Height }; - SDL.SDL_SetTextureBlendMode(texture, blend ? SDL.SDL_BlendMode.SDL_BLENDMODE_ADD : SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND); + if (texture[TextureIndex] == IntPtr.Zero) + { + texture[TextureIndex] = SDL.SDL_CreateTexture(renderer, SDL.SDL_PIXELFORMAT_ARGB8888, (int)SDL.SDL_TextureAccess.SDL_TEXTUREACCESS_STREAMING, Pow2(FrameSize.Width), Pow2(FrameSize.Height)); - SDL.SDL_LockTexture(texture, IntPtr.Zero, out IntPtr pixels, out int pitch); + if (texture[TextureIndex] == IntPtr.Zero) + throw new OpenDiablo2Exception("Unaple to initialize texture."); + SDL.SDL_SetTextureBlendMode(texture[TextureIndex], blend ? SDL.SDL_BlendMode.SDL_BLENDMODE_ADD : SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND); + } + + var sourceFrame = source.Frames[frame]; + + SDL.SDL_LockTexture(texture[TextureIndex], IntPtr.Zero, out IntPtr pixels, out int pitch); try { UInt32* data = (UInt32*)pixels; var frameOffset = FrameSize.Height - sourceFrame.Height; var frameWidth = FrameSize.Width; var frameHeight = FrameSize.Height; - for (var y = 0; y < frameHeight; y++) + for (int y = 0; y < frameHeight; y++) { for (int x = 0; x < frameWidth; x++) { @@ -151,10 +187,10 @@ namespace OpenDiablo2.SDL2_ } finally { - SDL.SDL_UnlockTexture(texture); + SDL.SDL_UnlockTexture(texture[TextureIndex]); } - + frameLoaded[TextureIndex] = true; } private int Pow2(int val) @@ -165,9 +201,27 @@ namespace OpenDiablo2.SDL2_ return result; } + private void ClearAllFrames() + { + var framestoClear = cacheFrames ? TotalFrames : 1; + for (int i = 0; i < framestoClear; i++) + frameLoaded[i] = false; + } + public void Dispose() { - SDL.SDL_DestroyTexture(texture); + if (disposed) + return; + + var framestoClear = cacheFrames ? TotalFrames : 1; + for (var i = 0; i < framestoClear; i++) + { + SDL.SDL_DestroyTexture(texture[i]); + texture[i] = IntPtr.Zero; + } + + texture = Array.Empty(); + disposed = true; } } diff --git a/OpenDiablo2.Scenes/AutofacModule.cs b/OpenDiablo2.Scenes/AutofacModule.cs index 779c649b..606e253b 100644 --- a/OpenDiablo2.Scenes/AutofacModule.cs +++ b/OpenDiablo2.Scenes/AutofacModule.cs @@ -20,7 +20,7 @@ namespace OpenDiablo2.Scenes builder .RegisterType(type) .Keyed(att.SceneType) - .SingleInstance(); + .InstancePerDependency(); } } } diff --git a/OpenDiablo2.Scenes/SelectHeroClass.cs b/OpenDiablo2.Scenes/SelectHeroClass.cs index 33a6319b..5fa3d1c8 100644 --- a/OpenDiablo2.Scenes/SelectHeroClass.cs +++ b/OpenDiablo2.Scenes/SelectHeroClass.cs @@ -228,18 +228,19 @@ namespace OpenDiablo2.Scenes Parallel.ForEach(new[] { ResourcePaths.SFXAmazonSelect, - ResourcePaths.SFXAmazonDeselect, ResourcePaths.SFXAssassinSelect, - ResourcePaths.SFXAssassinDeselect, ResourcePaths.SFXBarbarianSelect, - ResourcePaths.SFXBarbarianDeselect, ResourcePaths.SFXDruidSelect, - ResourcePaths.SFXDruidDeselect, ResourcePaths.SFXNecromancerSelect, - ResourcePaths.SFXNecromancerDeselect, ResourcePaths.SFXPaladinSelect, - ResourcePaths.SFXPaladinDeselect, ResourcePaths.SFXSorceressSelect, + + ResourcePaths.SFXAmazonDeselect, + ResourcePaths.SFXAssassinDeselect, + ResourcePaths.SFXBarbarianDeselect, + ResourcePaths.SFXDruidDeselect, + ResourcePaths.SFXNecromancerDeselect, + ResourcePaths.SFXPaladinDeselect, ResourcePaths.SFXSorceressDeselect }, (path => sfxDictionary.Add(path, mpqProvider.GetBytes(path)))); } @@ -609,6 +610,7 @@ namespace OpenDiablo2.Scenes campfireSprite.Dispose(); headingFont.Dispose(); headingLabel.Dispose(); + sfxDictionary.Clear(); } } }