DI: Only initialize one renderer at once

rendering
Liza 2023-02-17 19:12:44 +01:00
parent 8986b368c7
commit 5419f51942
8 changed files with 94 additions and 32 deletions

View File

@ -48,6 +48,7 @@ namespace Pal.Client
private readonly string _sqliteConnectionString; private readonly string _sqliteConnectionString;
private readonly CancellationTokenSource _initCts = new(); private readonly CancellationTokenSource _initCts = new();
private ServiceProvider? _serviceProvider; private ServiceProvider? _serviceProvider;
private Plugin? _plugin;
public string Name => Localization.Palace_Pal; public string Name => Localization.Palace_Pal;
@ -122,8 +123,8 @@ namespace Pal.Client
services.AddSingleton<StatisticsWindow>(); services.AddSingleton<StatisticsWindow>();
// these should maybe be scoped // these should maybe be scoped
services.AddSingleton<SimpleRenderer>(); services.AddScoped<SimpleRenderer>();
services.AddSingleton<SplatoonRenderer>(); services.AddScoped<SplatoonRenderer>();
services.AddSingleton<RenderAdapter>(); services.AddSingleton<RenderAdapter>();
// queue handling // queue handling
@ -199,7 +200,7 @@ namespace Pal.Client
_serviceProvider.GetRequiredService<ChatService>(); _serviceProvider.GetRequiredService<ChatService>();
token.ThrowIfCancellationRequested(); token.ThrowIfCancellationRequested();
_serviceProvider.GetRequiredService<Plugin>(); _plugin = new Plugin(pluginInterface, _serviceProvider);
_logger.LogInformation("Async init complete"); _logger.LogInformation("Async init complete");
} }
@ -226,15 +227,23 @@ namespace Pal.Client
// ensure we're not calling dispose recursively on ourselves // ensure we're not calling dispose recursively on ourselves
if (_serviceProvider != null) if (_serviceProvider != null)
{ {
_logger.LogInformation("Disposing DI Context");
ServiceProvider serviceProvider = _serviceProvider; ServiceProvider serviceProvider = _serviceProvider;
_serviceProvider = null; _serviceProvider = null;
_plugin?.Dispose();
_plugin = null;
serviceProvider.Dispose(); serviceProvider.Dispose();
// ensure we're not keeping the file open longer than the plugin is loaded // ensure we're not keeping the file open longer than the plugin is loaded
using (SqliteConnection sqliteConnection = new(_sqliteConnectionString)) using (SqliteConnection sqliteConnection = new(_sqliteConnectionString))
SqliteConnection.ClearPool(sqliteConnection); SqliteConnection.ClearPool(sqliteConnection);
} }
else
{
_logger.LogDebug("DI context is already disposed");
}
} }
} }
} }

View File

