Profile configuration - Implemented hotkeys

Plugin import - Fixed folders causing errors in some ZIP formats
This commit is contained in:
Robert committed 2021-06-13 21:36:47 +02:00
1 parent 6e197d725a
commit a7c7d74e03
16 files changed
+494 -158

No files matched your search

@@ -537,15 +537,13 @@ namespace Artemis.Core.Services
string metaDataDirectory = metaDataFileEntry.FullName.Replace(metaDataFileEntry.Name, "");
foreach (ZipArchiveEntry zipArchiveEntry in archive.Entries)
{
if (zipArchiveEntry.FullName.StartsWith(metaDataDirectory))
if (zipArchiveEntry.FullName.StartsWith(metaDataDirectory) && !zipArchiveEntry.FullName.EndsWith("/"))
{
string target = Path.Combine(directoryInfo.FullName, zipArchiveEntry.FullName.Remove(0, metaDataDirectory.Length));
// Create folders
if (zipArchiveEntry.FullName.EndsWith("/"))
Utilities.CreateAccessibleDirectory(Path.GetDirectoryName(target)!);
Utilities.CreateAccessibleDirectory(Path.GetDirectoryName(target)!);
// Extract files
else
zipArchiveEntry.ExtractToFile(target);
zipArchiveEntry.ExtractToFile(target);
}
}
@@ -10,14 +10,14 @@ namespace Artemis.Core.Services
public interface IProfileService : IArtemisService
{
/// <summary>
/// Gets the JSON serializer settings used to create profile mementos
/// Gets the JSON serializer settings used to create profile mementos
/// </summary>
public static JsonSerializerSettings MementoSettings { get; } = new() {TypeNameHandling = TypeNameHandling.All};
/// <summary>
/// Gets the JSON serializer settings used to import/export profiles
/// Gets the JSON serializer settings used to import/export profiles
/// </summary>
public static JsonSerializerSettings ExportSettings { get; } = new() {TypeNameHandling = TypeNameHandling.All, Formatting = Formatting.Indented};
public static JsonSerializerSettings ExportSettings { get; } = new() {TypeNameHandling = TypeNameHandling.All, Formatting = Formatting.Indented};
/// <summary>
/// Gets a read only collection containing all the profile categories
@@ -29,6 +29,11 @@ namespace Artemis.Core.Services
/// </summary>
ReadOnlyCollection<ProfileConfiguration> ProfileConfigurations { get; }
/// <summary>
/// Gets or sets a boolean indicating whether hotkeys are enabled
/// </summary>
bool HotkeysEnabled { get; set; }
/// <summary>
/// Gets or sets a boolean indicating whether rendering should only be done for profiles being edited
/// </summary>
@@ -128,10 +133,14 @@ namespace Artemis.Core.Services
/// <param name="category">The <see cref="ProfileCategory" /> in which to import the profile</param>
/// <param name="exportModel">The model containing the profile to import</param>
/// <param name="makeUnique">Whether or not to give the profile a new GUID, making it unique</param>
/// <param name="markAsFreshImport">Whether or not to mark the profile as a fresh import, causing it to be adapted until any changes are made to it</param>
/// <param name="markAsFreshImport">
/// Whether or not to mark the profile as a fresh import, causing it to be adapted until
/// any changes are made to it
/// </param>
/// <param name="nameAffix">Text to add after the name of the profile (separated by a dash)</param>
/// <returns>The resulting profile configuration</returns>
ProfileConfiguration ImportProfile(ProfileCategory category, ProfileConfigurationExportModel exportModel, bool makeUnique = true, bool markAsFreshImport = true, string? nameAffix = "imported");
ProfileConfiguration ImportProfile(ProfileCategory category, ProfileConfigurationExportModel exportModel, bool makeUnique = true, bool markAsFreshImport = true,
string? nameAffix = "imported");
/// <summary>
/// Adapts a given profile to the currently active devices
@@ -15,16 +15,17 @@ namespace Artemis.Core.Services
internal class ProfileService : IProfileService
{
private readonly ILogger _logger;
private readonly List<ArtemisKeyboardKeyEventArgs> _pendingKeyboardEvents = new();
private readonly IPluginManagementService _pluginManagementService;
private readonly List<ProfileCategory> _profileCategories;
private readonly IProfileCategoryRepository _profileCategoryRepository;
private readonly IProfileRepository _profileRepository;
private readonly IRgbService _rgbService;
private readonly List<Exception> _updateExceptions = new();
private DateTime _lastUpdateExceptionLog;
private readonly List<Exception> _renderExceptions = new();
private readonly IRgbService _rgbService;
private readonly List<Exception> _updateExceptions = new();
private DateTime _lastRenderExceptionLog;
private DateTime _lastUpdateExceptionLog;
public ProfileService(ILogger logger,
IRgbService rgbService,
@@ -33,6 +34,7 @@ namespace Artemis.Core.Services
IDataBindingService dataBindingService,
IProfileCategoryRepository profileCategoryRepository,
IPluginManagementService pluginManagementService,
IInputService inputService,
IProfileRepository profileRepository)
{
_logger = logger;
@@ -46,10 +48,23 @@ namespace Artemis.Core.Services
_pluginManagementService.PluginFeatureEnabled += PluginManagementServiceOnPluginFeatureToggled;
_pluginManagementService.PluginFeatureDisabled += PluginManagementServiceOnPluginFeatureToggled;
inputService.KeyboardKeyUp += InputServiceOnKeyboardKeyUp;
if (!_profileCategories.Any())
CreateDefaultProfileCategories();
}
private void InputServiceOnKeyboardKeyUp(object? sender, ArtemisKeyboardKeyEventArgs e)
{
if (!HotkeysEnabled)
return;
lock (_profileCategories)
{
_pendingKeyboardEvents.Add(e);
}
}
/// <summary>
/// Populates all missing LEDs on all currently active profiles
/// </summary>
@@ -88,84 +103,25 @@ namespace Artemis.Core.Services
UpdateModules();
}
public bool RenderForEditor { get; set; }
public void UpdateProfiles(double deltaTime)
private void ProcessPendingKeyEvents(ProfileConfiguration profileConfiguration)
{
lock (_profileCategories)
if (profileConfiguration.HotkeyMode == ProfileConfigurationHotkeyMode.None)
return;
foreach (ArtemisKeyboardKeyEventArgs e in _pendingKeyboardEvents)
{
// Iterate the children in reverse because the first category must be rendered last to end up on top
for (int i = _profileCategories.Count - 1; i > -1; i--)
if (profileConfiguration.HotkeyMode == ProfileConfigurationHotkeyMode.Toggle)
{
ProfileCategory profileCategory = _profileCategories[i];
for (int j = profileCategory.ProfileConfigurations.Count - 1; j > -1; j--)
{
ProfileConfiguration profileConfiguration = profileCategory.ProfileConfigurations[j];
// Profiles being edited are updated at their own leisure
if (profileConfiguration.IsBeingEdited)
continue;
bool shouldBeActive = profileConfiguration.ShouldBeActive(false);
if (shouldBeActive)
{
profileConfiguration.Update();
shouldBeActive = profileConfiguration.ActivationConditionMet;
}
try
{
// Make sure the profile is active or inactive according to the parameters above
if (shouldBeActive && profileConfiguration.Profile == null)
ActivateProfile(profileConfiguration);
else if (!shouldBeActive && profileConfiguration.Profile != null)
DeactivateProfile(profileConfiguration);
profileConfiguration.Profile?.Update(deltaTime);
}
catch (Exception e)
{
_updateExceptions.Add(e);
}
}
if (profileConfiguration.EnableHotkey != null && profileConfiguration.EnableHotkey.MatchesEventArgs(e))
profileConfiguration.IsSuspended = !profileConfiguration.IsSuspended;
}
LogProfileUpdateExceptions();
}
}
public void RenderProfiles(SKCanvas canvas)
{
lock (_profileCategories)
{
// Iterate the children in reverse because the first category must be rendered last to end up on top
for (int i = _profileCategories.Count - 1; i > -1; i--)
else
{
ProfileCategory profileCategory = _profileCategories[i];
for (int j = profileCategory.ProfileConfigurations.Count - 1; j > -1; j--)
{
try
{
ProfileConfiguration profileConfiguration = profileCategory.ProfileConfigurations[j];
if (RenderForEditor)
{
if (profileConfiguration.IsBeingEdited)
profileConfiguration.Profile?.Render(canvas, SKPointI.Empty);
}
else
{
// Ensure all criteria are met before rendering
if (!profileConfiguration.IsSuspended && !profileConfiguration.IsMissingModule && profileConfiguration.ActivationConditionMet)
profileConfiguration.Profile?.Render(canvas, SKPointI.Empty);
}
}
catch (Exception e)
{
_renderExceptions.Add(e);
}
}
if (profileConfiguration.IsSuspended && profileConfiguration.EnableHotkey != null && profileConfiguration.EnableHotkey.MatchesEventArgs(e))
profileConfiguration.IsSuspended = false;
if (!profileConfiguration.IsSuspended && profileConfiguration.DisableHotkey != null && profileConfiguration.DisableHotkey.MatchesEventArgs(e))
profileConfiguration.IsSuspended = true;
}
LogProfileRenderExceptions();
}
}
@@ -211,6 +167,93 @@ namespace Artemis.Core.Services
_renderExceptions.Clear();
}
public bool HotkeysEnabled { get; set; }
public bool RenderForEditor { get; set; }
public void UpdateProfiles(double deltaTime)
{
lock (_profileCategories)
{
// Iterate the children in reverse because the first category must be rendered last to end up on top
for (int i = _profileCategories.Count - 1; i > -1; i--)
{
ProfileCategory profileCategory = _profileCategories[i];
for (int j = profileCategory.ProfileConfigurations.Count - 1; j > -1; j--)
{
ProfileConfiguration profileConfiguration = profileCategory.ProfileConfigurations[j];
// Process hotkeys that where pressed since this profile last updated
ProcessPendingKeyEvents(profileConfiguration);
// Profiles being edited are updated at their own leisure
if (profileConfiguration.IsBeingEdited)
continue;
bool shouldBeActive = profileConfiguration.ShouldBeActive(false);
if (shouldBeActive)
{
profileConfiguration.Update();
shouldBeActive = profileConfiguration.ActivationConditionMet;
}
try
{
// Make sure the profile is active or inactive according to the parameters above
if (shouldBeActive && profileConfiguration.Profile == null)
ActivateProfile(profileConfiguration);
else if (!shouldBeActive && profileConfiguration.Profile != null)
DeactivateProfile(profileConfiguration);
profileConfiguration.Profile?.Update(deltaTime);
}
catch (Exception e)
{
_updateExceptions.Add(e);
}
}
}
LogProfileUpdateExceptions();
_pendingKeyboardEvents.Clear();
}
}
public void RenderProfiles(SKCanvas canvas)
{
lock (_profileCategories)
{
// Iterate the children in reverse because the first category must be rendered last to end up on top
for (int i = _profileCategories.Count - 1; i > -1; i--)
{
ProfileCategory profileCategory = _profileCategories[i];
for (int j = profileCategory.ProfileConfigurations.Count - 1; j > -1; j--)
{
try
{
ProfileConfiguration profileConfiguration = profileCategory.ProfileConfigurations[j];
if (RenderForEditor)
{
if (profileConfiguration.IsBeingEdited)
profileConfiguration.Profile?.Render(canvas, SKPointI.Empty);
}
else
{
// Ensure all criteria are met before rendering
if (!profileConfiguration.IsSuspended && !profileConfiguration.IsMissingModule && profileConfiguration.ActivationConditionMet)
profileConfiguration.Profile?.Render(canvas, SKPointI.Empty);
}
}
catch (Exception e)
{
_renderExceptions.Add(e);
}
}
}
LogProfileRenderExceptions();
}
}
public ReadOnlyCollection<ProfileCategory> ProfileCategories
{
get
@@ -485,7 +528,8 @@ namespace Artemis.Core.Services
if (markAsFreshImport)
profileEntity.IsFreshImport = true;
_profileRepository.Add(profileEntity);
if (!makeUnique && _profileRepository.Get(profileEntity.Id) == null)
_profileRepository.Add(profileEntity);
ProfileConfiguration profileConfiguration;
if (exportModel.ProfileConfigurationEntity != null)
@@ -500,9 +544,7 @@ namespace Artemis.Core.Services
profileConfiguration.Name = $"{profileConfiguration.Name} - {nameAffix}";
}
else
{
profileConfiguration = new ProfileConfiguration(category, profileEntity.Name, "Import");
}
if (exportModel.ProfileImage != null)
{