diff --git a/src/Artemis.Core/Models/Profile/Conditions/Abstract/ConditionOperator.cs b/src/Artemis.Core/Models/Profile/Conditions/Abstract/ConditionOperator.cs index 416f41912..3011059ea 100644 --- a/src/Artemis.Core/Models/Profile/Conditions/Abstract/ConditionOperator.cs +++ b/src/Artemis.Core/Models/Profile/Conditions/Abstract/ConditionOperator.cs @@ -13,20 +13,30 @@ namespace Artemis.Core /// The parameter on the left side of the expression /// The parameter on the right side of the expression public abstract bool Evaluate(TLeftSide a, TRightSide b); - + /// internal override bool InternalEvaluate(object? leftSideValue, object? rightSideValue) { // TODO: Can we avoid boxing/unboxing? TLeftSide leftSide; if (leftSideValue != null) - leftSide = (TLeftSide) Convert.ChangeType(leftSideValue, typeof(TLeftSide)); + { + if (leftSideValue.GetType() != typeof(TLeftSide)) + leftSide = (TLeftSide) Convert.ChangeType(leftSideValue, typeof(TLeftSide)); + else + leftSide = (TLeftSide) leftSideValue; + } else leftSide = default; TRightSide rightSide; if (rightSideValue != null) - rightSide = (TRightSide) Convert.ChangeType(rightSideValue, typeof(TRightSide)); + { + if (rightSideValue.GetType() != typeof(TRightSide)) + rightSide = (TRightSide) Convert.ChangeType(rightSideValue, typeof(TRightSide)); + else + rightSide = (TRightSide) rightSideValue; + } else rightSide = default; @@ -57,7 +67,12 @@ namespace Artemis.Core // TODO: Can we avoid boxing/unboxing? TLeftSide leftSide; if (leftSideValue != null) - leftSide = (TLeftSide) Convert.ChangeType(leftSideValue, typeof(TLeftSide)); + { + if (leftSideValue.GetType() != typeof(TLeftSide)) + leftSide = (TLeftSide)Convert.ChangeType(leftSideValue, typeof(TLeftSide)); + else + leftSide = (TLeftSide)leftSideValue; + } else leftSide = default; diff --git a/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionEvent.cs b/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionEvent.cs new file mode 100644 index 000000000..be0cf0e81 --- /dev/null +++ b/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionEvent.cs @@ -0,0 +1,189 @@ +using System; +using Artemis.Storage.Entities.Profile.Abstract; +using Artemis.Storage.Entities.Profile.Conditions; + +namespace Artemis.Core +{ + /// + /// A condition that evaluates to true when an event is triggered + /// + public class DataModelConditionEvent : DataModelConditionPart + { + private bool _disposed; + private bool _reinitializing; + private IDataModelEvent? _event; + private bool _eventTriggered; + + /// + /// Creates a new instance of the class + /// + /// + public DataModelConditionEvent(DataModelConditionPart parent) + { + Parent = parent; + Entity = new DataModelConditionEventEntity(); + + Initialize(); + } + + internal DataModelConditionEvent(DataModelConditionPart parent, DataModelConditionEventEntity entity) + { + Parent = parent; + Entity = entity; + + Initialize(); + } + + /// + /// Gets the path of the event property + /// + public DataModelPath? EventPath { get; private set; } + + + internal DataModelConditionEventEntity Entity { get; set; } + + /// + public override bool Evaluate() + { + if (_disposed) + throw new ObjectDisposedException("DataModelConditionEvent"); + + // Ensure the event has not been replaced + if (EventPath?.GetValue() is IDataModelEvent dataModelEvent && _event != dataModelEvent) + SubscribeToDataModelEvent(dataModelEvent); + + // Only evaluate to true once every time the event has been triggered + if (!_eventTriggered) + return false; + + _eventTriggered = false; + return true; + } + + private void SubscribeToDataModelEvent(IDataModelEvent dataModelEvent) + { + if (_event != null) + _event.EventTriggered -= OnEventTriggered; + + _event = dataModelEvent; + if (_event != null) + _event.EventTriggered += OnEventTriggered; + } + + /// + /// Updates the event the condition is triggered by + /// + public void UpdateEvent(DataModelPath? path) + { + if (_disposed) + throw new ObjectDisposedException("DataModelConditionEvent"); + + if (path != null && !path.IsValid) + throw new ArtemisCoreException("Cannot update event to an invalid path"); + + EventPath?.Dispose(); + EventPath = path != null ? new DataModelPath(path) : null; + SubscribeToEventPath(); + } + + #region IDisposable + + /// + protected override void Dispose(bool disposing) + { + _disposed = true; + + EventPath?.Dispose(); + + foreach (DataModelConditionPart child in Children) + child.Dispose(); + + base.Dispose(disposing); + } + + #endregion + + internal override bool EvaluateObject(object target) + { + return false; + } + + internal override void Save() + { + // Don't save an invalid state + if (EventPath != null && !EventPath.IsValid) + return; + + // Target list + EventPath?.Save(); + Entity.EventPath = EventPath?.Entity; + } + + internal override DataModelConditionPartEntity GetEntity() + { + return Entity; + } + + internal void Initialize() + { + if (Entity.EventPath == null) + return; + + // Ensure the list path is valid and points to a list + DataModelPath eventPath = new DataModelPath(null, Entity.EventPath); + // Can't check this on an invalid list, if it becomes valid later lets hope for the best + if (eventPath.IsValid && !PointsToEvent(eventPath)) + return; + + EventPath = eventPath; + SubscribeToEventPath(); + } + + private bool PointsToEvent(DataModelPath dataModelPath) + { + Type? type = dataModelPath.GetPropertyType(); + if (type == null) + return false; + + return typeof(IDataModelEvent).IsAssignableFrom(type); + } + + private void SubscribeToEventPath() + { + if (EventPath == null) return; + EventPath.PathValidated += EventPathOnPathValidated; + EventPath.PathInvalidated += EventPathOnPathInvalidated; + } + + #region Event handlers + + private void OnEventTriggered(object? sender, EventArgs e) + { + _eventTriggered = true; + } + + private void EventPathOnPathValidated(object? sender, EventArgs e) + { + if (_reinitializing) + return; + + _reinitializing = true; + EventPath?.Dispose(); + Initialize(); + _reinitializing = false; + } + + private void EventPathOnPathInvalidated(object? sender, EventArgs e) + { + if (_reinitializing) + return; + + _reinitializing = true; + EventPath?.Dispose(); + Initialize(); + _reinitializing = false; + } + + #endregion + } +} \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionList.cs b/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionList.cs index a3459f385..392e1ba51 100644 --- a/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionList.cs +++ b/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionList.cs @@ -180,7 +180,7 @@ namespace Artemis.Core DataModelPath listPath = new DataModelPath(null, Entity.ListPath); Type listType = listPath.GetPropertyType()!; // Can't check this on an invalid list, if it becomes valid later lets hope for the best - if (listPath.IsValid && !listPath.PointsToList) + if (listPath.IsValid && !PointsToList(listPath)) return; ListPath = listPath; @@ -208,6 +208,12 @@ namespace Artemis.Core } } + private bool PointsToList(DataModelPath dataModelPath) + { + Type? type = dataModelPath.GetPropertyType(); + return type?.IsGenericEnumerable() ?? false; + } + private void SubscribeToListPath() { if (ListPath == null) return; diff --git a/src/Artemis.Core/Models/Profile/DataModel/DataModelEvent.cs b/src/Artemis.Core/Models/Profile/DataModel/DataModelEvent.cs new file mode 100644 index 000000000..79e719881 --- /dev/null +++ b/src/Artemis.Core/Models/Profile/DataModel/DataModelEvent.cs @@ -0,0 +1,85 @@ +using System; +using Artemis.Core.DataModelExpansions; + +namespace Artemis.Core +{ + /// + /// Represents a data model event with event arguments of type + /// + public class DataModelEvent : IDataModelEvent where T : DataModelEventArgs + { + /// + /// Trigger the event with the given + /// + /// The event argument to pass to the event + public void Trigger(T eventArgs) + { + if (eventArgs == null) throw new ArgumentNullException(nameof(eventArgs)); + eventArgs.TriggerTime = DateTime.Now; + + LastEventArguments = eventArgs; + LastTrigger = DateTime.Now; + TriggerCount++; + + OnEventTriggered(); + } + + internal virtual void OnEventTriggered() + { + EventTriggered?.Invoke(this, EventArgs.Empty); + } + + /// + public DateTime LastTrigger { get; private set; } + + /// + public int TriggerCount { get; private set; } + + /// + /// Gets the event arguments of the last time the event was triggered + /// + public T? LastEventArguments { get; private set; } + + /// + [DataModelIgnore] + public Type ArgumentsType => typeof(T); + + /// + public event EventHandler? EventTriggered; + } + + /// + /// Represents a data model event without event arguments + /// + public class DataModelEvent : IDataModelEvent + { + /// + /// Trigger the event + /// + public void Trigger() + { + LastTrigger = DateTime.Now; + TriggerCount++; + + OnEventTriggered(); + } + + internal virtual void OnEventTriggered() + { + EventTriggered?.Invoke(this, EventArgs.Empty); + } + + /// + public DateTime LastTrigger { get; private set; } + + /// + public int TriggerCount { get; private set; } + + /// + [DataModelIgnore] + public Type? ArgumentsType => null; + + /// + public event EventHandler? EventTriggered; + } +} \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/DataModel/DataModelEventArgs.cs b/src/Artemis.Core/Models/Profile/DataModel/DataModelEventArgs.cs new file mode 100644 index 000000000..3e20a9b1c --- /dev/null +++ b/src/Artemis.Core/Models/Profile/DataModel/DataModelEventArgs.cs @@ -0,0 +1,15 @@ +using System; + +namespace Artemis.Core +{ + /// + /// Represents the base class for data model events that contain event data + /// + public class DataModelEventArgs + { + /// + /// Gets the time at which the event with these arguments was triggered + /// + public DateTime TriggerTime { get; internal set; } + } +} \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/DataModel/DataModelPath.cs b/src/Artemis.Core/Models/Profile/DataModel/DataModelPath.cs index 64f62ed68..bd4f0b540 100644 --- a/src/Artemis.Core/Models/Profile/DataModel/DataModelPath.cs +++ b/src/Artemis.Core/Models/Profile/DataModel/DataModelPath.cs @@ -111,18 +111,6 @@ namespace Artemis.Core /// public IReadOnlyCollection Segments => _segments.ToList().AsReadOnly(); - /// - /// Gets a boolean indicating whether this data model path points to a list - /// - public bool PointsToList - { - get - { - Type? type = GetPropertyType(); - return type?.IsGenericEnumerable() ?? false; - } - } - internal DataModelPathEntity Entity { get; } internal Func? Accessor { get; private set; } diff --git a/src/Artemis.Core/Models/Profile/DataModel/IDataModelEvent.cs b/src/Artemis.Core/Models/Profile/DataModel/IDataModelEvent.cs new file mode 100644 index 000000000..c31606967 --- /dev/null +++ b/src/Artemis.Core/Models/Profile/DataModel/IDataModelEvent.cs @@ -0,0 +1,27 @@ +using System; + +namespace Artemis.Core +{ + internal interface IDataModelEvent + { + /// + /// Gets the last time the event was triggered + /// + DateTime LastTrigger { get; } + + /// + /// Gets the amount of times the event was triggered + /// + int TriggerCount { get; } + + /// + /// Gets the type of arguments this event contains + /// + Type? ArgumentsType { get; } + + /// + /// Fires when the event is triggered + /// + event EventHandler EventTriggered; + } +} \ No newline at end of file diff --git a/src/Artemis.Storage/Entities/Profile/Conditions/DataModelConditionEventEntity.cs b/src/Artemis.Storage/Entities/Profile/Conditions/DataModelConditionEventEntity.cs new file mode 100644 index 000000000..cd710f0d5 --- /dev/null +++ b/src/Artemis.Storage/Entities/Profile/Conditions/DataModelConditionEventEntity.cs @@ -0,0 +1,14 @@ +using Artemis.Storage.Entities.Profile.Abstract; + +namespace Artemis.Storage.Entities.Profile.Conditions +{ + public class DataModelConditionEventEntity : DataModelConditionPartEntity + { + public DataModelConditionEventEntity() + { + + } + + public DataModelPathEntity EventPath { get; set; } + } +} \ No newline at end of file diff --git a/src/Artemis.Storage/Entities/Profile/Conditions/DataModelConditionListEntity.cs b/src/Artemis.Storage/Entities/Profile/Conditions/DataModelConditionListEntity.cs index 8c8959ab4..fd812cc41 100644 --- a/src/Artemis.Storage/Entities/Profile/Conditions/DataModelConditionListEntity.cs +++ b/src/Artemis.Storage/Entities/Profile/Conditions/DataModelConditionListEntity.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using Artemis.Storage.Entities.Profile.Abstract; namespace Artemis.Storage.Entities.Profile.Conditions diff --git a/src/Artemis.UI.Shared/Artemis.UI.Shared.csproj.DotSettings b/src/Artemis.UI.Shared/Artemis.UI.Shared.csproj.DotSettings index 6cbf8796d..82d8ff190 100644 --- a/src/Artemis.UI.Shared/Artemis.UI.Shared.csproj.DotSettings +++ b/src/Artemis.UI.Shared/Artemis.UI.Shared.csproj.DotSettings @@ -1,2 +1,14 @@  + True + True + True + True + True + True + True + True + True + True + True + True True \ No newline at end of file diff --git a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelEventViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelEventViewModel.cs new file mode 100644 index 000000000..9e0d64dac --- /dev/null +++ b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelEventViewModel.cs @@ -0,0 +1,33 @@ +using Artemis.Core; +using Artemis.Core.DataModelExpansions; +using Artemis.UI.Shared.Services; + +namespace Artemis.UI.Shared +{ + public class DataModelEventViewModel : DataModelVisualizationViewModel + { + internal DataModelEventViewModel(DataModel dataModel, DataModelVisualizationViewModel parent, DataModelPath dataModelPath) : base(dataModel, parent, dataModelPath) + { + } + + public override void Update(IDataModelUIService dataModelUIService) + { + } + + public override object GetCurrentValue() + { + return null; + } + + /// + public override string ToString() + { + return DisplayPath ?? Path; + } + + internal override int GetChildDepth() + { + return PropertyDescription != null && !PropertyDescription.ResetsDepth ? Depth + 1 : 1; + } + } +} \ No newline at end of file diff --git a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelPropertiesViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelPropertiesViewModel.cs index 0f02e7d16..2a66363ec 100644 --- a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelPropertiesViewModel.cs +++ b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelPropertiesViewModel.cs @@ -7,8 +7,8 @@ namespace Artemis.UI.Shared { public class DataModelPropertiesViewModel : DataModelVisualizationViewModel { - private Type _displayValueType; private object _displayValue; + private Type _displayValueType; internal DataModelPropertiesViewModel(DataModel dataModel, DataModelVisualizationViewModel parent, DataModelPath dataModelPath) : base(dataModel, parent, dataModelPath) { @@ -29,15 +29,15 @@ namespace Artemis.UI.Shared public override void Update(IDataModelUIService dataModelUIService) { DisplayValueType = DataModelPath?.GetPropertyType(); - + // Only set a display value if ToString returns useful information and not just the type name object currentValue = GetCurrentValue(); if (currentValue != null && currentValue.ToString() != currentValue.GetType().ToString()) DisplayValue = currentValue.ToString(); else DisplayValue = null; - - // Always populate properties + + // Always populate properties PopulateProperties(dataModelUIService); // Only update children if the parent is expanded diff --git a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs index 59764842e..292db909f 100644 --- a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs +++ b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs @@ -1,5 +1,4 @@ using System; -using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; @@ -137,7 +136,8 @@ namespace Artemis.UI.Shared if (looseMatch) IsMatchingFilteredTypes = filteredTypes.Any(t => t.IsCastableFrom(type) || t == typeof(Enum) && type.IsEnum || - t == typeof(IEnumerable<>) && type.IsGenericEnumerable()); + t == typeof(IEnumerable<>) && type.IsGenericEnumerable() || + type.IsGenericType && t == type.GetGenericTypeDefinition()); else IsMatchingFilteredTypes = filteredTypes.Any(t => t == type || t == typeof(Enum) && type.IsEnum); } @@ -219,7 +219,6 @@ namespace Artemis.UI.Shared // Add missing dynamic children object value = Parent == null || Parent.IsRootViewModel ? DataModel : DataModelPath.GetValue(); if (value is DataModel dataModel) - { foreach (KeyValuePair kvp in dataModel.DynamicDataModels) { string childPath = AppendToPath(kvp.Key); @@ -230,7 +229,6 @@ namespace Artemis.UI.Shared if (child != null) Children.Add(child); } - } // Remove dynamic children that have been removed from the data model List toRemoveDynamic = Children.Where(c => !c.DataModelPath.IsValid).ToList(); @@ -266,6 +264,8 @@ namespace Artemis.UI.Shared return new DataModelPropertyViewModel(DataModel, this, dataModelPath) {Depth = depth}; if (propertyType.IsGenericEnumerable()) return new DataModelListViewModel(DataModel, this, dataModelPath) {Depth = depth}; + if (propertyType == typeof(DataModelEvent) || propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(DataModelEvent<>)) + return new DataModelEventViewModel(DataModel, this, dataModelPath) { Depth = depth }; // For other value types create a child view model if (propertyType.IsClass || propertyType.IsStruct()) return new DataModelPropertiesViewModel(DataModel, this, dataModelPath) {Depth = depth}; diff --git a/src/Artemis.UI.Shared/ResourceDictionaries/DataModelConditions.xaml b/src/Artemis.UI.Shared/ResourceDictionaries/DataModelConditions.xaml index 0bd2eb41a..f29058c56 100644 --- a/src/Artemis.UI.Shared/ResourceDictionaries/DataModelConditions.xaml +++ b/src/Artemis.UI.Shared/ResourceDictionaries/DataModelConditions.xaml @@ -39,6 +39,12 @@ + + + + + + @@ -73,6 +79,12 @@ + + + + + + diff --git a/src/Artemis.UI/Screens/ProfileEditor/Conditions/DataModelConditionEventViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Conditions/DataModelConditionEventViewModel.cs new file mode 100644 index 000000000..62d7d267e --- /dev/null +++ b/src/Artemis.UI/Screens/ProfileEditor/Conditions/DataModelConditionEventViewModel.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Media; +using Artemis.Core; +using Artemis.UI.Ninject.Factories; +using Artemis.UI.Screens.ProfileEditor.Conditions.Abstract; +using Artemis.UI.Shared; +using Artemis.UI.Shared.Input; +using Artemis.UI.Shared.Services; + +namespace Artemis.UI.Screens.ProfileEditor.Conditions +{ + public class DataModelConditionEventViewModel : DataModelConditionViewModel, IDisposable + { + private readonly IDataModelConditionsVmFactory _dataModelConditionsVmFactory; + private readonly IDataModelUIService _dataModelUIService; + private readonly IProfileEditorService _profileEditorService; + private DataModelDynamicViewModel _targetSelectionViewModel; + + public DataModelConditionEventViewModel(DataModelConditionEvent model, + IProfileEditorService profileEditorService, + IDataModelUIService dataModelUIService, + IDataModelConditionsVmFactory dataModelConditionsVmFactory) : base(model) + { + _profileEditorService = profileEditorService; + _dataModelUIService = dataModelUIService; + _dataModelConditionsVmFactory = dataModelConditionsVmFactory; + + Initialize(); + } + + public DataModelConditionEvent DataModelConditionEvent => (DataModelConditionEvent) Model; + + public DataModelDynamicViewModel TargetSelectionViewModel + { + get => _targetSelectionViewModel; + set => SetAndNotify(ref _targetSelectionViewModel, value); + } + + public void Initialize() + { + TargetSelectionViewModel = _dataModelUIService.GetDynamicSelectionViewModel(_profileEditorService.GetCurrentModule()); + TargetSelectionViewModel.PropertySelected += TargetSelectionViewModelOnPropertySelected; + + IReadOnlyCollection editors = _dataModelUIService.RegisteredDataModelEditors; + List supportedInputTypes = editors.Select(e => e.SupportedType).ToList(); + supportedInputTypes.AddRange(editors.Where(e => e.CompatibleConversionTypes != null).SelectMany(e => e.CompatibleConversionTypes)); + supportedInputTypes.Add(typeof(IEnumerable<>)); + TargetSelectionViewModel.FilterTypes = supportedInputTypes.ToArray(); + + TargetSelectionViewModel.ButtonBrush = new SolidColorBrush(Color.FromRgb(188, 174, 71)); + TargetSelectionViewModel.Placeholder = "Select a list"; + + Update(); + } + + public void ApplyEvent() + { + if (!TargetSelectionViewModel.DataModelPath.GetPropertyType().IsGenericEnumerable()) + { + if (Parent is DataModelConditionGroupViewModel groupViewModel) + groupViewModel.ConvertToPredicate(this); + return; + } + + DataModelConditionEvent.UpdateEvent(TargetSelectionViewModel.DataModelPath); + _profileEditorService.UpdateSelectedProfileElement(); + + Update(); + } + + #region Event handlers + + private void TargetSelectionViewModelOnPropertySelected(object? sender, DataModelInputDynamicEventArgs e) + { + ApplyEvent(); + } + + #endregion + + #region IDisposable + + public void Dispose() + { + TargetSelectionViewModel.Dispose(); + TargetSelectionViewModel.PropertySelected -= TargetSelectionViewModelOnPropertySelected; + } + + #endregion + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/ProfileEditor/Conditions/DataModelConditionGroupViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Conditions/DataModelConditionGroupViewModel.cs index 48dbb28b9..805208232 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Conditions/DataModelConditionGroupViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/Conditions/DataModelConditionGroupViewModel.cs @@ -147,6 +147,24 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions Update(); } + public void ConvertToConditionEvent(DataModelConditionPredicateViewModel predicateViewModel) + { + // Remove the old child + DataModelConditionGroup.RemoveChild(predicateViewModel.Model); + + DataModelConditionPart rootGroup = DataModelConditionGroup; + while (rootGroup.Parent != null) + rootGroup = rootGroup.Parent; + + // Insert an event at the start of the root group + DataModelConditionEvent conditionEvent = new DataModelConditionEvent(rootGroup); + conditionEvent.UpdateEvent(predicateViewModel.LeftSideSelectionViewModel.DataModelPath); + rootGroup.AddChild(conditionEvent, 0); + + // Update to switch the VMs + Update(); + } + public void ConvertToPredicate(DataModelConditionListViewModel listViewModel) { // Store the old index and remove the old predicate diff --git a/src/Artemis.UI/Screens/ProfileEditor/Conditions/DataModelConditionPredicateViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Conditions/DataModelConditionPredicateViewModel.cs index 622efce3c..11c7a36c7 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Conditions/DataModelConditionPredicateViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/Conditions/DataModelConditionPredicateViewModel.cs @@ -97,6 +97,8 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions _supportedInputTypes = editors.Select(e => e.SupportedType).ToList(); _supportedInputTypes.AddRange(editors.Where(e => e.CompatibleConversionTypes != null).SelectMany(e => e.CompatibleConversionTypes)); _supportedInputTypes.Add(typeof(IEnumerable<>)); + _supportedInputTypes.Add(typeof(DataModelEvent)); + _supportedInputTypes.Add(typeof(DataModelEvent<>)); Update(); } @@ -278,7 +280,6 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions Update(); } - private void RightSideInputViewModelOnSwitchToDynamicRequested(object? sender, EventArgs e) { DataModelConditionPredicate.PredicateType = ProfileRightSideType.Dynamic; diff --git a/src/Plugins/Artemis.Plugins.DataModelExpansions.TestData/DataModels/PluginDataModel.cs b/src/Plugins/Artemis.Plugins.DataModelExpansions.TestData/DataModels/PluginDataModel.cs index 28709b186..6bf77b345 100644 --- a/src/Plugins/Artemis.Plugins.DataModelExpansions.TestData/DataModels/PluginDataModel.cs +++ b/src/Plugins/Artemis.Plugins.DataModelExpansions.TestData/DataModels/PluginDataModel.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Artemis.Core; using Artemis.Core.DataModelExpansions; using SkiaSharp; @@ -34,6 +35,22 @@ namespace Artemis.Plugins.DataModelExpansions.TestData.DataModels public bool IsWinning { get; set; } public List ListItems { get; set; } + + [DataModelProperty(Description = "Event without arguments")] + public DataModelEvent Event1 { get; set; } = new DataModelEvent(); + + [DataModelProperty(Description = "Event with arguments")] + public DataModelEvent Event2 { get; set; } = new DataModelEvent(); + } + + public class TestEventArgs : DataModelEventArgs + { + public TestEventArgs(string someValue) + { + SomeValue = someValue; + } + + public string SomeValue { get; set; } } public class Test diff --git a/src/Plugins/Artemis.Plugins.DataModelExpansions.TestData/PluginDataModelExpansion.cs b/src/Plugins/Artemis.Plugins.DataModelExpansions.TestData/PluginDataModelExpansion.cs index 05132e27c..bf04cbf9d 100644 --- a/src/Plugins/Artemis.Plugins.DataModelExpansions.TestData/PluginDataModelExpansion.cs +++ b/src/Plugins/Artemis.Plugins.DataModelExpansions.TestData/PluginDataModelExpansion.cs @@ -23,6 +23,8 @@ namespace Artemis.Plugins.DataModelExpansions.TestData { // You can access your data model here and update it however you like DataModel.TemplateDataModelString = $"The last delta time was {deltaTime} seconds"; + + // DataModel.Event1.Trigger(); } private void TimedUpdate(double deltaTime)