mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Merge branch 'development'
This commit is contained in:
commit
4a3b4c21dc
@ -46,7 +46,7 @@ namespace Artemis.Core
|
|||||||
/// </param>
|
/// </param>
|
||||||
/// <returns><c>true</c> if the value was changed, <c>false</c> if the existing value matched the desired value.</returns>
|
/// <returns><c>true</c> if the value was changed, <c>false</c> if the existing value matched the desired value.</returns>
|
||||||
[NotifyPropertyChangedInvocator]
|
[NotifyPropertyChangedInvocator]
|
||||||
protected virtual bool SetAndNotify<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
|
protected virtual bool SetAndNotify<T>(ref T storage, T value, [CallerMemberName] string? propertyName = null)
|
||||||
{
|
{
|
||||||
if (!RequiresUpdate(ref storage, value)) return false;
|
if (!RequiresUpdate(ref storage, value)) return false;
|
||||||
|
|
||||||
@ -64,7 +64,7 @@ namespace Artemis.Core
|
|||||||
/// and can be provided automatically when invoked from compilers that support <see cref="CallerMemberNameAttribute" />
|
/// and can be provided automatically when invoked from compilers that support <see cref="CallerMemberNameAttribute" />
|
||||||
/// .
|
/// .
|
||||||
/// </param>
|
/// </param>
|
||||||
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
|
||||||
{
|
{
|
||||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,6 +9,9 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class CategoryAdaptionHint : IAdaptionHint
|
public class CategoryAdaptionHint : IAdaptionHint
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance of the <see cref="CategoryAdaptionHint" /> class
|
||||||
|
/// </summary>
|
||||||
public CategoryAdaptionHint()
|
public CategoryAdaptionHint()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -41,6 +44,12 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public int Amount { get; set; }
|
public int Amount { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"Category adaption - {nameof(Category)}: {Category}, {nameof(Skip)}: {Skip}, {nameof(LimitAmount)}: {LimitAmount}, {nameof(Amount)}: {Amount}";
|
||||||
|
}
|
||||||
|
|
||||||
#region Implementation of IAdaptionHint
|
#region Implementation of IAdaptionHint
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -65,11 +74,5 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return $"Category adaption - {nameof(Category)}: {Category}, {nameof(Skip)}: {Skip}, {nameof(LimitAmount)}: {LimitAmount}, {nameof(Amount)}: {Amount}";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -10,6 +10,9 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class DeviceAdaptionHint : IAdaptionHint
|
public class DeviceAdaptionHint : IAdaptionHint
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance of the <see cref="DeviceAdaptionHint" /> class
|
||||||
|
/// </summary>
|
||||||
public DeviceAdaptionHint()
|
public DeviceAdaptionHint()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,6 +18,9 @@ namespace Artemis.Core
|
|||||||
{KeyboardSection.Extra, Enum.GetValues<LedId>().Where(l => l >= LedId.Keyboard_Custom1 && l <= LedId.Keyboard_Custom64).ToList()}
|
{KeyboardSection.Extra, Enum.GetValues<LedId>().Where(l => l >= LedId.Keyboard_Custom1 && l <= LedId.Keyboard_Custom64).ToList()}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance of the <see cref="KeyboardSectionAdaptionHint" /> class
|
||||||
|
/// </summary>
|
||||||
public KeyboardSectionAdaptionHint()
|
public KeyboardSectionAdaptionHint()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@ -421,7 +421,7 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
if (keyframeEntity.Position > ProfileElement.Timeline.Length)
|
if (keyframeEntity.Position > ProfileElement.Timeline.Length)
|
||||||
return null;
|
return null;
|
||||||
T value = CoreJson.DeserializeObject<T>(keyframeEntity.Value);
|
T? value = CoreJson.DeserializeObject<T>(keyframeEntity.Value);
|
||||||
if (value == null)
|
if (value == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
|||||||
@ -28,6 +28,7 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
internal ProfileCategory(ProfileCategoryEntity entity)
|
internal ProfileCategory(ProfileCategoryEntity entity)
|
||||||
{
|
{
|
||||||
|
_name = null!;
|
||||||
Entity = entity;
|
Entity = entity;
|
||||||
Load();
|
Load();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,4 @@
|
|||||||
using System;
|
using System.IO;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
|
||||||
using System.Reflection;
|
|
||||||
using Artemis.Core.Services;
|
using Artemis.Core.Services;
|
||||||
using Artemis.Storage;
|
using Artemis.Storage;
|
||||||
using Artemis.Storage.Migrations.Interfaces;
|
using Artemis.Storage.Migrations.Interfaces;
|
||||||
|
|||||||
@ -15,7 +15,7 @@ namespace Artemis.Core.Modules
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the current value of the dynamic child
|
/// Gets or sets the current value of the dynamic child
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public new T Value { get; set; }
|
public T Value { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override object? GetValue()
|
protected override object? GetValue()
|
||||||
|
|||||||
@ -66,6 +66,9 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public ReadOnlyCollection<PluginFeatureInfo> Features => _features.AsReadOnly();
|
public ReadOnlyCollection<PluginFeatureInfo> Features => _features.AsReadOnly();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a read-only collection of profiles running on the plugin
|
||||||
|
/// </summary>
|
||||||
public ReadOnlyCollection<Profiler> Profilers => _profilers.AsReadOnly();
|
public ReadOnlyCollection<Profiler> Profilers => _profilers.AsReadOnly();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -51,6 +51,7 @@ namespace Artemis.Core
|
|||||||
if (instance == null) throw new ArgumentNullException(nameof(instance));
|
if (instance == null) throw new ArgumentNullException(nameof(instance));
|
||||||
Plugin = plugin ?? throw new ArgumentNullException(nameof(plugin));
|
Plugin = plugin ?? throw new ArgumentNullException(nameof(plugin));
|
||||||
FeatureType = instance.GetType();
|
FeatureType = instance.GetType();
|
||||||
|
Entity = new PluginFeatureEntity();
|
||||||
|
|
||||||
Name = attribute?.Name ?? instance.GetType().Name.Humanize(LetterCasing.Title);
|
Name = attribute?.Name ?? instance.GetType().Name.Humanize(LetterCasing.Title);
|
||||||
Description = attribute?.Description;
|
Description = attribute?.Description;
|
||||||
|
|||||||
@ -9,10 +9,10 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
private long _current;
|
private long _current;
|
||||||
private DateTime _lastReport;
|
private DateTime _lastReport;
|
||||||
|
private long _lastReportValue;
|
||||||
private double _percentage;
|
private double _percentage;
|
||||||
private double _progressPerSecond;
|
private double _progressPerSecond;
|
||||||
private long _total;
|
private long _total;
|
||||||
private long _lastReportValue;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The current amount
|
/// The current amount
|
||||||
@ -81,6 +81,9 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public event EventHandler? ProgressReported;
|
public event EventHandler? ProgressReported;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the <see cref="ProgressReported" /> event
|
||||||
|
/// </summary>
|
||||||
protected virtual void OnProgressReported()
|
protected virtual void OnProgressReported()
|
||||||
{
|
{
|
||||||
ProgressReported?.Invoke(this, EventArgs.Empty);
|
ProgressReported?.Invoke(this, EventArgs.Empty);
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using Artemis.Storage.Entities.General;
|
using System;
|
||||||
|
using Artemis.Storage.Entities.General;
|
||||||
|
|
||||||
namespace Artemis.Core.ScriptingProviders
|
namespace Artemis.Core.ScriptingProviders
|
||||||
{
|
{
|
||||||
@ -7,24 +8,26 @@ namespace Artemis.Core.ScriptingProviders
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class ScriptConfiguration : CorePropertyChanged, IStorageModel
|
public class ScriptConfiguration : CorePropertyChanged, IStorageModel
|
||||||
{
|
{
|
||||||
private string _scriptingProviderId;
|
private bool _hasChanges;
|
||||||
private string _name;
|
private string _name;
|
||||||
|
private string? _pendingScriptContent;
|
||||||
private string? _scriptContent;
|
private string? _scriptContent;
|
||||||
|
private string _scriptingProviderId;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new instance of the <see cref="ScriptConfiguration" /> class
|
/// Creates a new instance of the <see cref="ScriptConfiguration" /> class
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ScriptConfiguration(ScriptingProvider provider, string name)
|
public ScriptConfiguration(ScriptingProvider provider, string name)
|
||||||
{
|
{
|
||||||
ScriptingProviderId = provider.Id;
|
_scriptingProviderId = provider.Id;
|
||||||
Name = name;
|
_name = name;
|
||||||
Entity = new ScriptConfigurationEntity();
|
Entity = new ScriptConfigurationEntity();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal ScriptConfiguration(ScriptConfigurationEntity entity)
|
internal ScriptConfiguration(ScriptConfigurationEntity entity)
|
||||||
{
|
{
|
||||||
ScriptingProviderId = null!;
|
_scriptingProviderId = null!;
|
||||||
Name = null!;
|
_name = null!;
|
||||||
Entity = entity;
|
Entity = entity;
|
||||||
|
|
||||||
Load();
|
Load();
|
||||||
@ -54,7 +57,36 @@ namespace Artemis.Core.ScriptingProviders
|
|||||||
public string? ScriptContent
|
public string? ScriptContent
|
||||||
{
|
{
|
||||||
get => _scriptContent;
|
get => _scriptContent;
|
||||||
set => SetAndNotify(ref _scriptContent, value);
|
private set
|
||||||
|
{
|
||||||
|
if (!SetAndNotify(ref _scriptContent, value)) return;
|
||||||
|
OnScriptContentChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the pending changes to the script's content
|
||||||
|
/// </summary>
|
||||||
|
public string? PendingScriptContent
|
||||||
|
{
|
||||||
|
get => _pendingScriptContent;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(value))
|
||||||
|
value = null;
|
||||||
|
if (!SetAndNotify(ref _pendingScriptContent, value)) return;
|
||||||
|
HasChanges = ScriptContent != PendingScriptContent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a boolean indicating whether this configuration has pending changes to it's
|
||||||
|
/// <see cref="ScriptContent" />
|
||||||
|
/// </summary>
|
||||||
|
public bool HasChanges
|
||||||
|
{
|
||||||
|
get => _hasChanges;
|
||||||
|
set => SetAndNotify(ref _hasChanges, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -64,6 +96,24 @@ namespace Artemis.Core.ScriptingProviders
|
|||||||
|
|
||||||
internal ScriptConfigurationEntity Entity { get; }
|
internal ScriptConfigurationEntity Entity { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Applies the <see cref="PendingScriptContent" /> to the <see cref="ScriptContent" />
|
||||||
|
/// </summary>
|
||||||
|
public void ApplyPendingChanges()
|
||||||
|
{
|
||||||
|
ScriptContent = PendingScriptContent;
|
||||||
|
HasChanges = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Discards the <see cref="PendingScriptContent" />
|
||||||
|
/// </summary>
|
||||||
|
public void DiscardPendingChanges()
|
||||||
|
{
|
||||||
|
PendingScriptContent = ScriptContent;
|
||||||
|
HasChanges = false;
|
||||||
|
}
|
||||||
|
|
||||||
#region Implementation of IStorageModel
|
#region Implementation of IStorageModel
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -71,6 +121,7 @@ namespace Artemis.Core.ScriptingProviders
|
|||||||
{
|
{
|
||||||
ScriptingProviderId = Entity.ScriptingProviderId;
|
ScriptingProviderId = Entity.ScriptingProviderId;
|
||||||
ScriptContent = Entity.ScriptContent;
|
ScriptContent = Entity.ScriptContent;
|
||||||
|
PendingScriptContent = Entity.ScriptContent;
|
||||||
Name = Entity.Name;
|
Name = Entity.Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,6 +130,24 @@ namespace Artemis.Core.ScriptingProviders
|
|||||||
{
|
{
|
||||||
Entity.ScriptingProviderId = ScriptingProviderId;
|
Entity.ScriptingProviderId = ScriptingProviderId;
|
||||||
Entity.ScriptContent = ScriptContent;
|
Entity.ScriptContent = ScriptContent;
|
||||||
|
Entity.Name = Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Events
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs whenever the contents of the script have changed
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler? ScriptContentChanged;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the <see cref="ScriptContentChanged" /> event
|
||||||
|
/// </summary>
|
||||||
|
protected virtual void OnScriptContentChanged()
|
||||||
|
{
|
||||||
|
ScriptContentChanged?.Invoke(this, EventArgs.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@ -37,6 +37,19 @@ namespace Artemis.Core.ScriptingProviders
|
|||||||
/// <param name="script">The script the editor must edit</param>
|
/// <param name="script">The script the editor must edit</param>
|
||||||
public abstract IScriptEditorViewModel CreatePropertyScriptEditor(TPropertyScript script);
|
public abstract IScriptEditorViewModel CreatePropertyScriptEditor(TPropertyScript script);
|
||||||
|
|
||||||
|
#region Overrides of PluginFeature
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
internal override void InternalDisable()
|
||||||
|
{
|
||||||
|
base.InternalDisable();
|
||||||
|
|
||||||
|
while (Scripts.Count > 0)
|
||||||
|
Scripts[0].Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region Overrides of ScriptingProvider
|
#region Overrides of ScriptingProvider
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -104,19 +117,6 @@ namespace Artemis.Core.ScriptingProviders
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Overrides of PluginFeature
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
internal override void InternalDisable()
|
|
||||||
{
|
|
||||||
base.InternalDisable();
|
|
||||||
|
|
||||||
while (Scripts.Count > 0)
|
|
||||||
Scripts[0].Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -128,17 +128,22 @@ namespace Artemis.Core.ScriptingProviders
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class ScriptingProvider : PluginFeature
|
public abstract class ScriptingProvider : PluginFeature
|
||||||
{
|
{
|
||||||
internal abstract Type GlobalScriptType { get; }
|
/// <summary>
|
||||||
internal abstract Type PropertyScriptType { get; }
|
/// Gets the name of the scripting language this provider provides
|
||||||
internal abstract Type LayerScriptType { get; }
|
/// </summary>
|
||||||
internal abstract Type ProfileScriptType { get; }
|
public abstract string LanguageName { get; }
|
||||||
internal List<Script> InternalScripts { get; } = new();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a list of all active scripts belonging to this scripting provider
|
/// Gets a list of all active scripts belonging to this scripting provider
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ReadOnlyCollection<Script> Scripts => InternalScripts.AsReadOnly();
|
public ReadOnlyCollection<Script> Scripts => InternalScripts.AsReadOnly();
|
||||||
|
|
||||||
|
internal abstract Type GlobalScriptType { get; }
|
||||||
|
internal abstract Type PropertyScriptType { get; }
|
||||||
|
internal abstract Type LayerScriptType { get; }
|
||||||
|
internal abstract Type ProfileScriptType { get; }
|
||||||
|
internal List<Script> InternalScripts { get; } = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when the UI needs a script editor for a <see cref="GlobalScript" />
|
/// Called when the UI needs a script editor for a <see cref="GlobalScript" />
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -12,7 +12,7 @@ namespace Artemis.Core.ScriptingProviders
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
internal ScriptingService ScriptingService { get; set; }
|
internal ScriptingService? ScriptingService { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called whenever the Artemis Core is about to update
|
/// Called whenever the Artemis Core is about to update
|
||||||
@ -35,7 +35,7 @@ namespace Artemis.Core.ScriptingProviders
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
internal override void InternalCleanup()
|
internal override void InternalCleanup()
|
||||||
{
|
{
|
||||||
ScriptingService.InternalGlobalScripts.Remove(this);
|
ScriptingService?.InternalGlobalScripts.Remove(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@ -11,6 +11,10 @@ namespace Artemis.Core.ScriptingProviders
|
|||||||
protected LayerScript(Layer layer, ScriptConfiguration configuration) : base(configuration)
|
protected LayerScript(Layer layer, ScriptConfiguration configuration) : base(configuration)
|
||||||
{
|
{
|
||||||
Layer = layer;
|
Layer = layer;
|
||||||
|
lock (Layer.Scripts)
|
||||||
|
{
|
||||||
|
Layer.Scripts.Add(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -11,6 +11,10 @@ namespace Artemis.Core.ScriptingProviders
|
|||||||
protected ProfileScript(Profile profile, ScriptConfiguration configuration) : base(configuration)
|
protected ProfileScript(Profile profile, ScriptConfiguration configuration) : base(configuration)
|
||||||
{
|
{
|
||||||
Profile = profile;
|
Profile = profile;
|
||||||
|
lock (Profile.Scripts)
|
||||||
|
{
|
||||||
|
Profile.Scripts.Add(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -10,6 +10,10 @@
|
|||||||
protected PropertyScript(ILayerProperty layerProperty, ScriptConfiguration configuration) : base(configuration)
|
protected PropertyScript(ILayerProperty layerProperty, ScriptConfiguration configuration) : base(configuration)
|
||||||
{
|
{
|
||||||
LayerProperty = layerProperty;
|
LayerProperty = layerProperty;
|
||||||
|
lock (LayerProperty.Scripts)
|
||||||
|
{
|
||||||
|
LayerProperty.Scripts.Add(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -35,7 +35,7 @@ namespace Artemis.Core
|
|||||||
/// <param name="name">The name of the setting</param>
|
/// <param name="name">The name of the setting</param>
|
||||||
/// <param name="defaultValue">The default value to use if the setting does not exist yet</param>
|
/// <param name="defaultValue">The default value to use if the setting does not exist yet</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public PluginSetting<T> GetSetting<T>(string name, T defaultValue = default)
|
public PluginSetting<T> GetSetting<T>(string name, T? defaultValue = default)
|
||||||
{
|
{
|
||||||
lock (_settingEntities)
|
lock (_settingEntities)
|
||||||
{
|
{
|
||||||
|
|||||||
64
src/Artemis.Core/Services/Interfaces/IScriptingService.cs
Normal file
64
src/Artemis.Core/Services/Interfaces/IScriptingService.cs
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using Artemis.Core.ScriptingProviders;
|
||||||
|
|
||||||
|
namespace Artemis.Core.Services
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A service that allows you to manage various types of <see cref="Script" /> instances
|
||||||
|
/// </summary>
|
||||||
|
public interface IScriptingService : IArtemisService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a list of all currently active global scripts
|
||||||
|
/// </summary>
|
||||||
|
ReadOnlyCollection<GlobalScript> GlobalScripts { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a <see cref="GlobalScript" /> instance for the given <paramref name="scriptConfiguration" />
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="scriptConfiguration">The script configuration of the script</param>
|
||||||
|
/// <returns>
|
||||||
|
/// If the <see cref="ScriptingProvider" /> was found an instance of the script; otherwise <see langword="null" />
|
||||||
|
/// .
|
||||||
|
/// </returns>
|
||||||
|
GlobalScript? CreateScriptInstance(ScriptConfiguration scriptConfiguration);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a <see cref="ProfileScript" /> instance for the given <paramref name="scriptConfiguration" />
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="profile">The profile the script configuration is configured for</param>
|
||||||
|
/// <param name="scriptConfiguration">The script configuration of the script</param>
|
||||||
|
/// <returns>
|
||||||
|
/// If the <see cref="ScriptingProvider" /> was found an instance of the script; otherwise <see langword="null" />
|
||||||
|
/// .
|
||||||
|
/// </returns>
|
||||||
|
ProfileScript? CreateScriptInstance(Profile profile, ScriptConfiguration scriptConfiguration);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a <see cref="LayerScript" /> instance for the given <paramref name="scriptConfiguration" />
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="layer">The layer the script configuration is configured fo</param>
|
||||||
|
/// <param name="scriptConfiguration">The script configuration of the script</param>
|
||||||
|
/// <returns>
|
||||||
|
/// If the <see cref="ScriptingProvider" /> was found an instance of the script; otherwise <see langword="null" />
|
||||||
|
/// .
|
||||||
|
/// </returns>
|
||||||
|
LayerScript? CreateScriptInstance(Layer layer, ScriptConfiguration scriptConfiguration);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a <see cref="PropertyScript" /> instance for the given <paramref name="scriptConfiguration" />
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="layerProperty">The layer property the script configuration is configured fo</param>
|
||||||
|
/// <param name="scriptConfiguration">The script configuration of the script</param>
|
||||||
|
/// <returns>
|
||||||
|
/// If the <see cref="ScriptingProvider" /> was found an instance of the script; otherwise <see langword="null" />
|
||||||
|
/// .
|
||||||
|
/// </returns>
|
||||||
|
PropertyScript? CreateScriptInstance(ILayerProperty layerProperty, ScriptConfiguration scriptConfiguration);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Deletes the provided global script by it's configuration
|
||||||
|
/// </summary>
|
||||||
|
void DeleteScript(ScriptConfiguration scriptConfiguration);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -175,45 +175,10 @@ namespace Artemis.Core.Services
|
|||||||
provider.InternalScripts.Add(script);
|
provider.InternalScripts.Add(script);
|
||||||
return script;
|
return script;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public interface IScriptingService : IArtemisService
|
/// <inheritdoc />
|
||||||
{
|
public void DeleteScript(ScriptConfiguration scriptConfiguration)
|
||||||
/// <summary>
|
{
|
||||||
/// Gets a read only collection of all active global scripts
|
}
|
||||||
/// </summary>
|
|
||||||
ReadOnlyCollection<GlobalScript> GlobalScripts { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Attempts to create an instance of a global script configured in the provided <see cref="ScriptConfiguration" />
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="scriptConfiguration">The script configuration of the script to instantiate</param>
|
|
||||||
/// <returns>An instance of the script if the script provider was found; otherwise <see langword="null" /></returns>
|
|
||||||
GlobalScript? CreateScriptInstance(ScriptConfiguration scriptConfiguration);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Attempts to create an instance of a profile script configured in the provided <see cref="ScriptConfiguration" />
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="profile">The profile the script is bound to</param>
|
|
||||||
/// <param name="scriptConfiguration">The script configuration of the script to instantiate</param>
|
|
||||||
/// <returns>An instance of the script if the script provider was found; otherwise <see langword="null" /></returns>
|
|
||||||
ProfileScript? CreateScriptInstance(Profile profile, ScriptConfiguration scriptConfiguration);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Attempts to create an instance of a layer script configured in the provided <see cref="ScriptConfiguration" />
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="layer">The layer the script is bound to</param>
|
|
||||||
/// <param name="scriptConfiguration">The script configuration of the script to instantiate</param>
|
|
||||||
/// <returns>An instance of the script if the script provider was found; otherwise <see langword="null" /></returns>
|
|
||||||
LayerScript? CreateScriptInstance(Layer layer, ScriptConfiguration scriptConfiguration);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Attempts to create an instance of a layer property script configured in the provided
|
|
||||||
/// <see cref="ScriptConfiguration" />
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="layerProperty">The layer property the script is bound to</param>
|
|
||||||
/// <param name="scriptConfiguration">The script configuration of the script to instantiate</param>
|
|
||||||
/// <returns>An instance of the script if the script provider was found; otherwise <see langword="null" /></returns>
|
|
||||||
PropertyScript? CreateScriptInstance(ILayerProperty layerProperty, ScriptConfiguration scriptConfiguration);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -12,9 +12,9 @@ namespace Artemis.Core.Services
|
|||||||
_pluginSettings = new PluginSettings(Constants.CorePlugin, pluginRepository);
|
_pluginSettings = new PluginSettings(Constants.CorePlugin, pluginRepository);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PluginSetting<T> GetSetting<T>(string name, T defaultValue = default)
|
public PluginSetting<T> GetSetting<T>(string name, T? defaultValue = default)
|
||||||
{
|
{
|
||||||
return _pluginSettings.GetSetting(name, defaultValue!);
|
return _pluginSettings.GetSetting(name, defaultValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,6 +31,6 @@ namespace Artemis.Core.Services
|
|||||||
/// <param name="name">The name of the setting</param>
|
/// <param name="name">The name of the setting</param>
|
||||||
/// <param name="defaultValue">The default value to use if the setting does not exist yet</param>
|
/// <param name="defaultValue">The default value to use if the setting does not exist yet</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
PluginSetting<T> GetSetting<T>(string name, T defaultValue = default);
|
PluginSetting<T> GetSetting<T>(string name, T? defaultValue = default);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -42,7 +42,8 @@ namespace Artemis.Core.Services
|
|||||||
_profileCategoryRepository = profileCategoryRepository;
|
_profileCategoryRepository = profileCategoryRepository;
|
||||||
_pluginManagementService = pluginManagementService;
|
_pluginManagementService = pluginManagementService;
|
||||||
_profileRepository = profileRepository;
|
_profileRepository = profileRepository;
|
||||||
_profileCategories = new List<ProfileCategory>(_profileCategoryRepository.GetAll().Select(c => new ProfileCategory(c)).OrderBy(c => c.Order));
|
_profileCategories = new List<ProfileCategory>(_profileCategoryRepository.GetAll()
|
||||||
|
.Select(c => new ProfileCategory(c)).OrderBy(c => c.Order));
|
||||||
|
|
||||||
_rgbService.LedsChanged += RgbServiceOnLedsChanged;
|
_rgbService.LedsChanged += RgbServiceOnLedsChanged;
|
||||||
_pluginManagementService.PluginFeatureEnabled += PluginManagementServiceOnPluginFeatureToggled;
|
_pluginManagementService.PluginFeatureEnabled += PluginManagementServiceOnPluginFeatureToggled;
|
||||||
@ -52,6 +53,17 @@ namespace Artemis.Core.Services
|
|||||||
|
|
||||||
if (!_profileCategories.Any())
|
if (!_profileCategories.Any())
|
||||||
CreateDefaultProfileCategories();
|
CreateDefaultProfileCategories();
|
||||||
|
UpdateModules();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void OnProfileActivated(ProfileConfigurationEventArgs e)
|
||||||
|
{
|
||||||
|
ProfileActivated?.Invoke(this, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void OnProfileDeactivated(ProfileConfigurationEventArgs e)
|
||||||
|
{
|
||||||
|
ProfileDeactivated?.Invoke(this, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InputServiceOnKeyboardKeyUp(object? sender, ArtemisKeyboardKeyEventArgs e)
|
private void InputServiceOnKeyboardKeyUp(object? sender, ArtemisKeyboardKeyEventArgs e)
|
||||||
@ -87,8 +99,10 @@ namespace Artemis.Core.Services
|
|||||||
{
|
{
|
||||||
List<Module> modules = _pluginManagementService.GetFeaturesOfType<Module>();
|
List<Module> modules = _pluginManagementService.GetFeaturesOfType<Module>();
|
||||||
foreach (ProfileCategory profileCategory in _profileCategories)
|
foreach (ProfileCategory profileCategory in _profileCategories)
|
||||||
foreach (ProfileConfiguration profileConfiguration in profileCategory.ProfileConfigurations)
|
{
|
||||||
profileConfiguration.LoadModules(modules);
|
foreach (ProfileConfiguration profileConfiguration in profileCategory.ProfileConfigurations)
|
||||||
|
profileConfiguration.LoadModules(modules);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +126,8 @@ namespace Artemis.Core.Services
|
|||||||
{
|
{
|
||||||
if (profileConfiguration.HotkeyMode == ProfileConfigurationHotkeyMode.Toggle)
|
if (profileConfiguration.HotkeyMode == ProfileConfigurationHotkeyMode.Toggle)
|
||||||
{
|
{
|
||||||
if (profileConfiguration.EnableHotkey != null && profileConfiguration.EnableHotkey.MatchesEventArgs(e))
|
if (profileConfiguration.EnableHotkey != null &&
|
||||||
|
profileConfiguration.EnableHotkey.MatchesEventArgs(e))
|
||||||
profileConfiguration.IsSuspended = !profileConfiguration.IsSuspended;
|
profileConfiguration.IsSuspended = !profileConfiguration.IsSuspended;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -143,7 +158,11 @@ namespace Artemis.Core.Services
|
|||||||
|
|
||||||
// Group by stack trace, that should gather up duplicate exceptions
|
// Group by stack trace, that should gather up duplicate exceptions
|
||||||
foreach (IGrouping<string?, Exception> exceptions in _updateExceptions.GroupBy(e => e.StackTrace))
|
foreach (IGrouping<string?, Exception> exceptions in _updateExceptions.GroupBy(e => e.StackTrace))
|
||||||
_logger.Warning(exceptions.First(), "Exception was thrown {count} times during profile update in the last 10 seconds", exceptions.Count());
|
{
|
||||||
|
_logger.Warning(exceptions.First(),
|
||||||
|
"Exception was thrown {count} times during profile update in the last 10 seconds",
|
||||||
|
exceptions.Count());
|
||||||
|
}
|
||||||
|
|
||||||
// When logging is finished start with a fresh slate
|
// When logging is finished start with a fresh slate
|
||||||
_updateExceptions.Clear();
|
_updateExceptions.Clear();
|
||||||
@ -161,7 +180,11 @@ namespace Artemis.Core.Services
|
|||||||
|
|
||||||
// Group by stack trace, that should gather up duplicate exceptions
|
// Group by stack trace, that should gather up duplicate exceptions
|
||||||
foreach (IGrouping<string?, Exception> exceptions in _renderExceptions.GroupBy(e => e.StackTrace))
|
foreach (IGrouping<string?, Exception> exceptions in _renderExceptions.GroupBy(e => e.StackTrace))
|
||||||
_logger.Warning(exceptions.First(), "Exception was thrown {count} times during profile render in the last 10 seconds", exceptions.Count());
|
{
|
||||||
|
_logger.Warning(exceptions.First(),
|
||||||
|
"Exception was thrown {count} times during profile render in the last 10 seconds",
|
||||||
|
exceptions.Count());
|
||||||
|
}
|
||||||
|
|
||||||
// When logging is finished start with a fresh slate
|
// When logging is finished start with a fresh slate
|
||||||
_renderExceptions.Clear();
|
_renderExceptions.Clear();
|
||||||
@ -464,8 +487,9 @@ namespace Artemis.Core.Services
|
|||||||
string top = profile.UndoStack.Pop();
|
string top = profile.UndoStack.Pop();
|
||||||
string memento = JsonConvert.SerializeObject(profile.ProfileEntity, IProfileService.MementoSettings);
|
string memento = JsonConvert.SerializeObject(profile.ProfileEntity, IProfileService.MementoSettings);
|
||||||
profile.RedoStack.Push(memento);
|
profile.RedoStack.Push(memento);
|
||||||
profile.ProfileEntity = JsonConvert.DeserializeObject<ProfileEntity>(top, IProfileService.MementoSettings)
|
profile.ProfileEntity =
|
||||||
?? throw new InvalidOperationException("Failed to deserialize memento");
|
JsonConvert.DeserializeObject<ProfileEntity>(top, IProfileService.MementoSettings)
|
||||||
|
?? throw new InvalidOperationException("Failed to deserialize memento");
|
||||||
|
|
||||||
profile.Load();
|
profile.Load();
|
||||||
profile.PopulateLeds(_rgbService.EnabledDevices);
|
profile.PopulateLeds(_rgbService.EnabledDevices);
|
||||||
@ -489,8 +513,9 @@ namespace Artemis.Core.Services
|
|||||||
string top = profile.RedoStack.Pop();
|
string top = profile.RedoStack.Pop();
|
||||||
string memento = JsonConvert.SerializeObject(profile.ProfileEntity, IProfileService.MementoSettings);
|
string memento = JsonConvert.SerializeObject(profile.ProfileEntity, IProfileService.MementoSettings);
|
||||||
profile.UndoStack.Push(memento);
|
profile.UndoStack.Push(memento);
|
||||||
profile.ProfileEntity = JsonConvert.DeserializeObject<ProfileEntity>(top, IProfileService.MementoSettings)
|
profile.ProfileEntity =
|
||||||
?? throw new InvalidOperationException("Failed to deserialize memento");
|
JsonConvert.DeserializeObject<ProfileEntity>(top, IProfileService.MementoSettings)
|
||||||
|
?? throw new InvalidOperationException("Failed to deserialize memento");
|
||||||
|
|
||||||
profile.Load();
|
profile.Load();
|
||||||
profile.PopulateLeds(_rgbService.EnabledDevices);
|
profile.PopulateLeds(_rgbService.EnabledDevices);
|
||||||
@ -513,14 +538,16 @@ namespace Artemis.Core.Services
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProfileConfiguration ImportProfile(ProfileCategory category, ProfileConfigurationExportModel exportModel, bool makeUnique, bool markAsFreshImport, string? nameAffix)
|
public ProfileConfiguration ImportProfile(ProfileCategory category, ProfileConfigurationExportModel exportModel,
|
||||||
|
bool makeUnique, bool markAsFreshImport, string? nameAffix)
|
||||||
{
|
{
|
||||||
if (exportModel.ProfileEntity == null)
|
if (exportModel.ProfileEntity == null)
|
||||||
throw new ArtemisCoreException("Cannot import a profile without any data");
|
throw new ArtemisCoreException("Cannot import a profile without any data");
|
||||||
|
|
||||||
// Create a copy of the entity because we'll be using it from now on
|
// Create a copy of the entity because we'll be using it from now on
|
||||||
ProfileEntity profileEntity = JsonConvert.DeserializeObject<ProfileEntity>(
|
ProfileEntity profileEntity = JsonConvert.DeserializeObject<ProfileEntity>(
|
||||||
JsonConvert.SerializeObject(exportModel.ProfileEntity, IProfileService.ExportSettings), IProfileService.ExportSettings
|
JsonConvert.SerializeObject(exportModel.ProfileEntity, IProfileService.ExportSettings),
|
||||||
|
IProfileService.ExportSettings
|
||||||
)!;
|
)!;
|
||||||
|
|
||||||
// Assign a new GUID to make sure it is unique in case of a previous import of the same content
|
// Assign a new GUID to make sure it is unique in case of a previous import of the same content
|
||||||
@ -532,7 +559,7 @@ namespace Artemis.Core.Services
|
|||||||
if (markAsFreshImport)
|
if (markAsFreshImport)
|
||||||
profileEntity.IsFreshImport = true;
|
profileEntity.IsFreshImport = true;
|
||||||
|
|
||||||
if (_profileRepository.Get(profileEntity.Id) != null)
|
if (_profileRepository.Get(profileEntity.Id) == null)
|
||||||
_profileRepository.Add(profileEntity);
|
_profileRepository.Add(profileEntity);
|
||||||
else
|
else
|
||||||
throw new ArtemisCoreException($"Cannot import this profile without {nameof(makeUnique)} being true");
|
throw new ArtemisCoreException($"Cannot import this profile without {nameof(makeUnique)} being true");
|
||||||
@ -550,7 +577,9 @@ namespace Artemis.Core.Services
|
|||||||
profileConfiguration.Name = $"{profileConfiguration.Name} - {nameAffix}";
|
profileConfiguration.Name = $"{profileConfiguration.Name} - {nameAffix}";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
profileConfiguration = new ProfileConfiguration(category, profileEntity.Name, "Import");
|
profileConfiguration = new ProfileConfiguration(category, profileEntity.Name, "Import");
|
||||||
|
}
|
||||||
|
|
||||||
if (exportModel.ProfileImage != null)
|
if (exportModel.ProfileImage != null)
|
||||||
{
|
{
|
||||||
@ -561,6 +590,9 @@ namespace Artemis.Core.Services
|
|||||||
|
|
||||||
profileConfiguration.Entity.ProfileId = profileEntity.Id;
|
profileConfiguration.Entity.ProfileId = profileEntity.Id;
|
||||||
category.AddProfileConfiguration(profileConfiguration, 0);
|
category.AddProfileConfiguration(profileConfiguration, 0);
|
||||||
|
|
||||||
|
List<Module> modules = _pluginManagementService.GetFeaturesOfType<Module>();
|
||||||
|
profileConfiguration.LoadModules(modules);
|
||||||
SaveProfileCategory(category);
|
SaveProfileCategory(category);
|
||||||
|
|
||||||
return profileConfiguration;
|
return profileConfiguration;
|
||||||
@ -589,21 +621,7 @@ namespace Artemis.Core.Services
|
|||||||
_profileRepository.Save(profile.ProfileEntity);
|
_profileRepository.Save(profile.ProfileEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Events
|
|
||||||
|
|
||||||
public event EventHandler<ProfileConfigurationEventArgs>? ProfileActivated;
|
public event EventHandler<ProfileConfigurationEventArgs>? ProfileActivated;
|
||||||
public event EventHandler<ProfileConfigurationEventArgs>? ProfileDeactivated;
|
public event EventHandler<ProfileConfigurationEventArgs>? ProfileDeactivated;
|
||||||
|
|
||||||
protected virtual void OnProfileActivated(ProfileConfigurationEventArgs e)
|
|
||||||
{
|
|
||||||
ProfileActivated?.Invoke(this, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void OnProfileDeactivated(ProfileConfigurationEventArgs e)
|
|
||||||
{
|
|
||||||
ProfileDeactivated?.Invoke(this, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -52,7 +52,9 @@ namespace Artemis.Core.Services
|
|||||||
object? response = null;
|
object? response = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
T deserialized = JsonConvert.DeserializeObject<T>(await reader.ReadToEndAsync());
|
T? deserialized = JsonConvert.DeserializeObject<T>(await reader.ReadToEndAsync());
|
||||||
|
if (deserialized == null)
|
||||||
|
throw new JsonException("Deserialization returned null");
|
||||||
|
|
||||||
if (_requestHandler != null)
|
if (_requestHandler != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -13,7 +13,7 @@ namespace Artemis.Storage.Migrations
|
|||||||
{
|
{
|
||||||
ILiteCollection<ProfileCategoryEntity> profileCategories = repository.Database.GetCollection<ProfileCategoryEntity>();
|
ILiteCollection<ProfileCategoryEntity> profileCategories = repository.Database.GetCollection<ProfileCategoryEntity>();
|
||||||
profileCategories.EnsureIndex(s => s.Name, true);
|
profileCategories.EnsureIndex(s => s.Name, true);
|
||||||
ProfileCategoryEntity? profileCategoryEntity = profileCategories.Find(c => c.Name == "Converted").FirstOrDefault();
|
ProfileCategoryEntity profileCategoryEntity = profileCategories.Find(c => c.Name == "Converted").FirstOrDefault();
|
||||||
if (profileCategoryEntity == null)
|
if (profileCategoryEntity == null)
|
||||||
{
|
{
|
||||||
profileCategoryEntity = new ProfileCategoryEntity {Name = "Imported"};
|
profileCategoryEntity = new ProfileCategoryEntity {Name = "Imported"};
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using MaterialDesignThemes.Wpf;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Shared
|
namespace Artemis.UI.Shared
|
||||||
|
|
||||||
@ -11,16 +10,22 @@ namespace Artemis.UI.Shared
|
|||||||
public partial class ProfileConfigurationIcon : UserControl
|
public partial class ProfileConfigurationIcon : UserControl
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the <see cref="PackIconKind" />
|
/// Gets or sets the <see cref="Core.ProfileConfigurationIcon" /> to display
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly DependencyProperty ConfigurationIconProperty =
|
public static readonly DependencyProperty ConfigurationIconProperty =
|
||||||
DependencyProperty.Register(nameof(ConfigurationIcon), typeof(Core.ProfileConfigurationIcon), typeof(ProfileConfigurationIcon));
|
DependencyProperty.Register(nameof(ConfigurationIcon), typeof(Core.ProfileConfigurationIcon), typeof(ProfileConfigurationIcon));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance of the <see cref="ProfileConfigurationIcon" /> class
|
||||||
|
/// </summary>
|
||||||
public ProfileConfigurationIcon()
|
public ProfileConfigurationIcon()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the <see cref="Core.ProfileConfigurationIcon" /> to display
|
||||||
|
/// </summary>
|
||||||
public Core.ProfileConfigurationIcon ConfigurationIcon
|
public Core.ProfileConfigurationIcon ConfigurationIcon
|
||||||
{
|
{
|
||||||
get => (Core.ProfileConfigurationIcon) GetValue(ConfigurationIconProperty);
|
get => (Core.ProfileConfigurationIcon) GetValue(ConfigurationIconProperty);
|
||||||
|
|||||||
@ -17,7 +17,7 @@ namespace Artemis.UI.Shared
|
|||||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
{
|
{
|
||||||
if (value is not Stream stream)
|
if (value is not Stream stream)
|
||||||
return null;
|
return Binding.DoNothing;
|
||||||
|
|
||||||
stream.Position = 0;
|
stream.Position = 0;
|
||||||
|
|
||||||
|
|||||||
@ -19,7 +19,7 @@ namespace Artemis.UI.Shared
|
|||||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
{
|
{
|
||||||
if (value is not Stream stream)
|
if (value is not Stream stream)
|
||||||
return null;
|
return Binding.DoNothing;
|
||||||
|
|
||||||
stream.Position = 0;
|
stream.Position = 0;
|
||||||
|
|
||||||
|
|||||||
@ -6,10 +6,10 @@ namespace Artemis.UI.Shared.ScriptingProviders
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a Stylet view model containing a script editor
|
/// Represents a Stylet view model containing a script editor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ScriptEditorViewModelViewModel : Screen, IScriptEditorViewModel
|
public class ScriptEditorViewModel : Screen, IScriptEditorViewModel
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public ScriptEditorViewModelViewModel(Script script)
|
public ScriptEditorViewModel(Script script)
|
||||||
{
|
{
|
||||||
Script = script;
|
Script = script;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,12 +2,21 @@
|
|||||||
|
|
||||||
namespace Artemis.UI.Shared
|
namespace Artemis.UI.Shared
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Providers a proxy between data contexts
|
||||||
|
/// </summary>
|
||||||
public class BindingProxy : Freezable
|
public class BindingProxy : Freezable
|
||||||
{
|
{
|
||||||
// Using a DependencyProperty as the backing store for Data. This enables animation, styling, binding, etc...
|
// Using a DependencyProperty as the backing store for Data. This enables animation, styling, binding, etc...
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the data that was proxied
|
||||||
|
/// </summary>
|
||||||
public static readonly DependencyProperty DataProperty =
|
public static readonly DependencyProperty DataProperty =
|
||||||
DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
|
DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the data that was proxied
|
||||||
|
/// </summary>
|
||||||
public object Data
|
public object Data
|
||||||
{
|
{
|
||||||
get => GetValue(DataProperty);
|
get => GetValue(DataProperty);
|
||||||
@ -16,6 +25,7 @@ namespace Artemis.UI.Shared
|
|||||||
|
|
||||||
#region Overrides of Freezable
|
#region Overrides of Freezable
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override Freezable CreateInstanceCore()
|
protected override Freezable CreateInstanceCore()
|
||||||
{
|
{
|
||||||
return new BindingProxy();
|
return new BindingProxy();
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.Modules;
|
using Artemis.Core.Modules;
|
||||||
|
using Artemis.Core.ScriptingProviders;
|
||||||
using Artemis.UI.Screens.Header;
|
using Artemis.UI.Screens.Header;
|
||||||
using Artemis.UI.Screens.Plugins;
|
using Artemis.UI.Screens.Plugins;
|
||||||
using Artemis.UI.Screens.ProfileEditor.Conditions;
|
using Artemis.UI.Screens.ProfileEditor.Conditions;
|
||||||
@ -16,6 +17,7 @@ using Artemis.UI.Screens.ProfileEditor.ProfileTree.Dialogs.AdaptionHints;
|
|||||||
using Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem;
|
using Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem;
|
||||||
using Artemis.UI.Screens.ProfileEditor.Visualization;
|
using Artemis.UI.Screens.ProfileEditor.Visualization;
|
||||||
using Artemis.UI.Screens.ProfileEditor.Visualization.Tools;
|
using Artemis.UI.Screens.ProfileEditor.Visualization.Tools;
|
||||||
|
using Artemis.UI.Screens.Scripting;
|
||||||
using Artemis.UI.Screens.Settings.Device;
|
using Artemis.UI.Screens.Settings.Device;
|
||||||
using Artemis.UI.Screens.Settings.Device.Tabs;
|
using Artemis.UI.Screens.Settings.Device.Tabs;
|
||||||
using Artemis.UI.Screens.Settings.Tabs.Devices;
|
using Artemis.UI.Screens.Settings.Tabs.Devices;
|
||||||
@ -108,6 +110,14 @@ namespace Artemis.UI.Ninject.Factories
|
|||||||
PluginPrerequisiteViewModel PluginPrerequisiteViewModel(PluginPrerequisite pluginPrerequisite, bool uninstall);
|
PluginPrerequisiteViewModel PluginPrerequisiteViewModel(PluginPrerequisite pluginPrerequisite, bool uninstall);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface IScriptVmFactory : IVmFactory
|
||||||
|
{
|
||||||
|
ScriptsDialogViewModel ScriptsDialogViewModel(Profile profile);
|
||||||
|
ScriptsDialogViewModel ScriptsDialogViewModel(Layer layer);
|
||||||
|
ScriptsDialogViewModel ScriptsDialogViewModel(ILayerProperty layerProperty);
|
||||||
|
ScriptConfigurationViewModel ScriptConfigurationViewModel(ScriptConfiguration scriptConfiguration);
|
||||||
|
}
|
||||||
|
|
||||||
public interface ISidebarVmFactory : IVmFactory
|
public interface ISidebarVmFactory : IVmFactory
|
||||||
{
|
{
|
||||||
SidebarCategoryViewModel SidebarCategoryViewModel(ProfileCategory profileCategory);
|
SidebarCategoryViewModel SidebarCategoryViewModel(ProfileCategory profileCategory);
|
||||||
@ -122,7 +132,10 @@ namespace Artemis.UI.Ninject.Factories
|
|||||||
IDataBindingViewModel DataBindingViewModel(IDataBindingRegistration registration);
|
IDataBindingViewModel DataBindingViewModel(IDataBindingRegistration registration);
|
||||||
DirectDataBindingModeViewModel<TLayerProperty, TProperty> DirectDataBindingModeViewModel<TLayerProperty, TProperty>(DirectDataBinding<TLayerProperty, TProperty> directDataBinding);
|
DirectDataBindingModeViewModel<TLayerProperty, TProperty> DirectDataBindingModeViewModel<TLayerProperty, TProperty>(DirectDataBinding<TLayerProperty, TProperty> directDataBinding);
|
||||||
DataBindingModifierViewModel<TLayerProperty, TProperty> DataBindingModifierViewModel<TLayerProperty, TProperty>(DataBindingModifier<TLayerProperty, TProperty> modifier);
|
DataBindingModifierViewModel<TLayerProperty, TProperty> DataBindingModifierViewModel<TLayerProperty, TProperty>(DataBindingModifier<TLayerProperty, TProperty> modifier);
|
||||||
ConditionalDataBindingModeViewModel<TLayerProperty, TProperty> ConditionalDataBindingModeViewModel<TLayerProperty, TProperty>(ConditionalDataBinding<TLayerProperty, TProperty> conditionalDataBinding);
|
|
||||||
|
ConditionalDataBindingModeViewModel<TLayerProperty, TProperty> ConditionalDataBindingModeViewModel<TLayerProperty, TProperty>(
|
||||||
|
ConditionalDataBinding<TLayerProperty, TProperty> conditionalDataBinding);
|
||||||
|
|
||||||
DataBindingConditionViewModel<TLayerProperty, TProperty> DataBindingConditionViewModel<TLayerProperty, TProperty>(DataBindingCondition<TLayerProperty, TProperty> dataBindingCondition);
|
DataBindingConditionViewModel<TLayerProperty, TProperty> DataBindingConditionViewModel<TLayerProperty, TProperty>(DataBindingCondition<TLayerProperty, TProperty> dataBindingCondition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -217,7 +217,7 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
|
|||||||
Update();
|
Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CoreServiceOnFrameRendered(object? sender, FrameRenderedEventArgs e)
|
private void CoreServiceOnFrameRendered(object sender, FrameRenderedEventArgs e)
|
||||||
{
|
{
|
||||||
if (IsRootGroup)
|
if (IsRootGroup)
|
||||||
Evaluate();
|
Evaluate();
|
||||||
|
|||||||
@ -139,7 +139,7 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
|||||||
RenderProfileElement.Timeline.PropertyChanged += TimelineOnPropertyChanged;
|
RenderProfileElement.Timeline.PropertyChanged += TimelineOnPropertyChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TimelineOnPropertyChanged(object? sender, PropertyChangedEventArgs e)
|
private void TimelineOnPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||||
{
|
{
|
||||||
NotifyOfPropertyChange(nameof(DisplayContinuously));
|
NotifyOfPropertyChange(nameof(DisplayContinuously));
|
||||||
NotifyOfPropertyChange(nameof(AlwaysFinishTimeline));
|
NotifyOfPropertyChange(nameof(AlwaysFinishTimeline));
|
||||||
|
|||||||
@ -96,13 +96,16 @@
|
|||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem Header="_Scripting" IsEnabled="False">
|
<MenuItem Header="_Scripting" IsEnabled="False">
|
||||||
<MenuItem Header="_Profile scripts"
|
<MenuItem Header="_Profile scripts"
|
||||||
Icon="{materialDesign:PackIcon Kind=BookEdit}" />
|
Icon="{materialDesign:PackIcon Kind=BookEdit}"
|
||||||
|
Command="{s:Action OpenProfileScripts}"/>
|
||||||
<MenuItem Header="_Layer scripts"
|
<MenuItem Header="_Layer scripts"
|
||||||
Icon="{materialDesign:PackIcon Kind=Layers}"
|
Icon="{materialDesign:PackIcon Kind=Layers}"
|
||||||
IsEnabled="{Binding HasSelectedElement}"/>
|
IsEnabled="{Binding HasSelectedElement}"
|
||||||
|
Command="{s:Action OpenLayerScripts}"/>
|
||||||
<MenuItem Header="_Property scripts"
|
<MenuItem Header="_Property scripts"
|
||||||
Icon="{materialDesign:PackIcon Kind=FormTextbox}"
|
Icon="{materialDesign:PackIcon Kind=FormTextbox}"
|
||||||
IsEnabled="{Binding HasSelectedElement}"/>
|
IsEnabled="{Binding HasSelectedElement}"
|
||||||
|
Command="{s:Action OpenLayerPropertyScripts}"/>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem Header="_Help">
|
<MenuItem Header="_Help">
|
||||||
<MenuItem Header="Artemis wiki"
|
<MenuItem Header="Artemis wiki"
|
||||||
|
|||||||
@ -5,13 +5,11 @@ using System.Windows;
|
|||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.Services;
|
using Artemis.Core.Services;
|
||||||
using Artemis.UI.Events;
|
|
||||||
using Artemis.UI.Ninject.Factories;
|
using Artemis.UI.Ninject.Factories;
|
||||||
using Artemis.UI.Screens.ProfileEditor.DisplayConditions;
|
using Artemis.UI.Screens.ProfileEditor.DisplayConditions;
|
||||||
using Artemis.UI.Screens.ProfileEditor.LayerProperties;
|
using Artemis.UI.Screens.ProfileEditor.LayerProperties;
|
||||||
using Artemis.UI.Screens.ProfileEditor.ProfileTree;
|
using Artemis.UI.Screens.ProfileEditor.ProfileTree;
|
||||||
using Artemis.UI.Screens.ProfileEditor.Visualization;
|
using Artemis.UI.Screens.ProfileEditor.Visualization;
|
||||||
using Artemis.UI.Screens.Sidebar.Dialogs;
|
|
||||||
using Artemis.UI.Services;
|
using Artemis.UI.Services;
|
||||||
using Artemis.UI.Shared;
|
using Artemis.UI.Shared;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
@ -22,13 +20,14 @@ namespace Artemis.UI.Screens.ProfileEditor
|
|||||||
{
|
{
|
||||||
public class ProfileEditorViewModel : MainScreenViewModel
|
public class ProfileEditorViewModel : MainScreenViewModel
|
||||||
{
|
{
|
||||||
private readonly IMessageService _messageService;
|
|
||||||
private readonly IDebugService _debugService;
|
private readonly IDebugService _debugService;
|
||||||
private readonly ISidebarVmFactory _sidebarVmFactory;
|
private readonly IMessageService _messageService;
|
||||||
private readonly IEventAggregator _eventAggregator;
|
|
||||||
private readonly IProfileEditorService _profileEditorService;
|
private readonly IProfileEditorService _profileEditorService;
|
||||||
private readonly IProfileService _profileService;
|
private readonly IProfileService _profileService;
|
||||||
|
private readonly IScriptVmFactory _scriptVmFactory;
|
||||||
private readonly ISettingsService _settingsService;
|
private readonly ISettingsService _settingsService;
|
||||||
|
private readonly ISidebarVmFactory _sidebarVmFactory;
|
||||||
|
private readonly IWindowManager _windowManager;
|
||||||
private PluginSetting<GridLength> _bottomPanelsHeight;
|
private PluginSetting<GridLength> _bottomPanelsHeight;
|
||||||
private PluginSetting<GridLength> _dataModelConditionsHeight;
|
private PluginSetting<GridLength> _dataModelConditionsHeight;
|
||||||
private DisplayConditionsViewModel _displayConditionsViewModel;
|
private DisplayConditionsViewModel _displayConditionsViewModel;
|
||||||
@ -46,8 +45,10 @@ namespace Artemis.UI.Screens.ProfileEditor
|
|||||||
IProfileService profileService,
|
IProfileService profileService,
|
||||||
IDialogService dialogService,
|
IDialogService dialogService,
|
||||||
ISettingsService settingsService,
|
ISettingsService settingsService,
|
||||||
IMessageService messageService,
|
IMessageService messageService,
|
||||||
IDebugService debugService,
|
IDebugService debugService,
|
||||||
|
IWindowManager windowManager,
|
||||||
|
IScriptVmFactory scriptVmFactory,
|
||||||
ISidebarVmFactory sidebarVmFactory)
|
ISidebarVmFactory sidebarVmFactory)
|
||||||
{
|
{
|
||||||
_profileEditorService = profileEditorService;
|
_profileEditorService = profileEditorService;
|
||||||
@ -55,6 +56,8 @@ namespace Artemis.UI.Screens.ProfileEditor
|
|||||||
_settingsService = settingsService;
|
_settingsService = settingsService;
|
||||||
_messageService = messageService;
|
_messageService = messageService;
|
||||||
_debugService = debugService;
|
_debugService = debugService;
|
||||||
|
_windowManager = windowManager;
|
||||||
|
_scriptVmFactory = scriptVmFactory;
|
||||||
_sidebarVmFactory = sidebarVmFactory;
|
_sidebarVmFactory = sidebarVmFactory;
|
||||||
|
|
||||||
DisplayName = "Profile Editor";
|
DisplayName = "Profile Editor";
|
||||||
@ -191,6 +194,51 @@ namespace Artemis.UI.Screens.ProfileEditor
|
|||||||
_messageService.ShowMessage("Redid profile update", "UNDO", Undo);
|
_messageService.ShowMessage("Redid profile update", "UNDO", Undo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected override void OnInitialActivate()
|
||||||
|
{
|
||||||
|
_profileEditorService.SelectedProfileChanged += ProfileEditorServiceOnSelectedProfileChanged;
|
||||||
|
_profileEditorService.SelectedProfileElementChanged += ProfileEditorServiceOnSelectedProfileElementChanged;
|
||||||
|
LoadWorkspaceSettings();
|
||||||
|
base.OnInitialActivate();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnClose()
|
||||||
|
{
|
||||||
|
_profileEditorService.SelectedProfileChanged -= ProfileEditorServiceOnSelectedProfileChanged;
|
||||||
|
_profileEditorService.SelectedProfileElementChanged -= ProfileEditorServiceOnSelectedProfileElementChanged;
|
||||||
|
SaveWorkspaceSettings();
|
||||||
|
_profileEditorService.ChangeSelectedProfileConfiguration(null);
|
||||||
|
|
||||||
|
base.OnClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProfileEditorServiceOnSelectedProfileChanged(object sender, ProfileConfigurationEventArgs e)
|
||||||
|
{
|
||||||
|
NotifyOfPropertyChange(nameof(ProfileConfiguration));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProfileEditorServiceOnSelectedProfileElementChanged(object sender, RenderProfileElementEventArgs e)
|
||||||
|
{
|
||||||
|
NotifyOfPropertyChange(nameof(HasSelectedElement));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadWorkspaceSettings()
|
||||||
|
{
|
||||||
|
SidePanelsWidth = _settingsService.GetSetting("ProfileEditor.SidePanelsWidth", new GridLength(385));
|
||||||
|
DataModelConditionsHeight = _settingsService.GetSetting("ProfileEditor.DataModelConditionsHeight", new GridLength(345));
|
||||||
|
BottomPanelsHeight = _settingsService.GetSetting("ProfileEditor.BottomPanelsHeight", new GridLength(265));
|
||||||
|
ElementPropertiesWidth = _settingsService.GetSetting("ProfileEditor.ElementPropertiesWidth", new GridLength(545));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SaveWorkspaceSettings()
|
||||||
|
{
|
||||||
|
SidePanelsWidth.Save();
|
||||||
|
DataModelConditionsHeight.Save();
|
||||||
|
BottomPanelsHeight.Save();
|
||||||
|
ElementPropertiesWidth.Save();
|
||||||
|
}
|
||||||
|
|
||||||
#region Menu
|
#region Menu
|
||||||
|
|
||||||
public bool HasSelectedElement => _profileEditorService.SelectedProfileElement != null;
|
public bool HasSelectedElement => _profileEditorService.SelectedProfileElement != null;
|
||||||
@ -232,7 +280,9 @@ namespace Artemis.UI.Screens.ProfileEditor
|
|||||||
public void Paste()
|
public void Paste()
|
||||||
{
|
{
|
||||||
if (_profileEditorService.SelectedProfileElement != null && _profileEditorService.SelectedProfileElement.Parent is Folder parent)
|
if (_profileEditorService.SelectedProfileElement != null && _profileEditorService.SelectedProfileElement.Parent is Folder parent)
|
||||||
|
{
|
||||||
_profileEditorService.PasteProfileElement(parent, _profileEditorService.SelectedProfileElement.Order - 1);
|
_profileEditorService.PasteProfileElement(parent, _profileEditorService.SelectedProfileElement.Order - 1);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Folder rootFolder = _profileEditorService.SelectedProfile?.GetRootFolder();
|
Folder rootFolder = _profileEditorService.SelectedProfile?.GetRootFolder();
|
||||||
@ -241,6 +291,21 @@ namespace Artemis.UI.Screens.ProfileEditor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void OpenProfileScripts()
|
||||||
|
{
|
||||||
|
_windowManager.ShowWindow(_scriptVmFactory.ScriptsDialogViewModel(ProfileConfiguration.Profile));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OpenLayerScripts()
|
||||||
|
{
|
||||||
|
if (_profileEditorService.SelectedProfileElement is Layer layer)
|
||||||
|
_windowManager.ShowWindow(_scriptVmFactory.ScriptsDialogViewModel(layer));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OpenLayerPropertyScripts()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public void OpenDebugger()
|
public void OpenDebugger()
|
||||||
{
|
{
|
||||||
_debugService.ShowDebugger();
|
_debugService.ShowDebugger();
|
||||||
@ -257,49 +322,5 @@ namespace Artemis.UI.Screens.ProfileEditor
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
protected override void OnInitialActivate()
|
|
||||||
{
|
|
||||||
_profileEditorService.SelectedProfileChanged += ProfileEditorServiceOnSelectedProfileChanged;
|
|
||||||
_profileEditorService.SelectedProfileElementChanged += ProfileEditorServiceOnSelectedProfileElementChanged;
|
|
||||||
LoadWorkspaceSettings();
|
|
||||||
base.OnInitialActivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnClose()
|
|
||||||
{
|
|
||||||
_profileEditorService.SelectedProfileChanged -= ProfileEditorServiceOnSelectedProfileChanged;
|
|
||||||
_profileEditorService.SelectedProfileElementChanged -= ProfileEditorServiceOnSelectedProfileElementChanged;
|
|
||||||
SaveWorkspaceSettings();
|
|
||||||
_profileEditorService.ChangeSelectedProfileConfiguration(null);
|
|
||||||
|
|
||||||
base.OnClose();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ProfileEditorServiceOnSelectedProfileChanged(object sender, ProfileConfigurationEventArgs e)
|
|
||||||
{
|
|
||||||
NotifyOfPropertyChange(nameof(ProfileConfiguration));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ProfileEditorServiceOnSelectedProfileElementChanged(object sender, RenderProfileElementEventArgs e)
|
|
||||||
{
|
|
||||||
NotifyOfPropertyChange(nameof(HasSelectedElement));
|
|
||||||
}
|
|
||||||
private void LoadWorkspaceSettings()
|
|
||||||
{
|
|
||||||
SidePanelsWidth = _settingsService.GetSetting("ProfileEditor.SidePanelsWidth", new GridLength(385));
|
|
||||||
DataModelConditionsHeight = _settingsService.GetSetting("ProfileEditor.DataModelConditionsHeight", new GridLength(345));
|
|
||||||
BottomPanelsHeight = _settingsService.GetSetting("ProfileEditor.BottomPanelsHeight", new GridLength(265));
|
|
||||||
ElementPropertiesWidth = _settingsService.GetSetting("ProfileEditor.ElementPropertiesWidth", new GridLength(545));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SaveWorkspaceSettings()
|
|
||||||
{
|
|
||||||
SidePanelsWidth.Save();
|
|
||||||
DataModelConditionsHeight.Save();
|
|
||||||
BottomPanelsHeight.Save();
|
|
||||||
ElementPropertiesWidth.Save();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -57,10 +57,11 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization.Tools
|
|||||||
ShapePath = _layerEditorService.GetLayerPath(layer, true, true, true);
|
ShapePath = _layerEditorService.GetLayerPath(layer, true, true, true);
|
||||||
ShapeAnchor = _layerEditorService.GetLayerAnchorPosition(layer).ToSKPoint();
|
ShapeAnchor = _layerEditorService.GetLayerAnchorPosition(layer).ToSKPoint();
|
||||||
|
|
||||||
Rect layerBounds = _layerEditorService.GetLayerBounds(layer);
|
|
||||||
TransformGroup layerTransformGroup = _layerEditorService.GetLayerTransformGroup(layer);
|
|
||||||
Execute.PostToUIThread(() =>
|
Execute.PostToUIThread(() =>
|
||||||
{
|
{
|
||||||
|
Rect layerBounds = _layerEditorService.GetLayerBounds(layer);
|
||||||
|
TransformGroup layerTransformGroup = _layerEditorService.GetLayerTransformGroup(layer);
|
||||||
|
|
||||||
RectangleGeometry shapeGeometry = new(layerBounds) {Transform = layerTransformGroup};
|
RectangleGeometry shapeGeometry = new(layerBounds) {Transform = layerTransformGroup};
|
||||||
shapeGeometry.Freeze();
|
shapeGeometry.Freeze();
|
||||||
ShapeGeometry = shapeGeometry;
|
ShapeGeometry = shapeGeometry;
|
||||||
|
|||||||
@ -115,7 +115,7 @@ namespace Artemis.UI.Screens
|
|||||||
_eventAggregator.Publish(new MainWindowMouseEvent(sender, false, e));
|
_eventAggregator.Publish(new MainWindowMouseEvent(sender, false, e));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SidebarViewModelOnSelectedScreenChanged(object? sender, EventArgs e)
|
private void SidebarViewModelOnSelectedScreenChanged(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
ActiveItem = SidebarViewModel.SelectedScreen;
|
ActiveItem = SidebarViewModel.SelectedScreen;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,61 @@
|
|||||||
|
<UserControl x:Class="Artemis.UI.Screens.Scripting.Dialogs.ScriptConfigurationCreateView"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:local="clr-namespace:Artemis.UI.Screens.Scripting.Dialogs"
|
||||||
|
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||||
|
xmlns:s="https://github.com/canton7/Stylet"
|
||||||
|
xmlns:scriptingProviders="clr-namespace:Artemis.Core.ScriptingProviders;assembly=Artemis.Core"
|
||||||
|
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DesignHeight="450" d:DesignWidth="800"
|
||||||
|
d:DataContext="{d:DesignInstance local:ScriptConfigurationCreateViewModel}">
|
||||||
|
<UserControl.Resources>
|
||||||
|
<shared:BindingProxy x:Key="DataContextProxy" Data="{Binding}" />
|
||||||
|
</UserControl.Resources>
|
||||||
|
<StackPanel Margin="16">
|
||||||
|
<TextBlock Style="{StaticResource MaterialDesignHeadline6TextBlock}">
|
||||||
|
Add new script
|
||||||
|
</TextBlock>
|
||||||
|
|
||||||
|
<TextBox materialDesign:HintAssist.Hint="Script name"
|
||||||
|
Margin="0 8 0 16"
|
||||||
|
Width="300"
|
||||||
|
Style="{StaticResource MaterialDesignFilledTextBox}"
|
||||||
|
Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
|
|
||||||
|
<ComboBox materialDesign:HintAssist.Hint="Scripting provider"
|
||||||
|
Margin="0 8 0 16"
|
||||||
|
Width="300"
|
||||||
|
Style="{StaticResource MaterialDesignFilledComboBox}"
|
||||||
|
SelectedItem="{Binding SelectedScriptingProvider}">
|
||||||
|
<ComboBox.ItemsSource>
|
||||||
|
<CompositeCollection>
|
||||||
|
<ComboBoxItem IsEnabled="False"
|
||||||
|
Visibility="{Binding HasScriptingProviders, Converter={x:Static s:BoolToVisibilityConverter.InverseInstance}, Mode=OneWay}">
|
||||||
|
No scripting providers found
|
||||||
|
</ComboBoxItem>
|
||||||
|
<CollectionContainer Collection="{Binding Data.ScriptingProviders, Source={StaticResource DataContextProxy}}" />
|
||||||
|
</CompositeCollection>
|
||||||
|
</ComboBox.ItemsSource>
|
||||||
|
<ComboBox.ItemTemplate>
|
||||||
|
<DataTemplate DataType="{x:Type scriptingProviders:ScriptingProvider}">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<shared:ArtemisIcon Icon="{Binding Info.ResolvedIcon}" Width="18 " Height="18" Margin="0 0 5 0" VerticalAlignment="Center" />
|
||||||
|
<TextBlock Text="{Binding LanguageName}" VerticalAlignment="Center" />
|
||||||
|
</StackPanel>
|
||||||
|
</DataTemplate>
|
||||||
|
</ComboBox.ItemTemplate>
|
||||||
|
</ComboBox>
|
||||||
|
|
||||||
|
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0 8 0 0">
|
||||||
|
<Button Style="{StaticResource MaterialDesignFlatButton}" IsCancel="True" Margin="0 0 8 0" Command="{s:Action Cancel}">
|
||||||
|
CANCEL
|
||||||
|
</Button>
|
||||||
|
<Button Style="{StaticResource MaterialDesignFlatButton}" IsDefault="True" Margin="0 0 0 0" Command="{s:Action Accept}">
|
||||||
|
ACCEPT
|
||||||
|
</Button>
|
||||||
|
</StackPanel>
|
||||||
|
</StackPanel>
|
||||||
|
</UserControl>
|
||||||
@ -0,0 +1,57 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using Artemis.Core.ScriptingProviders;
|
||||||
|
using Artemis.Core.Services;
|
||||||
|
using Artemis.UI.Shared.Services;
|
||||||
|
using FluentValidation;
|
||||||
|
using Stylet;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Screens.Scripting.Dialogs
|
||||||
|
{
|
||||||
|
public class ScriptConfigurationCreateViewModel : DialogViewModelBase
|
||||||
|
{
|
||||||
|
private string _name;
|
||||||
|
private ScriptingProvider _selectedScriptingProvider;
|
||||||
|
|
||||||
|
public ScriptConfigurationCreateViewModel(IModelValidator<ScriptConfigurationCreateViewModel> validator, IPluginManagementService pluginManagementService) : base(validator)
|
||||||
|
{
|
||||||
|
_name = "My script";
|
||||||
|
|
||||||
|
ScriptingProviders = new BindableCollection<ScriptingProvider>(pluginManagementService.GetFeaturesOfType<ScriptingProvider>());
|
||||||
|
HasScriptingProviders = ScriptingProviders.Count > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BindableCollection<ScriptingProvider> ScriptingProviders { get; }
|
||||||
|
public bool HasScriptingProviders { get; }
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get => _name;
|
||||||
|
set => SetAndNotify(ref _name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScriptingProvider SelectedScriptingProvider
|
||||||
|
{
|
||||||
|
get => _selectedScriptingProvider;
|
||||||
|
set => SetAndNotify(ref _selectedScriptingProvider, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Accept()
|
||||||
|
{
|
||||||
|
await ValidateAsync();
|
||||||
|
|
||||||
|
if (HasErrors)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Session.Close(new ScriptConfiguration(SelectedScriptingProvider, Name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ProfileElementScriptConfigurationCreateViewModelValidator : AbstractValidator<ScriptConfigurationCreateViewModel>
|
||||||
|
{
|
||||||
|
public ProfileElementScriptConfigurationCreateViewModelValidator()
|
||||||
|
{
|
||||||
|
RuleFor(m => m.Name).NotEmpty().WithMessage("Script name may not be empty");
|
||||||
|
RuleFor(m => m.SelectedScriptingProvider).NotNull().WithMessage("Scripting provider is required");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
<UserControl x:Class="Artemis.UI.Screens.Scripting.Dialogs.ScriptConfigurationEditView"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:local="clr-namespace:Artemis.UI.Screens.Scripting.Dialogs"
|
||||||
|
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||||
|
xmlns:s="https://github.com/canton7/Stylet"
|
||||||
|
xmlns:scriptingProviders="clr-namespace:Artemis.Core.ScriptingProviders;assembly=Artemis.Core"
|
||||||
|
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DesignHeight="450" d:DesignWidth="800"
|
||||||
|
d:DataContext="{d:DesignInstance local:ScriptConfigurationEditViewModel}">
|
||||||
|
<StackPanel Margin="16">
|
||||||
|
<TextBlock Style="{StaticResource MaterialDesignHeadline6TextBlock}">
|
||||||
|
Edit script
|
||||||
|
</TextBlock>
|
||||||
|
|
||||||
|
<TextBox materialDesign:HintAssist.Hint="Script name"
|
||||||
|
Margin="0 8 0 16"
|
||||||
|
Width="300"
|
||||||
|
Style="{StaticResource MaterialDesignFilledTextBox}"
|
||||||
|
Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
|
|
||||||
|
<Grid Margin="0 8 0 0">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Button Grid.Column="0"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
Style="{StaticResource MaterialDesignFlatAccentButton}"
|
||||||
|
Command="{s:Action Delete}">
|
||||||
|
DELETE
|
||||||
|
</Button>
|
||||||
|
<StackPanel Grid.Column="1" Orientation="Horizontal">
|
||||||
|
<Button Style="{StaticResource MaterialDesignFlatButton}" IsCancel="True" Command="{s:Action Cancel}">
|
||||||
|
CANCEL
|
||||||
|
</Button>
|
||||||
|
<Button Style="{StaticResource MaterialDesignFlatButton}" IsDefault="True" Command="{s:Action Accept}">
|
||||||
|
ACCEPT
|
||||||
|
</Button>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</StackPanel>
|
||||||
|
</UserControl>
|
||||||
@ -0,0 +1,53 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using Artemis.Core.ScriptingProviders;
|
||||||
|
using Artemis.UI.Shared.Services;
|
||||||
|
using FluentValidation;
|
||||||
|
using Stylet;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Screens.Scripting.Dialogs
|
||||||
|
{
|
||||||
|
public class ScriptConfigurationEditViewModel : DialogViewModelBase
|
||||||
|
{
|
||||||
|
private string _name;
|
||||||
|
|
||||||
|
public ScriptConfigurationEditViewModel(IModelValidator<ScriptConfigurationEditViewModel> validator, ScriptConfiguration scriptConfiguration) : base(validator)
|
||||||
|
{
|
||||||
|
ScriptConfiguration = scriptConfiguration;
|
||||||
|
_name = ScriptConfiguration.Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScriptConfiguration ScriptConfiguration { get; }
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get => _name;
|
||||||
|
set => SetAndNotify(ref _name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Accept()
|
||||||
|
{
|
||||||
|
await ValidateAsync();
|
||||||
|
|
||||||
|
if (HasErrors)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ScriptConfiguration.Name = Name;
|
||||||
|
if (Session is {IsEnded: false})
|
||||||
|
Session.Close(nameof(Accept));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Delete()
|
||||||
|
{
|
||||||
|
if (Session is {IsEnded: false})
|
||||||
|
Session.Close(nameof(Delete));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ProfileElementScriptConfigurationEditViewModelValidator : AbstractValidator<ScriptConfigurationEditViewModel>
|
||||||
|
{
|
||||||
|
public ProfileElementScriptConfigurationEditViewModelValidator()
|
||||||
|
{
|
||||||
|
RuleFor(m => m.Name).NotEmpty().WithMessage("Script name may not be empty");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,83 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Artemis.Core.ScriptingProviders;
|
||||||
|
using Artemis.Core.Services;
|
||||||
|
using Artemis.UI.Screens.Scripting.Dialogs;
|
||||||
|
using Artemis.UI.Shared.ScriptingProviders;
|
||||||
|
using Artemis.UI.Shared.Services;
|
||||||
|
using Stylet;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Screens.Scripting
|
||||||
|
{
|
||||||
|
public class ScriptConfigurationViewModel : Conductor<IScriptEditorViewModel>
|
||||||
|
{
|
||||||
|
private readonly IScriptingService _scriptingService;
|
||||||
|
private readonly IDialogService _dialogService;
|
||||||
|
|
||||||
|
public ScriptConfigurationViewModel(ScriptConfiguration scriptConfiguration, IScriptingService scriptingService, IDialogService dialogService)
|
||||||
|
{
|
||||||
|
_scriptingService = scriptingService;
|
||||||
|
_dialogService = dialogService;
|
||||||
|
ScriptConfiguration = scriptConfiguration;
|
||||||
|
Script = ScriptConfiguration.Script;
|
||||||
|
|
||||||
|
ActiveItem = Script switch
|
||||||
|
{
|
||||||
|
GlobalScript globalScript => Script.ScriptingProvider.CreateGlobalScriptEditor(globalScript),
|
||||||
|
LayerScript layerScript => Script.ScriptingProvider.CreateLayerScriptScriptEditor(layerScript),
|
||||||
|
ProfileScript profileScript => Script.ScriptingProvider.CreateProfileScriptEditor(profileScript),
|
||||||
|
PropertyScript propertyScript => Script.ScriptingProvider.CreatePropertyScriptEditor(propertyScript),
|
||||||
|
_ => new UnknownScriptEditorViewModel(null)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public Script Script { get; set; }
|
||||||
|
public ScriptConfiguration ScriptConfiguration { get; }
|
||||||
|
|
||||||
|
public async Task ViewProperties()
|
||||||
|
{
|
||||||
|
object result = await _dialogService.ShowDialog<ScriptConfigurationEditViewModel>(new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{"scriptConfiguration", ScriptConfiguration}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result is nameof(ScriptConfigurationEditViewModel.Delete))
|
||||||
|
await Delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task Delete()
|
||||||
|
{
|
||||||
|
bool result = await _dialogService.ShowConfirmDialogAt("ScriptsDialog", "Delete script", $"Are you sure you want to delete '{ScriptConfiguration.Name}'?");
|
||||||
|
if (!result)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (Script)
|
||||||
|
{
|
||||||
|
case GlobalScript globalScript:
|
||||||
|
_scriptingService.DeleteScript(ScriptConfiguration);
|
||||||
|
break;
|
||||||
|
case LayerScript layerScript:
|
||||||
|
layerScript.Layer.ScriptConfigurations.Remove(ScriptConfiguration);
|
||||||
|
break;
|
||||||
|
case ProfileScript profileScript:
|
||||||
|
profileScript.Profile.ScriptConfigurations.Remove(ScriptConfiguration);
|
||||||
|
break;
|
||||||
|
case PropertyScript propertyScript:
|
||||||
|
propertyScript.LayerProperty.ScriptConfigurations.Remove(ScriptConfiguration);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScriptConfiguration.DiscardPendingChanges();
|
||||||
|
ScriptConfiguration.Script?.Dispose();
|
||||||
|
RequestClose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class UnknownScriptEditorViewModel : ScriptEditorViewModel
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public UnknownScriptEditorViewModel(Script script) : base(script)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
129
src/Artemis.UI/Screens/Scripting/ScriptsDialogView.xaml
Normal file
129
src/Artemis.UI/Screens/Scripting/ScriptsDialogView.xaml
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
<mde:MaterialWindow x:Class="Artemis.UI.Screens.Scripting.ScriptsDialogView"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:local="clr-namespace:Artemis.UI.Screens.Scripting"
|
||||||
|
xmlns:mde="https://spiegelp.github.io/MaterialDesignExtensions/winfx/xaml"
|
||||||
|
xmlns:svgc="http://sharpvectors.codeplex.com/svgc/"
|
||||||
|
xmlns:s="https://github.com/canton7/Stylet"
|
||||||
|
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||||
|
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
FadeContentIfInactive="False"
|
||||||
|
Icon="/Resources/Images/Logo/bow.ico"
|
||||||
|
Title="{Binding DisplayName}"
|
||||||
|
TitleBarIcon="{svgc:SvgImage Source=/Resources/Images/Logo/bow-white.svg}"
|
||||||
|
Foreground="{DynamicResource MaterialDesignBody}"
|
||||||
|
Background="{DynamicResource MaterialDesignPaper}"
|
||||||
|
FontFamily="pack://application:,,,/MaterialDesignThemes.Wpf;component/Resources/Roboto/#Roboto"
|
||||||
|
UseLayoutRounding="True"
|
||||||
|
Height="800" Width="1200"
|
||||||
|
d:DataContext="{d:DesignInstance {x:Type local:ScriptsDialogViewModel}}">
|
||||||
|
<mde:MaterialWindow.Resources>
|
||||||
|
<ResourceDictionary>
|
||||||
|
<ResourceDictionary.MergedDictionaries>
|
||||||
|
<ResourceDictionary Source="../Sidebar/ArtemisSidebar.xaml" />
|
||||||
|
</ResourceDictionary.MergedDictionaries>
|
||||||
|
</ResourceDictionary>
|
||||||
|
</mde:MaterialWindow.Resources>
|
||||||
|
<materialDesign:DialogHost IsTabStop="False" Focusable="False" Identifier="ScriptsDialog" DialogTheme="Inherit">
|
||||||
|
<Grid>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="240" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<!-- Sidebar -->
|
||||||
|
<Border Grid.Column="0" ClipToBounds="True" Background="{DynamicResource MaterialDesignToolBarBackground}">
|
||||||
|
<Grid>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<ListBox Grid.Row="0"
|
||||||
|
Margin="0 10 0 0"
|
||||||
|
ItemContainerStyle="{StaticResource SidebarListBoxItem}"
|
||||||
|
HorizontalContentAlignment="Stretch"
|
||||||
|
ItemsSource="{Binding Items}"
|
||||||
|
SelectedItem="{Binding ActiveItem}">
|
||||||
|
<ListBox.ItemTemplate>
|
||||||
|
<DataTemplate DataType="{x:Type local:ScriptConfigurationViewModel}">
|
||||||
|
<Grid>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<shared:ArtemisIcon Grid.Row="0"
|
||||||
|
Grid.Column="0"
|
||||||
|
Grid.RowSpan="2"
|
||||||
|
Icon="{Binding ScriptConfiguration.Script.ScriptingProvider.Info.ResolvedIcon, FallbackValue=QuestionMark}"
|
||||||
|
Width="18 "
|
||||||
|
Height="18"
|
||||||
|
Margin="0 0 10 0"
|
||||||
|
VerticalAlignment="Center" />
|
||||||
|
<TextBlock Grid.Row="0" Grid.Column="1" VerticalAlignment="Center" Text="{Binding ScriptConfiguration.Name}"
|
||||||
|
Visibility="{Binding ScriptConfiguration.HasChanges, Converter={x:Static s:BoolToVisibilityConverter.InverseInstance}, Mode=OneWay}"/>
|
||||||
|
<TextBlock Grid.Row="0" Grid.Column="1" VerticalAlignment="Center"
|
||||||
|
Visibility="{Binding ScriptConfiguration.HasChanges, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}">
|
||||||
|
<Run Text="{Binding ScriptConfiguration.Name}" FontWeight="Bold" />
|
||||||
|
<Run Text="*" />
|
||||||
|
</TextBlock>
|
||||||
|
<TextBlock Grid.Row="1"
|
||||||
|
Grid.Column="1"
|
||||||
|
Text="{Binding ScriptConfiguration.Script.ScriptingProvider.LanguageName, FallbackValue='Unknown scripting provider'}"
|
||||||
|
Foreground="{DynamicResource MaterialDesignBodyLight}"
|
||||||
|
VerticalAlignment="Center" />
|
||||||
|
|
||||||
|
<Button Grid.Row="0" Grid.RowSpan="2" Grid.Column="2" ToolTip="View properties" Width="20" Height="20" Command="{s:Action ViewProperties}" s:View.ActionTarget="{Binding}" HorizontalAlignment="Right">
|
||||||
|
<Button.Style>
|
||||||
|
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource MaterialDesignIconForegroundButton}">
|
||||||
|
<Setter Property="Visibility" Value="Collapsed" />
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}, Mode=FindAncestor}}" Value="True">
|
||||||
|
<Setter Property="Visibility" Value="Visible" />
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</Button.Style>
|
||||||
|
<materialDesign:PackIcon Kind="Cog" Width="16" Height="16" />
|
||||||
|
</Button>
|
||||||
|
<ToggleButton Grid.Row="0" Grid.RowSpan="2" Grid.Column="3" ToolTip="Suspend profile" Width="18" Height="18" Margin="2 0 0 0" IsChecked="{Binding ScriptConfiguration.IsSuspended}">
|
||||||
|
<ToggleButton.Style>
|
||||||
|
<Style TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource MaterialDesignFlatToggleButton}">
|
||||||
|
<Setter Property="Visibility" Value="Collapsed" />
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}, Mode=FindAncestor}}" Value="True">
|
||||||
|
<Setter Property="Visibility" Value="Visible" />
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</ToggleButton.Style>
|
||||||
|
<materialDesign:PackIcon Kind="Pause" Height="14" Width="14" />
|
||||||
|
</ToggleButton>
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
</DataTemplate>
|
||||||
|
</ListBox.ItemTemplate>
|
||||||
|
</ListBox>
|
||||||
|
|
||||||
|
<Button Grid.Row="1"
|
||||||
|
Style="{StaticResource MaterialDesignOutlinedButton}"
|
||||||
|
Content="ADD NEW SCRIPT"
|
||||||
|
Margin="10 10 10 0"
|
||||||
|
Command="{s:Action AddScriptConfiguration}"
|
||||||
|
VerticalAlignment="Top" />
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<!-- Script editor -->
|
||||||
|
<ContentControl Grid.Column="1" s:View.Model="{Binding ActiveItem.ActiveItem}" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" IsTabStop="False" />
|
||||||
|
</Grid>
|
||||||
|
</materialDesign:DialogHost>
|
||||||
|
</mde:MaterialWindow>
|
||||||
@ -1,24 +1,102 @@
|
|||||||
using Artemis.Core;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Artemis.Core;
|
||||||
|
using Artemis.Core.ScriptingProviders;
|
||||||
|
using Artemis.Core.Services;
|
||||||
|
using Artemis.UI.Ninject.Factories;
|
||||||
|
using Artemis.UI.Screens.Scripting.Dialogs;
|
||||||
|
using Artemis.UI.Shared.Services;
|
||||||
using Stylet;
|
using Stylet;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Scripting
|
namespace Artemis.UI.Screens.Scripting
|
||||||
{
|
{
|
||||||
public class ScriptsDialogViewModel : Conductor<ScriptConfigurationViewModel>.Collection.OneActive
|
public class ScriptsDialogViewModel : Conductor<ScriptConfigurationViewModel>.Collection.OneActive
|
||||||
{
|
{
|
||||||
public ScriptsDialogViewModel(Profile profile)
|
private readonly IScriptingService _scriptingService;
|
||||||
|
private readonly IDialogService _dialogService;
|
||||||
|
private readonly IProfileService _profileService;
|
||||||
|
private readonly IProfileEditorService _profileEditorService;
|
||||||
|
private readonly IScriptVmFactory _scriptVmFactory;
|
||||||
|
public Profile Profile { get; }
|
||||||
|
public Layer Layer { get; }
|
||||||
|
public ILayerProperty LayerProperty { get; }
|
||||||
|
|
||||||
|
public ScriptsDialogViewModel(Profile profile,
|
||||||
|
IScriptingService scriptingService,
|
||||||
|
IDialogService dialogService,
|
||||||
|
IProfileService profileService,
|
||||||
|
IProfileEditorService profileEditorService,
|
||||||
|
IScriptVmFactory scriptVmFactory)
|
||||||
{
|
{
|
||||||
|
_scriptingService = scriptingService;
|
||||||
|
_dialogService = dialogService;
|
||||||
|
_profileService = profileService;
|
||||||
|
_profileEditorService = profileEditorService;
|
||||||
|
_scriptVmFactory = scriptVmFactory;
|
||||||
|
|
||||||
|
DisplayName = "Artemis | Profile Scripts";
|
||||||
|
Profile = profile ?? throw new ArgumentNullException(nameof(profile));
|
||||||
|
|
||||||
|
Items.AddRange(Profile.ScriptConfigurations.Select(scriptVmFactory.ScriptConfigurationViewModel));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ScriptsDialogViewModel(Layer layer)
|
public ScriptsDialogViewModel(Layer layer, IDialogService dialogService)
|
||||||
{
|
{
|
||||||
|
_dialogService = dialogService;
|
||||||
|
DisplayName = "Artemins | Layer Scripts";
|
||||||
|
Layer = layer ?? throw new ArgumentNullException(nameof(layer));
|
||||||
|
|
||||||
|
Items.AddRange(Layer.ScriptConfigurations.Select(_scriptVmFactory.ScriptConfigurationViewModel));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ScriptsDialogViewModel(ILayerProperty layerProperty)
|
public ScriptsDialogViewModel(ILayerProperty layerProperty, IDialogService dialogService)
|
||||||
{
|
{
|
||||||
}
|
_dialogService = dialogService;
|
||||||
}
|
DisplayName = "Artemins | Layer Property Scripts";
|
||||||
|
LayerProperty = layerProperty ?? throw new ArgumentNullException(nameof(layerProperty));
|
||||||
|
|
||||||
public class ScriptConfigurationViewModel : Screen
|
Items.AddRange(Layer.ScriptConfigurations.Select(_scriptVmFactory.ScriptConfigurationViewModel));
|
||||||
{
|
}
|
||||||
|
|
||||||
|
public async Task AddScriptConfiguration()
|
||||||
|
{
|
||||||
|
object result = await _dialogService.ShowDialogAt<ScriptConfigurationCreateViewModel>("ScriptsDialog");
|
||||||
|
if (result is not ScriptConfiguration scriptConfiguration)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (Profile != null)
|
||||||
|
{
|
||||||
|
Profile.ScriptConfigurations.Add(scriptConfiguration);
|
||||||
|
_scriptingService.CreateScriptInstance(Profile, scriptConfiguration);
|
||||||
|
}
|
||||||
|
else if (Layer != null)
|
||||||
|
{
|
||||||
|
Layer.ScriptConfigurations.Add(scriptConfiguration);
|
||||||
|
_scriptingService.CreateScriptInstance(Layer, scriptConfiguration);
|
||||||
|
}
|
||||||
|
else if (LayerProperty != null)
|
||||||
|
{
|
||||||
|
LayerProperty.ScriptConfigurations.Add(scriptConfiguration);
|
||||||
|
_scriptingService.CreateScriptInstance(LayerProperty, scriptConfiguration);
|
||||||
|
}
|
||||||
|
|
||||||
|
Items.Add(_scriptVmFactory.ScriptConfigurationViewModel(scriptConfiguration));
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Overrides of OneActive
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void OnClose()
|
||||||
|
{
|
||||||
|
if (_profileEditorService.SelectedProfile == Profile)
|
||||||
|
_profileEditorService.SaveSelectedProfileConfiguration();
|
||||||
|
else
|
||||||
|
_profileService.SaveProfile(Profile, false);
|
||||||
|
|
||||||
|
base.OnClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -26,13 +26,13 @@ namespace Artemis.UI.Screens.Settings.Debug.Tabs.Performance
|
|||||||
viewModel.Update();
|
viewModel.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FeatureToggled(object? sender, PluginFeatureEventArgs e)
|
private void FeatureToggled(object sender, PluginFeatureEventArgs e)
|
||||||
{
|
{
|
||||||
Items.Clear();
|
Items.Clear();
|
||||||
PopulateItems();
|
PopulateItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PluginToggled(object? sender, PluginEventArgs e)
|
private void PluginToggled(object sender, PluginEventArgs e)
|
||||||
{
|
{
|
||||||
Items.Clear();
|
Items.Clear();
|
||||||
PopulateItems();
|
PopulateItems();
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Timers;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
@ -15,22 +17,24 @@ namespace Artemis.UI.Screens.Settings.Debug.Tabs
|
|||||||
public class RenderDebugViewModel : Screen
|
public class RenderDebugViewModel : Screen
|
||||||
{
|
{
|
||||||
private readonly ICoreService _coreService;
|
private readonly ICoreService _coreService;
|
||||||
|
private readonly Timer _fpsTimer;
|
||||||
private double _currentFps;
|
private double _currentFps;
|
||||||
private ImageSource _currentFrame;
|
private WriteableBitmap _currentFrame;
|
||||||
private int _renderWidth;
|
private int _renderWidth;
|
||||||
private int _renderHeight;
|
private int _renderHeight;
|
||||||
private string _frameTargetPath;
|
private string _frameTargetPath;
|
||||||
private string _renderer;
|
private string _renderer;
|
||||||
private int _frames;
|
private int _frames;
|
||||||
private DateTime _frameCountStart;
|
|
||||||
|
|
||||||
public RenderDebugViewModel(ICoreService coreService)
|
public RenderDebugViewModel(ICoreService coreService)
|
||||||
{
|
{
|
||||||
DisplayName = "RENDERING";
|
DisplayName = "RENDERING";
|
||||||
_coreService = coreService;
|
_coreService = coreService;
|
||||||
|
_fpsTimer = new Timer(1000);
|
||||||
|
_fpsTimer.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ImageSource CurrentFrame
|
public WriteableBitmap CurrentFrame
|
||||||
{
|
{
|
||||||
get => _currentFrame;
|
get => _currentFrame;
|
||||||
set => SetAndNotify(ref _currentFrame, value);
|
set => SetAndNotify(ref _currentFrame, value);
|
||||||
@ -77,19 +81,28 @@ namespace Artemis.UI.Screens.Settings.Debug.Tabs
|
|||||||
protected override void OnActivate()
|
protected override void OnActivate()
|
||||||
{
|
{
|
||||||
_coreService.FrameRendered += CoreServiceOnFrameRendered;
|
_coreService.FrameRendered += CoreServiceOnFrameRendered;
|
||||||
_coreService.FrameRendering += CoreServiceOnFrameRendering;
|
_fpsTimer.Elapsed += FpsTimerOnElapsed;
|
||||||
base.OnActivate();
|
base.OnActivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDeactivate()
|
protected override void OnDeactivate()
|
||||||
{
|
{
|
||||||
_coreService.FrameRendered -= CoreServiceOnFrameRendered;
|
_coreService.FrameRendered -= CoreServiceOnFrameRendered;
|
||||||
_coreService.FrameRendering -= CoreServiceOnFrameRendering;
|
_fpsTimer.Elapsed -= FpsTimerOnElapsed;
|
||||||
base.OnDeactivate();
|
base.OnDeactivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void OnClose()
|
||||||
|
{
|
||||||
|
_fpsTimer.Dispose();
|
||||||
|
base.OnClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void CoreServiceOnFrameRendered(object sender, FrameRenderedEventArgs e)
|
private void CoreServiceOnFrameRendered(object sender, FrameRenderedEventArgs e)
|
||||||
{
|
{
|
||||||
|
_frames++;
|
||||||
|
|
||||||
using SKImage skImage = e.Texture.Surface.Snapshot();
|
using SKImage skImage = e.Texture.Surface.Snapshot();
|
||||||
SKImageInfo bitmapInfo = e.Texture.ImageInfo;
|
SKImageInfo bitmapInfo = e.Texture.ImageInfo;
|
||||||
|
|
||||||
@ -106,42 +119,36 @@ namespace Artemis.UI.Screens.Settings.Debug.Tabs
|
|||||||
_frameTargetPath = null;
|
_frameTargetPath = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RenderHeight = bitmapInfo.Height;
|
||||||
|
RenderWidth = bitmapInfo.Width;
|
||||||
|
|
||||||
Execute.OnUIThreadSync(() =>
|
Execute.OnUIThreadSync(() =>
|
||||||
{
|
{
|
||||||
RenderHeight = bitmapInfo.Height;
|
|
||||||
RenderWidth = bitmapInfo.Width;
|
|
||||||
|
|
||||||
// ReSharper disable twice CompareOfFloatsByEqualityOperator
|
// ReSharper disable twice CompareOfFloatsByEqualityOperator
|
||||||
if (CurrentFrame is not WriteableBitmap writable || writable.Width != bitmapInfo.Width || writable.Height != bitmapInfo.Height)
|
if (CurrentFrame == null || CurrentFrame.Width != bitmapInfo.Width || CurrentFrame.Height != bitmapInfo.Height)
|
||||||
{
|
{
|
||||||
CurrentFrame = e.Texture.Surface.Snapshot().ToWriteableBitmap();
|
CurrentFrame = e.Texture.Surface.Snapshot().ToWriteableBitmap();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
writable.Lock();
|
CurrentFrame.Lock();
|
||||||
using (SKPixmap pixmap = new(bitmapInfo, writable.BackBuffer, writable.BackBufferStride))
|
using (SKPixmap pixmap = new(bitmapInfo, CurrentFrame.BackBuffer, CurrentFrame.BackBufferStride))
|
||||||
{
|
{
|
||||||
// ReSharper disable once AccessToDisposedClosure - Looks fine
|
// ReSharper disable once AccessToDisposedClosure - Looks fine
|
||||||
skImage.ReadPixels(pixmap, 0, 0);
|
skImage.ReadPixels(pixmap, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
writable.AddDirtyRect(new Int32Rect(0, 0, writable.PixelWidth, writable.PixelHeight));
|
CurrentFrame.AddDirtyRect(new Int32Rect(0, 0, CurrentFrame.PixelWidth, CurrentFrame.PixelHeight));
|
||||||
writable.Unlock();
|
CurrentFrame.Unlock();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CoreServiceOnFrameRendering(object sender, FrameRenderingEventArgs e)
|
private void FpsTimerOnElapsed(object sender, ElapsedEventArgs e)
|
||||||
{
|
{
|
||||||
if (DateTime.Now - _frameCountStart >= TimeSpan.FromSeconds(1))
|
CurrentFps = _frames;
|
||||||
{
|
// Renderer = Constants.ManagedGraphicsContext != null ? Constants.ManagedGraphicsContext.GetType().Name : "Software";
|
||||||
CurrentFps = _frames;
|
Renderer = $"HighAccuracyTimers: {Stopwatch.IsHighResolution}";
|
||||||
Renderer = Constants.ManagedGraphicsContext != null ? Constants.ManagedGraphicsContext.GetType().Name : "Software";
|
_frames = 0;
|
||||||
|
|
||||||
_frames = 0;
|
|
||||||
_frameCountStart = DateTime.Now;
|
|
||||||
}
|
|
||||||
|
|
||||||
_frames++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -221,7 +221,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
|
|||||||
Core.Utilities.OpenUrl(uri.ToString());
|
Core.Utilities.OpenUrl(uri.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PluginManagementServiceOnPluginToggled(object? sender, PluginEventArgs e)
|
private void PluginManagementServiceOnPluginToggled(object sender, PluginEventArgs e)
|
||||||
{
|
{
|
||||||
NotifyOfPropertyChange(nameof(IsEnabled));
|
NotifyOfPropertyChange(nameof(IsEnabled));
|
||||||
NotifyOfPropertyChange(nameof(CanOpenSettings));
|
NotifyOfPropertyChange(nameof(CanOpenSettings));
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user