@ -8,6 +8,7 @@ using System.Linq;
using Pal.Client.Properties; using Pal.Client.Properties;
using ECommons; using ECommons;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Pal.Client.Configuration; using Pal.Client.Configuration;
namespace Pal.Client namespace Pal.Client
@ -19,24 +20,23 @@ namespace Pal.Client
/// <see cref="DependencyInjection.DependencyInjectionContext"/> /// <see cref="DependencyInjection.DependencyInjectionContext"/>
internal sealed class Plugin : IDisposable internal sealed class Plugin : IDisposable
{ {
private readonly IServiceProvider _serviceProvider;
private readonly DalamudPluginInterface _pluginInterface; private readonly DalamudPluginInterface _pluginInterface;
private readonly IServiceProvider _serviceProvider;
private readonly ILogger<Plugin> _logger;
private readonly IPalacePalConfiguration _configuration; private readonly IPalacePalConfiguration _configuration;
private readonly RenderAdapter _renderAdapter; private readonly RenderAdapter _renderAdapter;
private readonly WindowSystem _windowSystem; private readonly WindowSystem _windowSystem;
public Plugin( public Plugin(
IServiceProvider serviceProvider,
DalamudPluginInterface pluginInterface, DalamudPluginInterface pluginInterface,
IPalacePalConfiguration configuration, IServiceProvider serviceProvider)
RenderAdapter renderAdapter,
WindowSystem windowSystem)
{ {
_serviceProvider = serviceProvider;
_pluginInterface = pluginInterface; _pluginInterface = pluginInterface;
_configuration = configuration; _serviceProvider = serviceProvider;
_renderAdapter = renderAdapter; _logger = _serviceProvider.GetRequiredService<ILogger<Plugin>>();
_windowSystem = windowSystem; _configuration = serviceProvider.GetRequiredService<IPalacePalConfiguration>();
_renderAdapter = serviceProvider.GetRequiredService<RenderAdapter>();
_windowSystem = serviceProvider.GetRequiredService<WindowSystem>();
LanguageChanged(pluginInterface.UiLanguage); LanguageChanged(pluginInterface.UiLanguage);
@ -65,6 +65,8 @@ namespace Pal.Client
private void LanguageChanged(string languageCode) private void LanguageChanged(string languageCode)
{ {
_logger.LogInformation("Language set to '{Language}'", languageCode);
Localization.Culture = new CultureInfo(languageCode); Localization.Culture = new CultureInfo(languageCode);
_windowSystem.Windows.OfType<ILanguageChanged>() _windowSystem.Windows.OfType<ILanguageChanged>()
.Each(w => w.LanguageChanged()); .Each(w => w.LanguageChanged());

View File

@ -4,5 +4,6 @@
{ {
TrapHoard, TrapHoard,
RegularCoffers, RegularCoffers,
Test,
} }
} }

View File

@ -1,15 +1,13 @@
using ImGuiNET; using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics; using System.Numerics;
using System.Text; using Pal.Client.Configuration;
using System.Threading.Tasks;
namespace Pal.Client.Rendering namespace Pal.Client.Rendering
{ {
internal interface IRenderer internal interface IRenderer
{ {
ERenderer GetConfigValue();
void SetLayer(ELayer layer, IReadOnlyList<IRenderElement> elements); void SetLayer(ELayer layer, IReadOnlyList<IRenderElement> elements);
void ResetLayer(ELayer layer); void ResetLayer(ELayer layer);

View File

@ -1,25 +1,55 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.Numerics; using System.Numerics;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Pal.Client.Configuration; using Pal.Client.Configuration;
namespace Pal.Client.Rendering namespace Pal.Client.Rendering
{ {
internal sealed class RenderAdapter : IRenderer internal sealed class RenderAdapter : IRenderer, IDisposable
{ {
private readonly SimpleRenderer _simpleRenderer; private readonly IServiceScopeFactory _serviceScopeFactory;
private readonly SplatoonRenderer _splatoonRenderer; private readonly ILogger<RenderAdapter> _logger;
private readonly IPalacePalConfiguration _configuration; private readonly IPalacePalConfiguration _configuration;
public RenderAdapter(SimpleRenderer simpleRenderer, SplatoonRenderer splatoonRenderer, IPalacePalConfiguration configuration) private IServiceScope? _renderScope;
public RenderAdapter(IServiceScopeFactory serviceScopeFactory, ILogger<RenderAdapter> logger,
IPalacePalConfiguration configuration)
{ {
_simpleRenderer = simpleRenderer; _serviceScopeFactory = serviceScopeFactory;
_splatoonRenderer = splatoonRenderer; _logger = logger;
_configuration = configuration; _configuration = configuration;
Implementation = Recreate(null);
} }
public IRenderer Implementation => _configuration.Renderer.SelectedRenderer == ERenderer.Splatoon private IRenderer Recreate(ERenderer? currentRenderer)
? _splatoonRenderer {
: _simpleRenderer; ERenderer targetRenderer = _configuration.Renderer.SelectedRenderer;
if (targetRenderer == currentRenderer)
return Implementation;
_renderScope?.Dispose();
_logger.LogInformation("Selected new renderer: {Renderer}", _configuration.Renderer.SelectedRenderer);
_renderScope = _serviceScopeFactory.CreateScope();
if (targetRenderer == ERenderer.Splatoon)
return _renderScope.ServiceProvider.GetRequiredService<SplatoonRenderer>();
else
return _renderScope.ServiceProvider.GetRequiredService<SimpleRenderer>();
}
public void ConfigUpdated()
{
Implementation = Recreate(Implementation.GetConfigValue());
}
public void Dispose()
=> _renderScope?.Dispose();
public IRenderer Implementation { get; private set; }
public void SetLayer(ELayer layer, IReadOnlyList<IRenderElement> elements) public void SetLayer(ELayer layer, IReadOnlyList<IRenderElement> elements)
=> Implementation.SetLayer(layer, elements); => Implementation.SetLayer(layer, elements);
@ -35,5 +65,8 @@ namespace Pal.Client.Rendering
if (Implementation is SimpleRenderer sr) if (Implementation is SimpleRenderer sr)
sr.DrawLayers(); sr.DrawLayers();
} }
public ERenderer GetConfigValue()
=> throw new NotImplementedException();
} }
} }

View File

@ -146,6 +146,9 @@ namespace Pal.Client.Rendering
ImGui.GetWindowDrawList().PathClear(); ImGui.GetWindowDrawList().PathClear();
} }
public ERenderer GetConfigValue()
=> ERenderer.Simple;
public void Dispose() public void Dispose()
{ {
foreach (var l in _layers.Values) foreach (var l in _layers.Values)

View File

@ -14,6 +14,7 @@ using System.Reflection;
using Dalamud.Game.ClientState; using Dalamud.Game.ClientState;
using Dalamud.Game.Gui; using Dalamud.Game.Gui;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Pal.Client.Configuration;
using Pal.Client.DependencyInjection; using Pal.Client.DependencyInjection;
using Pal.Client.Extensions; using Pal.Client.Extensions;
@ -41,7 +42,7 @@ namespace Pal.Client.Rendering
_clientState = clientState; _clientState = clientState;
_chat = chat; _chat = chat;
_logger.LogInformation("Initializing splatoon..."); _logger.LogInformation("Initializing splatoon");
ECommonsMain.Init(pluginInterface, dalamudPlugin, ECommons.Module.SplatoonAPI); ECommonsMain.Init(pluginInterface, dalamudPlugin, ECommons.Module.SplatoonAPI);
} }
@ -117,7 +118,7 @@ namespace Pal.Client.Rendering
CreateElement(Marker.EType.Hoard, pos.Value, ImGui.ColorConvertFloat4ToU32(hoardColor)), CreateElement(Marker.EType.Hoard, pos.Value, ImGui.ColorConvertFloat4ToU32(hoardColor)),
}; };
if (!Splatoon.AddDynamicElements("PalacePal.Test", if (!Splatoon.AddDynamicElements(ToLayerName(ELayer.Test),
elements.Cast<SplatoonElement>().Select(x => x.Delegate).ToArray(), elements.Cast<SplatoonElement>().Select(x => x.Delegate).ToArray(),
new[] { Environment.TickCount64 + 10000 })) new[] { Environment.TickCount64 + 10000 }))
{ {
@ -158,12 +159,18 @@ namespace Pal.Client.Rendering
} }
} }
public ERenderer GetConfigValue()
=> ERenderer.Splatoon;
public void Dispose() public void Dispose()
{ {
_logger.LogInformation("Disposing splatoon");
IsDisposed = true; IsDisposed = true;
ResetLayer(ELayer.TrapHoard); ResetLayer(ELayer.TrapHoard);
ResetLayer(ELayer.RegularCoffers); ResetLayer(ELayer.RegularCoffers);
ResetLayer(ELayer.Test);
ECommonsMain.Dispose(); ECommonsMain.Dispose();
} }

