From 5a4f66888b3d489c2ca952383a29643e07e724ee Mon Sep 17 00:00:00 2001 From: Jim Buck Date: Wed, 10 Jan 2024 14:18:05 -0500 Subject: [PATCH 1/2] Added basic asset loading (Texture2D only for now). --- .../Ion.Examples.Breakout/Assets/Ball1.png | Bin 0 -> 692 bytes .../Ion.Examples.Breakout/Assets/Block1.png | Bin 0 -> 1024 bytes .../Ion.Examples.Breakout.csproj | 9 +++ Ion.Examples/Ion.Examples.Breakout/Program.cs | 18 ++++-- Ion/Ion.Core/Builder/IonApplicationBuilder.cs | 2 + Ion/Ion.Core/Storage/PersistentStorage.cs | 10 +++- .../Assets/AssetManager.cs | 53 +++++++++++++++-- .../Assets/AssetService.cs | 55 ------------------ .../BuilderExtensions.cs | 5 +- .../BuilderExtensions.cs | 3 +- 10 files changed, 83 insertions(+), 72 deletions(-) create mode 100644 Ion.Examples/Ion.Examples.Breakout/Assets/Ball1.png create mode 100644 Ion.Examples/Ion.Examples.Breakout/Assets/Block1.png delete mode 100644 Ion/Ion.Extensions.Graphics.Abstractions/Assets/AssetService.cs diff --git a/Ion.Examples/Ion.Examples.Breakout/Assets/Ball1.png b/Ion.Examples/Ion.Examples.Breakout/Assets/Ball1.png new file mode 100644 index 0000000000000000000000000000000000000000..b6325e749e54664a3388ed6b737a01b2d02a108b GIT binary patch literal 692 zcmV;l0!#ggP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0!c|kK~y+TT~o_y zVnGnCQ4%$xf}&s)6>*`6pn?j53pe@;87A3eJBx&6~Pw@ zktE{#(Nk5qnves{sqR}{r|zkH;XAZiEnHn)aU2eZAs7sDoJ=N}A0HnYYX*Qb?F-Ubd97;Qse}8ArX0sIBQr9x-;N|7zH@2ZP;u! z_(2u%ket4jV%YEZtW2QzJl1d6TP&7qwo;)`fKsXCC6~)DmkFsPx#1ZP1_K>z@;j|==^1poj5|4>X+Ma0C!%F4>k&CS@@*xK6K=;-M8_xI=L=giE^ z$H&LW$jIE>+`+-Y$;rvUz`(!1zs1GH&(F`@-QC;U+t=6E=H}+|^77%~;qmeD|NsB? z_V)Pr_`JNlySux+y}iT3!`|NB;Nalx?d{do)zj0{!otGF#>URh&iVQI?Ck9R{{HXp z@6^=P;^N}_`}@$)(AnA9y1KgR>gx6N_3-fU^Yio8*4DnhzS7dt%gf8PwYBBt<>ch# z(b3W0-`}{nxUa9Tw6wJA>+9p=tE;Q6t*xi0r>v~3x3{HPfs^z`(( zxw)>cuBxi4`uh5_v$OsE{kFEYdXw<900009a7bBm000id000id0mpBsWB>pHib+I4 zR5(u+Qt5h{Kmc406?PGpL%~GO

