mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Migrations - Added migration to segments
Layout - Fixed rotation not always applying (workaround) Conditions - Added string operators
This commit is contained in:
parent
dab11cb3e7
commit
385a30bec7
@ -34,6 +34,36 @@ namespace Artemis.Core.Models.Profile.Conditions
|
||||
/// </summary>
|
||||
public abstract string Icon { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether this condition operator supports a right side, defaults to true
|
||||
/// </summary>
|
||||
public bool SupportsRightSide { get; protected set; } = true;
|
||||
|
||||
public bool SupportsType(Type type)
|
||||
{
|
||||
if (type == null)
|
||||
return true;
|
||||
return CompatibleTypes.Any(t => t.IsCastableFrom(type));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a binary expression comparing two types
|
||||
/// </summary>
|
||||
/// <param name="leftSide">The parameter on the left side of the expression</param>
|
||||
/// <param name="rightSide">The parameter on the right side of the expression</param>
|
||||
/// <returns></returns>
|
||||
public abstract BinaryExpression CreateExpression(Expression leftSide, Expression rightSide);
|
||||
|
||||
/// <summary>
|
||||
/// Returns an expression that checks the given expression for null
|
||||
/// </summary>
|
||||
/// <param name="expression"></param>
|
||||
/// <returns></returns>
|
||||
protected Expression CreateNullCheckExpression(Expression expression)
|
||||
{
|
||||
return Expression.NotEqual(expression, Expression.Constant(null));
|
||||
}
|
||||
|
||||
internal void Register(PluginInfo pluginInfo, IDataModelService dataModelService)
|
||||
{
|
||||
if (_registered)
|
||||
@ -63,20 +93,5 @@ namespace Artemis.Core.Models.Profile.Conditions
|
||||
// Profile editor service will call Unsubscribe
|
||||
_dataModelService.RemoveConditionOperator(this);
|
||||
}
|
||||
|
||||
public bool SupportsType(Type type)
|
||||
{
|
||||
if (type == null)
|
||||
return true;
|
||||
return CompatibleTypes.Any(t => t.IsCastableFrom(type));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a binary expression comparing two types
|
||||
/// </summary>
|
||||
/// <param name="leftSide">The parameter on the left side of the expression</param>
|
||||
/// <param name="rightSide">The parameter on the right side of the expression</param>
|
||||
/// <returns></returns>
|
||||
public abstract BinaryExpression CreateExpression(Expression leftSide, Expression rightSide);
|
||||
}
|
||||
}
|
||||
@ -304,7 +304,11 @@ namespace Artemis.Core.Models.Profile.Conditions
|
||||
if (leftSideAccessor.Type.IsValueType && RightStaticValue == null)
|
||||
return;
|
||||
|
||||
var rightSideConstant = Expression.Constant(RightStaticValue);
|
||||
// If the right side value is null, the constant type cannot be inferred and must be provided manually
|
||||
var rightSideConstant = RightStaticValue != null
|
||||
? Expression.Constant(RightStaticValue)
|
||||
: Expression.Constant(null, leftSideAccessor.Type);
|
||||
|
||||
var conditionExpression = Operator.CreateExpression(leftSideAccessor, rightSideConstant);
|
||||
|
||||
StaticConditionLambda = Expression.Lambda<Func<DataModel, bool>>(conditionExpression, leftSideParameter);
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Artemis.Core.Models.Profile.Conditions.Operators
|
||||
{
|
||||
public class StringContainsConditionOperator : DisplayConditionOperator
|
||||
{
|
||||
private readonly MethodInfo _toLower;
|
||||
private readonly MethodInfo _contains;
|
||||
|
||||
public StringContainsConditionOperator()
|
||||
{
|
||||
_toLower = typeof(string).GetMethod("ToLower", new Type[] { });
|
||||
_contains = typeof(string).GetMethod("Contains", new[] {typeof(string) });
|
||||
}
|
||||
|
||||
public override IReadOnlyCollection<Type> CompatibleTypes => new List<Type> {typeof(string)};
|
||||
|
||||
public override string Description => "Contains";
|
||||
public override string Icon => "Contain";
|
||||
|
||||
public override BinaryExpression CreateExpression(Expression leftSide, Expression rightSide)
|
||||
{
|
||||
return Expression.Equal(Expression.Call(Expression.Call(leftSide, _toLower), _contains, Expression.Call(rightSide, _toLower)), Expression.Constant(true));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Artemis.Core.Models.Profile.Conditions.Operators
|
||||
{
|
||||
public class StringEndsWithConditionOperator : DisplayConditionOperator
|
||||
{
|
||||
private readonly MethodInfo _toLower;
|
||||
private readonly MethodInfo _endsWith;
|
||||
|
||||
public StringEndsWithConditionOperator()
|
||||
{
|
||||
_toLower = typeof(string).GetMethod("ToLower", new Type[] { });
|
||||
_endsWith = typeof(string).GetMethod("EndsWith", new[] { typeof(string) });
|
||||
}
|
||||
|
||||
public override IReadOnlyCollection<Type> CompatibleTypes => new List<Type> { typeof(string) };
|
||||
|
||||
public override string Description => "Ends with";
|
||||
public override string Icon => "ContainEnd";
|
||||
|
||||
public override BinaryExpression CreateExpression(Expression leftSide, Expression rightSide)
|
||||
{
|
||||
return Expression.Equal(Expression.Call(Expression.Call(leftSide, _toLower), _endsWith, Expression.Call(rightSide, _toLower)), Expression.Constant(true));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Artemis.Core.Models.Profile.Conditions.Operators
|
||||
{
|
||||
public class StringEqualsConditionOperator : DisplayConditionOperator
|
||||
{
|
||||
private readonly MethodInfo _toLower;
|
||||
|
||||
public StringEqualsConditionOperator()
|
||||
{
|
||||
_toLower = typeof(string).GetMethod("ToLower", new Type[] { });
|
||||
}
|
||||
|
||||
public override IReadOnlyCollection<Type> CompatibleTypes => new List<Type> {typeof(string)};
|
||||
|
||||
public override string Description => "Equals";
|
||||
public override string Icon => "Equal";
|
||||
|
||||
public override BinaryExpression CreateExpression(Expression leftSide, Expression rightSide)
|
||||
{
|
||||
return Expression.Equal(Expression.Call(leftSide, _toLower), Expression.Call(rightSide, _toLower));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Artemis.Core.Models.Profile.Conditions.Operators
|
||||
{
|
||||
public class StringNotContainsConditionOperator : DisplayConditionOperator
|
||||
{
|
||||
private readonly MethodInfo _toLower;
|
||||
private readonly MethodInfo _contains;
|
||||
|
||||
public StringNotContainsConditionOperator()
|
||||
{
|
||||
_toLower = typeof(string).GetMethod("ToLower", new Type[] { });
|
||||
_contains = typeof(string).GetMethod("Contains", new[] { typeof(string) });
|
||||
}
|
||||
|
||||
public override IReadOnlyCollection<Type> CompatibleTypes => new List<Type> { typeof(string) };
|
||||
|
||||
public override string Description => "Does not contain";
|
||||
public override string Icon => "FormatStrikethrough";
|
||||
|
||||
public override BinaryExpression CreateExpression(Expression leftSide, Expression rightSide)
|
||||
{
|
||||
return Expression.Equal(Expression.Call(Expression.Call(leftSide, _toLower), _contains, Expression.Call(rightSide, _toLower)), Expression.Constant(false));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Artemis.Core.Models.Profile.Conditions.Operators
|
||||
{
|
||||
public class StringNotEqualConditionOperator : DisplayConditionOperator
|
||||
{
|
||||
private readonly MethodInfo _toLower;
|
||||
|
||||
public StringNotEqualConditionOperator()
|
||||
{
|
||||
_toLower = typeof(string).GetMethod("ToLower", new Type[] { });
|
||||
}
|
||||
|
||||
public override IReadOnlyCollection<Type> CompatibleTypes => new List<Type> {typeof(string)};
|
||||
|
||||
public override string Description => "Does not equal";
|
||||
public override string Icon => "NotEqualVariant";
|
||||
|
||||
public override BinaryExpression CreateExpression(Expression leftSide, Expression rightSide)
|
||||
{
|
||||
return Expression.NotEqual(Expression.Call(leftSide, _toLower), Expression.Call(rightSide, _toLower));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace Artemis.Core.Models.Profile.Conditions.Operators
|
||||
{
|
||||
public class StringNullConditionOperator : DisplayConditionOperator
|
||||
{
|
||||
public StringNullConditionOperator()
|
||||
{
|
||||
SupportsRightSide = false;
|
||||
}
|
||||
|
||||
public override IReadOnlyCollection<Type> CompatibleTypes => new List<Type> {typeof(string)};
|
||||
|
||||
public override string Description => "Is null";
|
||||
public override string Icon => "Null";
|
||||
|
||||
public override BinaryExpression CreateExpression(Expression leftSide, Expression rightSide)
|
||||
{
|
||||
return Expression.Equal(leftSide, Expression.Constant(null, leftSide.Type));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Artemis.Core.Models.Profile.Conditions.Operators
|
||||
{
|
||||
public class StringStartsWithConditionOperator : DisplayConditionOperator
|
||||
{
|
||||
private readonly MethodInfo _toLower;
|
||||
private readonly MethodInfo _startsWith;
|
||||
|
||||
public StringStartsWithConditionOperator()
|
||||
{
|
||||
_toLower = typeof(string).GetMethod("ToLower", new Type[] { });
|
||||
_startsWith = typeof(string).GetMethod("StartsWith", new[] { typeof(string) });
|
||||
}
|
||||
|
||||
public override IReadOnlyCollection<Type> CompatibleTypes => new List<Type> { typeof(string) };
|
||||
|
||||
public override string Description => "Starts with";
|
||||
public override string Icon => "ContainStart";
|
||||
|
||||
public override BinaryExpression CreateExpression(Expression leftSide, Expression rightSide)
|
||||
{
|
||||
return Expression.Equal(Expression.Call(Expression.Call(leftSide, _toLower), _startsWith, Expression.Call(rightSide, _toLower)), Expression.Constant(true));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -134,10 +134,14 @@ namespace Artemis.Core.Models.Surface
|
||||
|
||||
internal void ApplyToRgbDevice()
|
||||
{
|
||||
RgbDevice.Location = new Point(DeviceEntity.X, DeviceEntity.Y);
|
||||
RgbDevice.Rotation = DeviceEntity.Rotation;
|
||||
RgbDevice.Scale = DeviceEntity.Scale;
|
||||
|
||||
// Workaround for device rotation not applying
|
||||
if (DeviceEntity.X == 0 && DeviceEntity.Y == 0)
|
||||
RgbDevice.Location = new Point(1, 1);
|
||||
RgbDevice.Location = new Point(DeviceEntity.X, DeviceEntity.Y);
|
||||
|
||||
CalculateRenderProperties();
|
||||
OnDeviceUpdated();
|
||||
}
|
||||
|
||||
@ -151,7 +151,21 @@ namespace Artemis.Core.Services
|
||||
{
|
||||
if (type == null)
|
||||
return new List<DisplayConditionOperator>(_registeredConditionOperators);
|
||||
return _registeredConditionOperators.Where(c => c.CompatibleTypes.Any(t => t.IsCastableFrom(type))).ToList();
|
||||
|
||||
var candidates = _registeredConditionOperators.Where(c => c.CompatibleTypes.Any(t => t.IsCastableFrom(type))).ToList();
|
||||
|
||||
// If there are multiple operators with the same description, use the closest match
|
||||
foreach (var displayConditionOperators in candidates.GroupBy(c => c.Description).Where(g => g.Count() > 1).ToList())
|
||||
{
|
||||
var bestCandidate = displayConditionOperators.OrderByDescending(c => c.CompatibleTypes.Contains(type)).FirstOrDefault();
|
||||
foreach (var displayConditionOperator in displayConditionOperators)
|
||||
{
|
||||
if (displayConditionOperator != bestCandidate)
|
||||
candidates.Remove(displayConditionOperator);
|
||||
}
|
||||
}
|
||||
|
||||
return candidates;
|
||||
}
|
||||
}
|
||||
|
||||
@ -162,12 +176,24 @@ namespace Artemis.Core.Services
|
||||
|
||||
private void RegisterBuiltInConditionOperators()
|
||||
{
|
||||
// General usage for any type
|
||||
RegisterConditionOperator(Constants.CorePluginInfo, new EqualsConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePluginInfo, new NotEqualConditionOperator());
|
||||
|
||||
// Numeric operators
|
||||
RegisterConditionOperator(Constants.CorePluginInfo, new LessThanConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePluginInfo, new GreaterThanConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePluginInfo, new LessThanOrEqualConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePluginInfo, new GreaterThanOrEqualConditionOperator());
|
||||
|
||||
// String operators
|
||||
RegisterConditionOperator(Constants.CorePluginInfo, new StringEqualsConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePluginInfo, new StringNotEqualConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePluginInfo, new StringContainsConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePluginInfo, new StringNotContainsConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePluginInfo, new StringStartsWithConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePluginInfo, new StringEndsWithConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePluginInfo, new StringNullConditionOperator());
|
||||
}
|
||||
|
||||
private void PluginServiceOnPluginEnabled(object sender, PluginEventArgs e)
|
||||
|
||||
39
src/Artemis.Storage/Migrations/M4ProfileSegments.cs
Normal file
39
src/Artemis.Storage/Migrations/M4ProfileSegments.cs
Normal file
@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using Artemis.Storage.Entities.Profile;
|
||||
using Artemis.Storage.Migrations.Interfaces;
|
||||
using LiteDB;
|
||||
|
||||
namespace Artemis.Storage.Migrations
|
||||
{
|
||||
public class M4ProfileSegmentsMigration : IStorageMigration
|
||||
{
|
||||
public int UserVersion => 4;
|
||||
|
||||
public void Apply(LiteRepository repository)
|
||||
{
|
||||
var profiles = repository.Query<ProfileEntity>().ToList();
|
||||
foreach (var profileEntity in profiles)
|
||||
{
|
||||
foreach (var folder in profileEntity.Folders.Where(f => f.MainSegmentLength == TimeSpan.Zero))
|
||||
{
|
||||
if (folder.PropertyEntities.Any(p => p.KeyframeEntities.Any()))
|
||||
folder.MainSegmentLength = folder.PropertyEntities.Where(p => p.KeyframeEntities.Any()).Max(p => p.KeyframeEntities.Max(k => k.Position));
|
||||
if (folder.MainSegmentLength == TimeSpan.Zero)
|
||||
folder.MainSegmentLength = TimeSpan.FromSeconds(5);
|
||||
}
|
||||
|
||||
foreach (var layer in profileEntity.Layers.Where(l => l.MainSegmentLength == TimeSpan.Zero))
|
||||
{
|
||||
if (layer.PropertyEntities.Any(p => p.KeyframeEntities.Any()))
|
||||
layer.MainSegmentLength = layer.PropertyEntities.Where(p => p.KeyframeEntities.Any()).Max(p => p.KeyframeEntities.Max(k => k.Position));
|
||||
if (layer.MainSegmentLength == TimeSpan.Zero)
|
||||
layer.MainSegmentLength = TimeSpan.FromSeconds(5);
|
||||
}
|
||||
|
||||
repository.Update(profileEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -12,7 +12,7 @@ namespace Artemis.Storage.Repositories
|
||||
internal PluginRepository(LiteRepository repository)
|
||||
{
|
||||
_repository = repository;
|
||||
|
||||
|
||||
_repository.Database.GetCollection<PluginSettingEntity>().EnsureIndex(s => new {s.Name, s.PluginGuid}, true);
|
||||
}
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@ using System.Threading.Tasks;
|
||||
using Artemis.Core.Models.Profile.Conditions;
|
||||
using Artemis.UI.Ninject.Factories;
|
||||
using Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions.Abstract;
|
||||
using Artemis.UI.Shared.Services.Interfaces;
|
||||
using Humanizer;
|
||||
using Stylet;
|
||||
|
||||
@ -11,13 +12,15 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions
|
||||
{
|
||||
public class DisplayConditionGroupViewModel : DisplayConditionViewModel
|
||||
{
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private readonly IDisplayConditionsVmFactory _displayConditionsVmFactory;
|
||||
private bool _isRootGroup;
|
||||
private bool _isInitialized;
|
||||
|
||||
public DisplayConditionGroupViewModel(DisplayConditionGroup displayConditionGroup, DisplayConditionViewModel parent, IDisplayConditionsVmFactory displayConditionsVmFactory) : base(
|
||||
displayConditionGroup, parent)
|
||||
public DisplayConditionGroupViewModel(DisplayConditionGroup displayConditionGroup, DisplayConditionViewModel parent,
|
||||
IProfileEditorService profileEditorService, IDisplayConditionsVmFactory displayConditionsVmFactory) : base(displayConditionGroup, parent)
|
||||
{
|
||||
_profileEditorService = profileEditorService;
|
||||
_displayConditionsVmFactory = displayConditionsVmFactory;
|
||||
Execute.PostToUIThread(async () =>
|
||||
{
|
||||
@ -55,13 +58,17 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions
|
||||
DisplayConditionGroup.AddChild(new DisplayConditionPredicate(DisplayConditionGroup, PredicateType.Static));
|
||||
else if (type == "Dynamic")
|
||||
DisplayConditionGroup.AddChild(new DisplayConditionPredicate(DisplayConditionGroup, PredicateType.Dynamic));
|
||||
|
||||
Update();
|
||||
_profileEditorService.UpdateSelectedProfileElement();
|
||||
}
|
||||
|
||||
public void AddGroup()
|
||||
{
|
||||
DisplayConditionGroup.AddChild(new DisplayConditionGroup(DisplayConditionGroup));
|
||||
|
||||
Update();
|
||||
_profileEditorService.UpdateSelectedProfileElement();
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
|
||||
@ -254,6 +254,7 @@ namespace Artemis.UI.Screens
|
||||
protected override void OnClose()
|
||||
{
|
||||
SidebarViewModel.Dispose();
|
||||
|
||||
|
||||
// Lets force the GC to run after closing the window so it is obvious to users watching task manager
|
||||
// that closing the UI will decrease the memory footprint of the application.
|
||||
|
||||
@ -197,6 +197,9 @@ namespace Artemis.UI.Screens.Sidebar
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
var closeTask = CloseCurrentItem();
|
||||
closeTask.Wait();
|
||||
|
||||
_pluginService.PluginEnabled -= PluginServiceOnPluginEnabled;
|
||||
_pluginService.PluginDisabled -= PluginServiceOnPluginDisabled;
|
||||
}
|
||||
|
||||
@ -38,8 +38,10 @@ namespace Artemis.Plugins.Modules.General
|
||||
public void UpdateCurrentWindow()
|
||||
{
|
||||
var processId = WindowUtilities.GetActiveProcessId();
|
||||
if (DataModel.ActiveWindow == null || DataModel.ActiveWindow.Process.Id != processId)
|
||||
if (DataModel.ActiveWindow == null || DataModel.ActiveWindow.Process.Id != processId)
|
||||
DataModel.ActiveWindow = new WindowDataModel(Process.GetProcessById(processId));
|
||||
if (DataModel.ActiveWindow != null && string.IsNullOrWhiteSpace(DataModel.ActiveWindow.WindowTitle))
|
||||
DataModel.ActiveWindow.WindowTitle = Process.GetProcessById(WindowUtilities.GetActiveProcessId()).MainWindowTitle;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user