View File

@ -1,6 +1,7 @@
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Pal.Client.Configuration; using Pal.Client.Configuration;
using Pal.Client.DependencyInjection; using Pal.Client.DependencyInjection;
using Pal.Client.Rendering;
namespace Pal.Client.Scheduled namespace Pal.Client.Scheduled
{ {
@ -11,14 +12,20 @@ namespace Pal.Client.Scheduled
private readonly IPalacePalConfiguration _configuration; private readonly IPalacePalConfiguration _configuration;
private readonly FloorService _floorService; private readonly FloorService _floorService;
private readonly TerritoryState _territoryState; private readonly TerritoryState _territoryState;
private readonly RenderAdapter _renderAdapter;
public Handler(ILogger<Handler> logger, IPalacePalConfiguration configuration, FloorService floorService, public Handler(
TerritoryState territoryState) ILogger<Handler> logger,
IPalacePalConfiguration configuration,
FloorService floorService,
TerritoryState territoryState,
RenderAdapter renderAdapter)
: base(logger) : base(logger)
{ {
_configuration = configuration; _configuration = configuration;
_floorService = floorService; _floorService = floorService;
_territoryState = territoryState; _territoryState = territoryState;
_renderAdapter = renderAdapter;
} }
protected override void Run(QueuedConfigUpdate queued, ref bool recreateLayout, ref bool saveMarkers) protected override void Run(QueuedConfigUpdate queued, ref bool recreateLayout, ref bool saveMarkers)
@ -33,6 +40,8 @@ namespace Pal.Client.Scheduled
recreateLayout = true; recreateLayout = true;
saveMarkers = true; saveMarkers = true;
} }
_renderAdapter.ConfigUpdated();
} }
} }
} }