qCfFe-DG?3cX)U;{({?Af7zh}Og`DOrM0L$@{ z>5Ladhy-a4WknP*RyEzw7fX|~rmH)2udZ!d2F_Xsl8ZS{^Ctm;q9V)lki}69<3#s0 zEqF-H;M1o~wtb||jjycNEFck+n~3*(L6+Br?FtOI39v{^gcd%VmAidq!UL=eC#r2* z0gXsJ(?dMpDxYnqa4ChjrD}^h?>O@sezRX}rl#UbiX2HYkU>a#|KuaRk)FOh7jnW8 zfnllF4e2gmz zN(I<2wg$=kGFVn+K9BRu=DOPVOe+XvxDJaUC_x<4TcH1F!?vY_CMrFgCa<$&-bQYo zZr&eFCZQ}_RwgYkC1?}U07;f37i0p{QgHD6-0^i=&^3by56P uyP4Lz&xOKXK6Ve=tmks?bl?X+6#oH!h+%NMfo!Y*0000 + + + PreserveNewest + + + PreserveNewest + + + diff --git a/Ion.Examples/Ion.Examples.Breakout/Program.cs b/Ion.Examples/Ion.Examples.Breakout/Program.cs index 26a4440..59cfd68 100644 --- a/Ion.Examples/Ion.Examples.Breakout/Program.cs +++ b/Ion.Examples/Ion.Examples.Breakout/Program.cs @@ -29,6 +29,7 @@ public class BreakoutSystems private readonly IInputState _input; private readonly ISpriteBatch _spriteBatch; private readonly IEventListener _events; + private readonly IAssetManager _assets; private const int ROWS = 10; private const int COLS = 10; @@ -37,7 +38,7 @@ public class BreakoutSystems private readonly Color[] _blockColors = new Color[ROWS * COLS]; private readonly RectangleF[] _blockRects = new RectangleF[ROWS * COLS]; - private Vector2 _blockSize = new(100, 20f); + private Vector2 _blockSize = new(100, 25f); private readonly float _blockGap = 10f; private readonly float _playerGap = 150f; private readonly float _bottomGap = 20f; @@ -53,17 +54,24 @@ public class BreakoutSystems private readonly Vector2 _paddleBounceMin = Vector2.Normalize(new Vector2(-1, -0.75f)); private readonly Vector2 _paddleBounceMax = Vector2.Normalize(new Vector2(+1, -0.75f)); - public BreakoutSystems(IWindow window, IInputState input, ISpriteBatch spriteBatch, IEventListener events) + private Texture2D _blockTexture; + private Texture2D _ballTexture; + + public BreakoutSystems(IWindow window, IInputState input, ISpriteBatch spriteBatch, IEventListener events, IAssetManager assets) { _window = window; _input = input; _spriteBatch = spriteBatch; _events = events; + _assets = assets; } [Init] public void SetupBlocks(GameTime dt, GameLoopDelegate next) { + _blockTexture = _assets.Load("Block1.png"); + _ballTexture = _assets.Load("Ball1.png"); + // Setup blocks in rows and columns across the window each with different colors: for (int row = 0; row < ROWS; row++) { @@ -203,12 +211,12 @@ public void Render(GameTime dt, GameLoopDelegate next) for (var col = 0; col < COLS; col++) { var i = (row * COLS) + col; - if (_blockStates[i]) _spriteBatch.DrawRect(_blockColors[i], _blockRects[i]); + if (_blockStates[i]) _spriteBatch.Draw(_blockTexture, _blockRects[i], color: _blockColors[i], options: (SpriteEffect)(i % 3)); } } - _spriteBatch.DrawRect(Color.DarkBlue, _playerRect); - _spriteBatch.DrawRect(Color.OrangeRed, _ballRect); + _spriteBatch.Draw(_blockTexture, _playerRect, color: Color.DarkBlue); + _spriteBatch.Draw(_ballTexture, _ballRect, color: Color.DarkRed); next(dt); } diff --git a/Ion/Ion.Core/Builder/IonApplicationBuilder.cs b/Ion/Ion.Core/Builder/IonApplicationBuilder.cs index 6bdd33a..37a09d9 100644 --- a/Ion/Ion.Core/Builder/IonApplicationBuilder.cs +++ b/Ion/Ion.Core/Builder/IonApplicationBuilder.cs @@ -36,6 +36,8 @@ internal IonApplicationBuilder(string[] args) Services.AddSingleton(); Services.AddTransient(); Services.AddSingleton(); + + Services.AddSingleton(); } public IonApplication Build() diff --git a/Ion/Ion.Core/Storage/PersistentStorage.cs b/Ion/Ion.Core/Storage/PersistentStorage.cs index dfd8aec..0fefcda 100644 --- a/Ion/Ion.Core/Storage/PersistentStorage.cs +++ b/Ion/Ion.Core/Storage/PersistentStorage.cs @@ -17,10 +17,16 @@ internal class PersistentStorage : IPersistentStorage public PersistentStorage(IOptions config) { - _game = new PersistentStorageProvider(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), config.Value.Title); - _assets = _game.Subpath("Assets"); +#if DEBUG + _game = new PersistentStorageProvider(Environment.CurrentDirectory); + _user = new PersistentStorageProvider(Environment.CurrentDirectory); +#else + _game = new PersistentStorageProvider(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), config.Value.Title); _user = new PersistentStorageProvider(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), config.Value.Title); +#endif + + _assets = _game.Subpath("Assets"); _saves = _user.Subpath("Saves"); } diff --git a/Ion/Ion.Extensions.Graphics.Abstractions/Assets/AssetManager.cs b/Ion/Ion.Extensions.Graphics.Abstractions/Assets/AssetManager.cs index 94424e2..95b5bd0 100644 --- a/Ion/Ion.Extensions.Graphics.Abstractions/Assets/AssetManager.cs +++ b/Ion/Ion.Extensions.Graphics.Abstractions/Assets/AssetManager.cs @@ -6,18 +6,21 @@ namespace Ion.Extensions.Graphics; public interface IAssetManager { T Load(params string[] path) where T : class, IAsset; + T LoadGlobal(params string[] path) where T : class, IAsset; T? Get(int id) where T : class, IAsset; void Unload(T asset) where T : class, IAsset; + void UnloadGlobal(T asset) where T : class, IAsset; } -public class AssetManager : IAssetManager +public class GlobalAssetManager : IAssetManager { private readonly ILogger _logger; private readonly IPersistentStorage _storage; private readonly ImmutableDictionary _loaders; private readonly Dictionary _assetCache = new(); + private readonly Dictionary _pathCache = new(); - public AssetManager(ILogger logger, IPersistentStorage storage, IEnumerable loaders) + public GlobalAssetManager(ILogger logger, IPersistentStorage storage, IEnumerable loaders) { _logger = logger; _storage = storage; @@ -26,19 +29,28 @@ public AssetManager(ILogger logger, IPersistentStorage storage, IE public T Load(params string[] path) where T : class, IAsset { + var name = Path.Combine(path); + + if (_pathCache.TryGetValue(name, out var cachedAsset)) return (T)cachedAsset; + if (!_loaders.TryGetValue(typeof(T), out IAssetLoader? loader)) throw new InvalidOperationException("No loader registered for type " + typeof(T).Name); - var name = Path.Combine(path); - using var stream = _storage.Assets.Read(path); + using var stream = _storage.Assets.Read(name); var asset = loader.Load(stream, name); _assetCache.Add(asset.Id, asset); + _pathCache.Add(name, asset); return asset; } - public T? Get(int id) where T : class, IAsset + public virtual T LoadGlobal(params string[] path) where T : class, IAsset + { + return Load(path); + } + + public virtual T? Get(int id) where T : class, IAsset { return _assetCache.TryGetValue(id, out var asset) ? (T)asset : default; } @@ -46,6 +58,37 @@ public T Load(params string[] path) where T : class, IAsset public void Unload(T asset) where T : class, IAsset { _assetCache.Remove(asset.Id); + _pathCache.Remove(asset.Name); asset.Dispose(); } + + public virtual void UnloadGlobal(T asset) where T : class, IAsset + { + Unload(asset); + } +} + +public class ScopedAssetManager : GlobalAssetManager +{ + private readonly GlobalAssetManager _globalAssetManager; + + public ScopedAssetManager(ILogger logger, IPersistentStorage storage, IEnumerable loaders, GlobalAssetManager globalAssetManager) : base(logger, storage, loaders) + { + _globalAssetManager = globalAssetManager; + } + + public override T LoadGlobal(params string[] path) + { + return _globalAssetManager.Load(path); + } + + public override void UnloadGlobal(T asset) + { + _globalAssetManager.Unload(asset); + } + + public override T? Get(int id) where T : class + { + return base.Get(id) ?? _globalAssetManager.Get(id); + } } \ No newline at end of file diff --git a/Ion/Ion.Extensions.Graphics.Abstractions/Assets/AssetService.cs b/Ion/Ion.Extensions.Graphics.Abstractions/Assets/AssetService.cs deleted file mode 100644 index 29cba7d..0000000 --- a/Ion/Ion.Extensions.Graphics.Abstractions/Assets/AssetService.cs +++ /dev/null @@ -1,55 +0,0 @@ -namespace Ion.Extensions.Graphics; - -public interface IAssetService -{ - IAssetBatch Load(Action batchBuilder); - IAssetBatch LoadGlobal(Action batchBuilder); - - T? Get(string virtualPath) where T : IAsset; -} - -internal class ScopedAssetService : GlobalAssetService -{ - private readonly GlobalAssetService _globalAssetService; - - public ScopedAssetService(GlobalAssetService globalAssetService) - { - _globalAssetService = globalAssetService; - } - - public override IAssetBatch LoadGlobal(Action batchBuilder) - { - return _globalAssetService.Load(batchBuilder); - } -} - -internal class GlobalAssetService : IAssetService, IDisposable -{ - protected readonly Dictionary _assets = new(); - - public IAssetBatch Load(Action batchBuilder) - { - var builder = new AssetBatchBuilder(); - batchBuilder(builder); - return builder.Load(_assets); - } - - public virtual IAssetBatch LoadGlobal(Action batchBuilder) - { - return Load(batchBuilder); - } - - public T? Get(string virtualPath) where T : IAsset - { - if (_assets.TryGetValue(virtualPath, out var asset)) return (T)asset; - - return default; - } - - public void Dispose() - { - foreach (var asset in _assets.Values) asset.Dispose(); - - _assets.Clear(); - } -} \ No newline at end of file diff --git a/Ion/Ion.Extensions.Graphics.Null/BuilderExtensions.cs b/Ion/Ion.Extensions.Graphics.Null/BuilderExtensions.cs index e4bcc31..7f6104f 100644 --- a/Ion/Ion.Extensions.Graphics.Null/BuilderExtensions.cs +++ b/Ion/Ion.Extensions.Graphics.Null/BuilderExtensions.cs @@ -15,14 +15,11 @@ public static IServiceCollection AddNullGraphics(this IServiceCollection service services // Standard .Configure(config) - .AddScoped() + .AddScoped() // Implementation-specific .AddSingleton() - // Loaders - //.AddSingleton() - // Implementation-specific Systems .AddSingleton(); diff --git a/Ion/Ion.Extensions.Graphics.Veldrid/BuilderExtensions.cs b/Ion/Ion.Extensions.Graphics.Veldrid/BuilderExtensions.cs index 430664e..3813a26 100644 --- a/Ion/Ion.Extensions.Graphics.Veldrid/BuilderExtensions.cs +++ b/Ion/Ion.Extensions.Graphics.Veldrid/BuilderExtensions.cs @@ -15,7 +15,6 @@ public static IServiceCollection AddVeldridGraphics(this IServiceCollection serv services // Standard .Configure(config) - .AddScoped() // Implementation-specific .AddSingleton() @@ -24,6 +23,8 @@ public static IServiceCollection AddVeldridGraphics(this IServiceCollection serv // Loaders .AddSingleton() + .AddSingleton() + .AddScoped() // Implementation-specific Systems .AddSingleton() From b6fbc637021d5a394c0c21d82b953c5813ea0728 Mon Sep 17 00:00:00 2001 From: Jim Buck Date: Wed, 10 Jan 2024 14:43:20 -0500 Subject: [PATCH 2/2] Fixed null graphics setup. --- Ion/Ion.Extensions.Graphics.Null/BuilderExtensions.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Ion/Ion.Extensions.Graphics.Null/BuilderExtensions.cs b/Ion/Ion.Extensions.Graphics.Null/BuilderExtensions.cs index 7f6104f..3dcb00b 100644 --- a/Ion/Ion.Extensions.Graphics.Null/BuilderExtensions.cs +++ b/Ion/Ion.Extensions.Graphics.Null/BuilderExtensions.cs @@ -15,7 +15,8 @@ public static IServiceCollection AddNullGraphics(this IServiceCollection service services // Standard .Configure(config) - .AddScoped() + .AddSingleton() + .AddScoped() // Implementation-specific .AddSingleton()