1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00

Conditions - Move to new paths API (more WIP)

This commit is contained in:
Robert 2020-10-07 23:15:10 +02:00
parent da132fa4e9
commit 9417332a07
7 changed files with 81 additions and 59 deletions

View File

@ -25,6 +25,7 @@ namespace Artemis.Core
PredicateType = predicateType;
Entity = new DataModelConditionListPredicateEntity();
DataModelConditionList = null!;
ApplyParentList();
Initialize();
}
@ -35,6 +36,7 @@ namespace Artemis.Core
Entity = entity;
PredicateType = (ListRightSideType) entity.PredicateType;
DataModelConditionList = null!;
ApplyParentList();
Initialize();
}
@ -49,37 +51,22 @@ namespace Artemis.Core
/// <summary>
/// Gets the operator
/// </summary>
public ConditionOperator Operator { get; private set; }
public ConditionOperator? Operator { get; private set; }
/// <summary>
/// Gets the data model condition list this predicate belongs to
/// </summary>
public DataModelConditionList DataModelConditionList { get; private set; }
/// <summary>
/// Gets the path of the left property in the <see cref="ListType" />
/// </summary>
public string LeftPropertyPath { get; private set; }
public DataModelPath? LeftPath { get; set; }
/// <summary>
/// Gets the currently used instance of the right side data model
/// <para>Note: This is null when using a path inside the list</para>
/// </summary>
public DataModel RightDataModel { get; set; }
/// <summary>
/// Gets the path of the right property in the <see cref="ListType" />
/// </summary>
public string RightPropertyPath { get; private set; }
public DataModelPath? RightPath { get; set; }
/// <summary>
/// Gets the right static value, only used it <see cref="PredicateType" /> is
/// <see cref="ListRightSideType.Static" />
/// </summary>
public object RightStaticValue { get; private set; }
public Func<object, object> LeftSideAccessor { get; set; }
public Func<object, object> RightSideAccessor { get; set; }
public object? RightStaticValue { get; private set; }
/// <summary>
/// Updates the left side of the predicate
@ -92,7 +79,8 @@ namespace Artemis.Core
if (!ListContainsInnerPath(path))
throw new ArtemisCoreException($"List type {DataModelConditionList.ListType.Name} does not contain path {path}");
LeftPropertyPath = path;
LeftPath?.Dispose();
LeftPath = new DataModelPath(new ListPredicateWrapperDataModel(), path);
ValidateOperator();
ValidateRightSide();
@ -110,7 +98,8 @@ namespace Artemis.Core
throw new ArtemisCoreException($"List type {DataModelConditionList.ListType.Name} does not contain path {path}");
PredicateType = ListRightSideType.DynamicList;
RightPropertyPath = path;
RightPath?.Dispose();
RightPath = new DataModelPath(new ListPredicateWrapperDataModel(), path);
CreateExpression();
}
@ -135,8 +124,8 @@ namespace Artemis.Core
}
PredicateType = ListRightSideType.Dynamic;
RightDataModel = dataModel;
RightPropertyPath = path;
RightPath?.Dispose();
RightPath = new DataModelPath(dataModel, path);
CreateExpression();
}
@ -148,7 +137,8 @@ namespace Artemis.Core
public void UpdateRightSideStatic(object staticValue)
{
PredicateType = ListRightSideType.Static;
RightPropertyPath = null;
RightPath?.Dispose();
RightPath = null;
SetStaticValue(staticValue);
CreateExpression();
@ -166,13 +156,18 @@ namespace Artemis.Core
return;
}
if (LeftPropertyPath == null)
// No need to clear compiled expressions, without a left data model they are already null
if (LeftPath == null || !LeftPath.IsValid)
{
Operator = conditionOperator;
return;
}
Type leftType = GetTypeAtInnerPath(LeftPropertyPath);
Type leftType = LeftPath.GetPropertyType()!;
if (!conditionOperator.SupportsType(leftType))
throw new ArtemisCoreException($"Cannot apply operator {conditionOperator.GetType().Name} to this predicate because " +
$"it does not support left side type {leftType.Name}");
if (conditionOperator.SupportsType(leftType))
Operator = conditionOperator;
@ -209,26 +204,30 @@ namespace Artemis.Core
return true;
}
internal override bool EvaluateObject(object target)
{
if (Operator == null || LeftSideAccessor == null || PredicateType != ListRightSideType.Static && RightSideAccessor == null)
if (Operator == null || LeftPath == null || !LeftPath.IsValid)
return false;
// Compare with a static value
if (PredicateType == ListRightSideType.Static)
{
if (!DataModelConditionList.ListType.IsValueType && RightStaticValue == null)
object? leftSideValue = GetListPathValue(LeftPath, target);
if (leftSideValue != null && leftSideValue.GetType().IsValueType && RightStaticValue == null)
return false;
return Operator.Evaluate(LeftSideAccessor(target), RightStaticValue);
return Operator.Evaluate(leftSideValue, RightStaticValue);
}
if (RightPath == null || !RightPath.IsValid)
return false;
// Compare with dynamic values
if (PredicateType == ListRightSideType.Dynamic)
return Operator.Evaluate(LeftSideAccessor(target), RightSideAccessor(RightDataModel));
return Operator.Evaluate(GetListPathValue(LeftPath, target), RightPath.GetValue());
if (PredicateType == ListRightSideType.DynamicList)
return Operator.Evaluate(LeftSideAccessor(target), RightSideAccessor(target));
return Operator.Evaluate(GetListPathValue(LeftPath, target), GetListPathValue(RightPath, target));
return false;
}
@ -444,6 +443,15 @@ namespace Artemis.Core
RightStaticValue = null;
}
private object? GetListPathValue(DataModelPath path, object target)
{
if (!(path.Target is ListPredicateWrapperDataModel wrapper))
throw new ArtemisCoreException("Data model condition list predicate has a path with an invalid target");
wrapper.Value = target;
return path.GetValue();
}
private void CreateDynamicListAccessors()
{
if (LeftPropertyPath == null || RightPropertyPath == null || Operator == null)
@ -515,6 +523,9 @@ namespace Artemis.Core
ConditionOperatorStore.ConditionOperatorAdded -= ConditionOperatorStoreOnConditionOperatorAdded;
ConditionOperatorStore.ConditionOperatorRemoved -= ConditionOperatorStoreOnConditionOperatorRemoved;
LeftPath?.Dispose();
RightPath?.Dispose();
base.Dispose(disposing);
}

