mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-12 13:28:33 +00:00
Profiles - Added IPluginFeatureDependent interface and implement throughout profiles (#842)
* Profiles - Added IPluginFeatureDependent interface and implement througout profiles * Workshop - Include dependencies in profile upload request
This commit is contained in:
parent
28640f9502
commit
e5a5f10286
15
src/Artemis.Core/Models/IPluginFeatureDependent.cs
Normal file
15
src/Artemis.Core/Models/IPluginFeatureDependent.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Artemis.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a class that depends on plugin features
|
||||
/// </summary>
|
||||
public interface IPluginFeatureDependent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the plugin features this class depends on, may contain the same plugin feature twice if depending on it in multiple ways.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="List{T}"/> of <see cref="PluginFeature"/> this class depends on.</returns>
|
||||
public IEnumerable<PluginFeature> GetFeatureDependencies();
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Artemis.Storage.Entities.Profile.Abstract;
|
||||
using Artemis.Storage.Entities.Profile.Conditions;
|
||||
|
||||
@ -82,4 +83,14 @@ public class AlwaysOnCondition : ICondition
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Implementation of IPluginFeatureDependent
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<PluginFeature> GetFeatureDependencies()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@ -325,4 +325,14 @@ public class EventCondition : CorePropertyChanged, INodeScriptCondition
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Implementation of IPluginFeatureDependent
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<PluginFeature> GetFeatureDependencies()
|
||||
{
|
||||
return Script.GetFeatureDependencies().Concat(EventPath?.GetFeatureDependencies() ?? []);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@ -6,7 +6,7 @@ namespace Artemis.Core;
|
||||
/// <summary>
|
||||
/// Represents a condition applied to a <see cref="ProfileElement" />
|
||||
/// </summary>
|
||||
public interface ICondition : IDisposable, IStorageModel
|
||||
public interface ICondition : IDisposable, IStorageModel, IPluginFeatureDependent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the entity used to store this condition
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Artemis.Storage.Entities.Profile.Abstract;
|
||||
using Artemis.Storage.Entities.Profile.Conditions;
|
||||
|
||||
@ -82,4 +83,14 @@ public class PlayOnceCondition : ICondition
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Implementation of IPluginFeatureDependent
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<PluginFeature> GetFeatureDependencies()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Artemis.Storage.Entities.Profile.Abstract;
|
||||
using Artemis.Storage.Entities.Profile.Conditions;
|
||||
@ -159,6 +160,16 @@ public class StaticCondition : CorePropertyChanged, INodeScriptCondition
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Implementation of IPluginFeatureDependent
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<PluginFeature> GetFeatureDependencies()
|
||||
{
|
||||
return Script.GetFeatureDependencies();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -243,4 +243,14 @@ public class DataBinding<TLayerProperty> : IDataBinding
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Implementation of IPluginFeatureDependent
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<PluginFeature> GetFeatureDependencies()
|
||||
{
|
||||
return Script.GetFeatureDependencies();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@ -8,7 +8,7 @@ namespace Artemis.Core;
|
||||
/// Represents a data binding that binds a certain <see cref="LayerProperty{T}" /> to a value inside a
|
||||
/// <see cref="DataModel" />
|
||||
/// </summary>
|
||||
public interface IDataBinding : IStorageModel, IDisposable
|
||||
public interface IDataBinding : IStorageModel, IDisposable, IPluginFeatureDependent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the layer property the data binding is applied to
|
||||
|
||||
@ -11,7 +11,7 @@ namespace Artemis.Core;
|
||||
/// <summary>
|
||||
/// Represents a path that points to a property in data model
|
||||
/// </summary>
|
||||
public class DataModelPath : IStorageModel, IDisposable
|
||||
public class DataModelPath : IStorageModel, IDisposable, IPluginFeatureDependent
|
||||
{
|
||||
private readonly LinkedList<DataModelPathSegment> _segments;
|
||||
private Expression<Func<object, object>>? _accessorLambda;
|
||||
@ -188,6 +188,14 @@ public class DataModelPath : IStorageModel, IDisposable
|
||||
return string.IsNullOrWhiteSpace(Path) ? "this" : Path;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<PluginFeature> GetFeatureDependencies()
|
||||
{
|
||||
if (Target == null)
|
||||
return [];
|
||||
return [Target.Module];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Occurs whenever the path becomes invalid
|
||||
/// </summary>
|
||||
|
||||
@ -179,6 +179,14 @@ public sealed class Folder : RenderProfileElement
|
||||
return $"[Folder] {nameof(Name)}: {Name}, {nameof(Order)}: {Order}";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IEnumerable<PluginFeature> GetFeatureDependencies()
|
||||
{
|
||||
return LayerEffects.SelectMany(e => e.GetFeatureDependencies())
|
||||
.Concat(Children.SelectMany(c => c.GetFeatureDependencies()))
|
||||
.Concat(DisplayCondition.GetFeatureDependencies());
|
||||
}
|
||||
|
||||
#region Rendering
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@ -189,6 +189,16 @@ public sealed class Layer : RenderProfileElement
|
||||
return $"[Layer] {nameof(Name)}: {Name}, {nameof(Order)}: {Order}";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IEnumerable<PluginFeature> GetFeatureDependencies()
|
||||
{
|
||||
return LayerEffects.SelectMany(e => e.GetFeatureDependencies())
|
||||
.Concat(LayerBrush?.GetFeatureDependencies() ?? [])
|
||||
.Concat(General.GetFeatureDependencies())
|
||||
.Concat(Transform.GetFeatureDependencies())
|
||||
.Concat(DisplayCondition.GetFeatureDependencies());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when a property affecting the rendering properties of this layer has been updated
|
||||
/// </summary>
|
||||
@ -768,7 +778,7 @@ public sealed class Layer : RenderProfileElement
|
||||
|
||||
if (!_leds.Remove(led))
|
||||
return;
|
||||
|
||||
|
||||
CalculateRenderProperties();
|
||||
}
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@ namespace Artemis.Core;
|
||||
/// initialize these for you.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public interface ILayerProperty : IStorageModel, IDisposable
|
||||
public interface ILayerProperty : IStorageModel, IDisposable, IPluginFeatureDependent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the description attribute applied to this property
|
||||
|
||||
@ -54,6 +54,12 @@ public class LayerProperty<T> : CorePropertyChanged, ILayerProperty
|
||||
return $"{Path} - {CurrentValue} ({PropertyType})";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<PluginFeature> GetFeatureDependencies()
|
||||
{
|
||||
return DataBinding.GetFeatureDependencies();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases the unmanaged resources used by the object and optionally releases the managed resources.
|
||||
/// </summary>
|
||||
|
||||
@ -15,7 +15,7 @@ namespace Artemis.Core;
|
||||
/// initialize these for you.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public abstract class LayerPropertyGroup : IDisposable
|
||||
public abstract class LayerPropertyGroup : IDisposable, IPluginFeatureDependent
|
||||
{
|
||||
private readonly List<ILayerProperty> _layerProperties;
|
||||
private readonly List<LayerPropertyGroup> _layerPropertyGroups;
|
||||
@ -343,4 +343,14 @@ public abstract class LayerPropertyGroup : IDisposable
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
#region Implementation of IPluginFeatureDependent
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<PluginFeature> GetFeatureDependencies()
|
||||
{
|
||||
return LayerProperties.SelectMany(p => p.GetFeatureDependencies()).Concat(LayerPropertyGroups.SelectMany(g => g.GetFeatureDependencies()));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@ -171,6 +171,12 @@ public sealed class Profile : ProfileElement
|
||||
return $"[Profile] {nameof(Name)}: {Name}";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IEnumerable<PluginFeature> GetFeatureDependencies()
|
||||
{
|
||||
return GetRootFolder().GetFeatureDependencies().Concat(Scripts.Select(c => c.ScriptingProvider));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populates all the LEDs on the elements in this profile
|
||||
/// </summary>
|
||||
|
||||
@ -9,7 +9,7 @@ namespace Artemis.Core;
|
||||
/// <summary>
|
||||
/// Represents an element of a <see cref="Profile" />
|
||||
/// </summary>
|
||||
public abstract class ProfileElement : BreakableModel, IDisposable
|
||||
public abstract class ProfileElement : BreakableModel, IDisposable, IPluginFeatureDependent
|
||||
{
|
||||
internal readonly List<ProfileElement> ChildrenList;
|
||||
private Guid _entityId;
|
||||
@ -122,6 +122,9 @@ public abstract class ProfileElement : BreakableModel, IDisposable
|
||||
return $"{nameof(EntityId)}: {EntityId}, {nameof(Order)}: {Order}, {nameof(Name)}: {Name}";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract IEnumerable<PluginFeature> GetFeatureDependencies();
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when a child was added to the <see cref="Children" /> list
|
||||
/// </summary>
|
||||
|
||||
@ -9,13 +9,13 @@ namespace Artemis.Core;
|
||||
/// <summary>
|
||||
/// Represents the configuration of a profile, contained in a <see cref="ProfileCategory" />
|
||||
/// </summary>
|
||||
public class ProfileConfiguration : BreakableModel, IStorageModel, IDisposable
|
||||
public class ProfileConfiguration : BreakableModel, IStorageModel, IDisposable, IPluginFeatureDependent
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an empty profile.
|
||||
/// </summary>
|
||||
public static readonly ProfileConfiguration Empty = new(ProfileCategory.Empty, "Empty", "Empty");
|
||||
|
||||
|
||||
private ActivationBehaviour _activationBehaviour;
|
||||
private bool _activationConditionMet;
|
||||
private ProfileCategory _category;
|
||||
@ -146,7 +146,7 @@ public class ProfileConfiguration : BreakableModel, IStorageModel, IDisposable
|
||||
get => _activationConditionMet;
|
||||
private set => SetAndNotify(ref _activationConditionMet, value);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the profile of this profile configuration
|
||||
/// </summary>
|
||||
@ -159,8 +159,8 @@ public class ProfileConfiguration : BreakableModel, IStorageModel, IDisposable
|
||||
/// <summary>
|
||||
/// Gets or sets a boolean indicating whether this profile should fade in and out when enabling or disabling
|
||||
/// </summary>
|
||||
public bool FadeInAndOut
|
||||
{
|
||||
public bool FadeInAndOut
|
||||
{
|
||||
get => _fadeInAndOut;
|
||||
set => SetAndNotify(ref _fadeInAndOut, value);
|
||||
}
|
||||
@ -188,7 +188,7 @@ public class ProfileConfiguration : BreakableModel, IStorageModel, IDisposable
|
||||
/// alongside any activation requirements of the <see cref="Module" />, if set
|
||||
/// </summary>
|
||||
public NodeScript<bool> ActivationCondition { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the entity used by this profile config
|
||||
/// </summary>
|
||||
@ -247,6 +247,19 @@ public class ProfileConfiguration : BreakableModel, IStorageModel, IDisposable
|
||||
return $"[ProfileConfiguration] {nameof(Name)}: {Name}";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<PluginFeature> GetFeatureDependencies()
|
||||
{
|
||||
if (_disposed)
|
||||
throw new ObjectDisposedException("ProfileConfiguration");
|
||||
if (Profile == null)
|
||||
throw new InvalidOperationException("Cannot determine feature dependencies when the profile is not loaded.");
|
||||
|
||||
return ActivationCondition.GetFeatureDependencies()
|
||||
.Concat(Profile.GetFeatureDependencies())
|
||||
.Concat(Module != null ? [Module] : []);
|
||||
}
|
||||
|
||||
internal void LoadModules(List<Module> enabledModules)
|
||||
{
|
||||
if (_disposed)
|
||||
|
||||
@ -9,7 +9,7 @@ namespace Artemis.Core.LayerBrushes;
|
||||
/// <summary>
|
||||
/// For internal use only, please use <see cref="LayerBrush{T}" /> or <see cref="PerLedLayerBrush{T}" /> or instead
|
||||
/// </summary>
|
||||
public abstract class BaseLayerBrush : BreakableModel, IDisposable
|
||||
public abstract class BaseLayerBrush : BreakableModel, IDisposable, IPluginFeatureDependent
|
||||
{
|
||||
private LayerBrushType _brushType;
|
||||
private ILayerBrushConfigurationDialog? _configurationDialog;
|
||||
@ -199,6 +199,20 @@ public abstract class BaseLayerBrush : BreakableModel, IDisposable
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
#region Implementation of IPluginFeatureDependent
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<PluginFeature> GetFeatureDependencies()
|
||||
{
|
||||
IEnumerable<PluginFeature> result = [Descriptor.Provider];
|
||||
if (BaseProperties != null)
|
||||
result = result.Concat(BaseProperties.GetFeatureDependencies());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Artemis.Storage.Entities.Profile;
|
||||
using SkiaSharp;
|
||||
|
||||
@ -7,7 +9,7 @@ namespace Artemis.Core.LayerEffects;
|
||||
/// <summary>
|
||||
/// For internal use only, please use <see cref="LayerEffect{T}" /> instead
|
||||
/// </summary>
|
||||
public abstract class BaseLayerEffect : BreakableModel, IDisposable, IStorageModel
|
||||
public abstract class BaseLayerEffect : BreakableModel, IDisposable, IStorageModel, IPluginFeatureDependent
|
||||
{
|
||||
private ILayerEffectConfigurationDialog? _configurationDialog;
|
||||
private LayerEffectDescriptor _descriptor;
|
||||
@ -164,7 +166,7 @@ public abstract class BaseLayerEffect : BreakableModel, IDisposable, IStorageMod
|
||||
// Not only is this needed to initialize properties on the layer effects, it also prevents implementing anything
|
||||
// but LayerEffect<T> outside the core
|
||||
internal abstract void Initialize();
|
||||
|
||||
|
||||
internal void InternalUpdate(Timeline timeline)
|
||||
{
|
||||
BaseProperties?.Update(timeline);
|
||||
@ -235,4 +237,18 @@ public abstract class BaseLayerEffect : BreakableModel, IDisposable, IStorageMod
|
||||
BaseProperties?.ApplyToEntity();
|
||||
LayerEffectEntity.PropertyGroup = BaseProperties?.PropertyGroupEntity;
|
||||
}
|
||||
|
||||
#region Implementation of IPluginFeatureDependent
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<PluginFeature> GetFeatureDependencies()
|
||||
{
|
||||
IEnumerable<PluginFeature> result = [Descriptor.Provider];
|
||||
if (BaseProperties != null)
|
||||
result = result.Concat(BaseProperties.GetFeatureDependencies());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@ -8,7 +8,7 @@ namespace Artemis.Core;
|
||||
/// <summary>
|
||||
/// Represents a kind of node inside a <see cref="INodeScript" />
|
||||
/// </summary>
|
||||
public interface INode : INotifyPropertyChanged, IBreakableModel
|
||||
public interface INode : INotifyPropertyChanged, IBreakableModel, IPluginFeatureDependent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the ID of the node.
|
||||
|
||||
@ -8,7 +8,7 @@ namespace Artemis.Core;
|
||||
/// <summary>
|
||||
/// Represents a node script
|
||||
/// </summary>
|
||||
public interface INodeScript : INotifyPropertyChanged, IDisposable, IStorageModel
|
||||
public interface INodeScript : INotifyPropertyChanged, IDisposable, IStorageModel, IPluginFeatureDependent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the name of the node script.
|
||||
|
||||
@ -401,6 +401,16 @@ public abstract class NodeScript : CorePropertyChanged, INodeScript
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Implementation of IPluginFeatureDependent
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<PluginFeature> GetFeatureDependencies()
|
||||
{
|
||||
return Nodes.SelectMany(n => n.GetFeatureDependencies());
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -3,7 +3,6 @@ using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using Artemis.Core.Events;
|
||||
using DryIoc;
|
||||
|
||||
namespace Artemis.Core;
|
||||
|
||||
@ -404,4 +403,14 @@ public abstract class Node : BreakableModel, INode
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Implementation of IPluginFeatureDependent
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual IEnumerable<PluginFeature> GetFeatureDependencies()
|
||||
{
|
||||
return NodeData == null ? [] : [NodeData.Provider];
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Artemis.Core;
|
||||
using Artemis.UI.Screens.Workshop.SubmissionWizard.Steps.Layout;
|
||||
using Artemis.UI.Screens.Workshop.SubmissionWizard.Steps.Plugin;
|
||||
using Artemis.UI.Screens.Workshop.SubmissionWizard.Steps.Profile;
|
||||
@ -37,7 +38,7 @@ public class SubmissionWizardState : IDisposable
|
||||
public List<ImageUploadRequest> Images { get; set; } = new();
|
||||
|
||||
public IEntrySource? EntrySource { get; set; }
|
||||
|
||||
|
||||
public void ChangeScreen<TSubmissionViewModel>() where TSubmissionViewModel : SubmissionViewModel
|
||||
{
|
||||
try
|
||||
|
||||
@ -65,10 +65,10 @@ public partial class ProfileSelectionStepViewModel : SubmissionViewModel
|
||||
|
||||
private void ExecuteContinue()
|
||||
{
|
||||
if (SelectedProfile == null)
|
||||
if (SelectedProfile?.Profile == null)
|
||||
return;
|
||||
|
||||
State.EntrySource = new ProfileEntrySource(SelectedProfile);
|
||||
State.EntrySource = new ProfileEntrySource(SelectedProfile, SelectedProfile.GetFeatureDependencies().Distinct().ToList());
|
||||
State.Name = SelectedProfile.Name;
|
||||
State.Icon = SelectedProfile.Icon.GetIconStream();
|
||||
|
||||
|
||||
@ -4,10 +4,12 @@ namespace Artemis.WebClient.Workshop.Handlers.UploadHandlers;
|
||||
|
||||
public class ProfileEntrySource : IEntrySource
|
||||
{
|
||||
public ProfileEntrySource(ProfileConfiguration profileConfiguration)
|
||||
public ProfileEntrySource(ProfileConfiguration profileConfiguration, List<PluginFeature> dependencies)
|
||||
{
|
||||
ProfileConfiguration = profileConfiguration;
|
||||
Dependencies = dependencies;
|
||||
}
|
||||
|
||||
public ProfileConfiguration ProfileConfiguration { get; set; }
|
||||
public ProfileConfiguration ProfileConfiguration { get; }
|
||||
public List<PluginFeature> Dependencies { get; }
|
||||
}
|
||||
@ -31,6 +31,7 @@ public class ProfileEntryUploadHandler : IEntryUploadHandler
|
||||
MultipartFormDataContent content = new();
|
||||
StreamContent streamContent = new(archiveStream);
|
||||
streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/zip");
|
||||
content.Add(JsonContent.Create(source.Dependencies.Select(d => new {PluginId = d.Plugin.Guid, FeatureId = d.Id}).ToList()), "ReleaseDependencies");
|
||||
content.Add(streamContent, "file", "file.zip");
|
||||
|
||||
// Submit
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user