View File

@ -0,0 +1,9 @@
using Artemis.Core.DataModelExpansions;
namespace Artemis.Core
{
internal class ListPredicateWrapperDataModel : DataModel
{
public object Value { get; set; }
}
}

View File

@ -21,13 +21,11 @@ namespace Artemis.Core
/// Creates a new instance of the <see cref="DataModelPath" /> class pointing directly to the target
/// </summary>
/// <param name="target">The target at which this path starts</param>
public DataModelPath(object target)
public DataModelPath(DataModel target)
{
Target = target ?? throw new ArgumentNullException(nameof(target));
Path = "";
Entity = new DataModelPathEntity();
if (Target is DataModel dataModel)
DataModelGuid = dataModel.PluginInfo.Guid;
_segments = new LinkedList<DataModelPathSegment>();
@ -41,13 +39,11 @@ namespace Artemis.Core
/// </summary>
/// <param name="target">The target at which this path starts</param>
/// <param name="path">A point-separated path</param>
public DataModelPath(object target, string path)
public DataModelPath(DataModel target, string path)
{
Target = target ?? throw new ArgumentNullException(nameof(target));
Path = path ?? throw new ArgumentNullException(nameof(path));
Entity = new DataModelPathEntity();
if (Target is DataModel dataModel)
DataModelGuid = dataModel.PluginInfo.Guid;
_segments = new LinkedList<DataModelPathSegment>();
@ -56,9 +52,9 @@ namespace Artemis.Core
SubscribeToDataModelStore();
}
internal DataModelPath(object? target, DataModelPathEntity entity)
internal DataModelPath(DataModel? target, DataModelPathEntity entity)
{
Target = target!;
Target = target;
Path = entity.Path;
Entity = entity;
@ -72,14 +68,14 @@ namespace Artemis.Core
/// <summary>
/// Gets the data model at which this path starts
/// </summary>
public object? Target { get; private set; }
public DataModel? Target { get; private set; }
internal DataModelPathEntity Entity { get; }
/// <summary>
/// Gets the data model GUID of the <see cref="Target" /> if it is a <see cref="DataModel" />
/// </summary>
public Guid? DataModelGuid { get; private set; }
public Guid? DataModelGuid => Target?.PluginInfo.Guid;
/// <summary>
/// Gets the point-separated path associated with this <see cref="DataModelPath" />
@ -221,10 +217,9 @@ namespace Artemis.Core
public void Load()
{
Path = Entity.Path;
DataModelGuid = Entity.DataModelGuid;
if (Target == null && Entity.DataModelGuid != null)
Target = DataModelStore.Get(Entity.DataModelGuid.Value);
if (Target == null && Entity.DataModelGuid != null)
Target = DataModelStore.Get(Entity.DataModelGuid.Value)?.DataModel;
}
/// <inheritdoc />
@ -253,7 +248,7 @@ namespace Artemis.Core
private void DataModelStoreOnDataModelAdded(object? sender, DataModelStoreEvent e)
{
if (e.Registration.DataModel.PluginInfo.Guid != DataModelGuid)
if (e.Registration.DataModel.PluginInfo.Guid != Entity.DataModelGuid)
return;
Target = e.Registration.DataModel;
@ -262,7 +257,7 @@ namespace Artemis.Core
private void DataModelStoreOnDataModelRemoved(object? sender, DataModelStoreEvent e)
{
if (e.Registration.DataModel.PluginInfo.Guid != DataModelGuid)
if (e.Registration.DataModel.PluginInfo.Guid != Entity.DataModelGuid)
return;
Target = null;

View File

@ -18,9 +18,9 @@ namespace Artemis.Core
_logger.Warning(
exception,
"Failed to deserialize display condition predicate {left} {operator} {right}",
dataModelConditionPredicate.Entity.LeftPropertyPath,
dataModelConditionPredicate.Entity.LeftPath?.Path,
dataModelConditionPredicate.Entity.OperatorType,
dataModelConditionPredicate.Entity.RightPropertyPath
dataModelConditionPredicate.Entity.RightPath?.Path
);
}

View File

@ -123,13 +123,16 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
public override void Update()
{
Guid listDataModelGuid = DataModelConditionListPredicate.DataModelConditionList.ListDataModel.PluginInfo.Guid;
Guid? listDataModelGuid = DataModelConditionListPredicate.DataModelConditionList.ListPath.DataModelGuid;
if (listDataModelGuid == null)
return;
if (!_isPrimitiveList)
{
LeftSideSelectionViewModel.FilterTypes = _supportedInputTypes.ToArray();
LeftSideSelectionViewModel.ButtonBrush = new SolidColorBrush(Color.FromRgb(71, 108, 188));
LeftSideSelectionViewModel.SelectedPropertyViewModel = LeftSideSelectionViewModel.DataModelViewModel.GetChildByPath(
listDataModelGuid, DataModelConditionListPredicate.LeftPropertyPath
listDataModelGuid.Value, DataModelConditionListPredicate.LeftPropertyPath
);
}
@ -170,7 +173,7 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
else
{
RightSideSelectionViewModel.SelectedPropertyViewModel = RightSideSelectionViewModel.DataModelViewModel.GetChildByPath(
listDataModelGuid, DataModelConditionListPredicate.RightPropertyPath
listDataModelGuid.Value, DataModelConditionListPredicate.RightPropertyPath
);
}
}
@ -236,9 +239,12 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
private DataModelVisualizationViewModel GetListDataModel()
{
DataModelPropertiesViewModel dataModel = _dataModelUIService.GetPluginDataModelVisualization(_profileEditorService.GetCurrentModule(), true);
if (DataModelConditionListPredicate.DataModelConditionList.ListPath.DataModelGuid == null)
return null;
DataModelListViewModel listDataModel = (DataModelListViewModel) dataModel.GetChildByPath(
DataModelConditionListPredicate.DataModelConditionList.ListDataModel.PluginInfo.Guid,
DataModelConditionListPredicate.DataModelConditionList.ListPropertyPath
DataModelConditionListPredicate.DataModelConditionList.ListPath.DataModelGuid.Value,
DataModelConditionListPredicate.DataModelConditionList.ListPath.Path
);
return listDataModel.GetListTypeViewModel(_dataModelUIService);

View File

@ -107,7 +107,7 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
public override void Update()
{
TargetSelectionViewModel.PopulateSelectedPropertyViewModel(DataModelConditionList.ListDataModel, DataModelConditionList.ListPropertyPath);
TargetSelectionViewModel.PopulateSelectedPropertyViewModel(DataModelConditionList.ListPath.Target, DataModelConditionList.ListPath.Path);
NotifyOfPropertyChange(nameof(SelectedListOperator));
// Remove VMs of effects no longer applied on the layer

View File

@ -4,6 +4,7 @@ using System.Linq;
using System.Windows;
using System.Windows.Media;
using Artemis.Core;
using Artemis.Core.DataModelExpansions;
using Artemis.Core.Services;
using Artemis.UI.Screens.ProfileEditor.Conditions.Abstract;
using Artemis.UI.Shared;
@ -117,8 +118,8 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
{
LeftSideSelectionViewModel.FilterTypes = _supportedInputTypes.ToArray();
LeftSideSelectionViewModel.PopulateSelectedPropertyViewModel(
DataModelConditionPredicate.LeftDataModel,
DataModelConditionPredicate.LeftPropertyPath
DataModelConditionPredicate.LeftPath.Target as DataModel,
DataModelConditionPredicate.LeftPath.Path
);
Type leftSideType = LeftSideSelectionViewModel.SelectedPropertyViewModel?.DataModelPath?.GetPropertyType();
@ -147,8 +148,8 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
}
RightSideSelectionViewModel.PopulateSelectedPropertyViewModel(
DataModelConditionPredicate.RightDataModel,
DataModelConditionPredicate.RightPropertyPath
DataModelConditionPredicate.RightPath.Target as DataModel,
DataModelConditionPredicate.RightPath.Path
);
RightSideSelectionViewModel.FilterTypes = new[] {targetType};
}