diff --git a/src/Artemis.Core/Artemis.Core.csproj.DotSettings b/src/Artemis.Core/Artemis.Core.csproj.DotSettings
index 5a6e7bef3..f99fab4de 100644
--- a/src/Artemis.Core/Artemis.Core.csproj.DotSettings
+++ b/src/Artemis.Core/Artemis.Core.csproj.DotSettings
@@ -38,6 +38,7 @@
True
True
True
+ True
True
True
True
diff --git a/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionEvent.cs b/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionEvent.cs
index dd849741c..0ff661385 100644
--- a/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionEvent.cs
+++ b/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionEvent.cs
@@ -12,6 +12,7 @@ namespace Artemis.Core
{
private bool _disposed;
private bool _reinitializing;
+ private IDataModelEvent? _valueChangedEvent;
///
/// Creates a new instance of the class
@@ -56,8 +57,11 @@ namespace Artemis.Core
if (_disposed)
throw new ObjectDisposedException("DataModelConditionEvent");
- if (EventPath?.GetValue() is not IDataModelEvent dataModelEvent)
+ IDataModelEvent? dataModelEvent = GetDataModelEvent();
+ if (dataModelEvent == null)
return false;
+ dataModelEvent.Update();
+
// Only evaluate to true once every time the event has been triggered since the last evaluation
if (dataModelEvent.LastTrigger <= LastTrigger)
return false;
@@ -86,6 +90,7 @@ namespace Artemis.Core
EventPath?.Dispose();
EventPath = path != null ? new DataModelPath(path) : null;
SubscribeToEventPath();
+ CreateValueChangedEventIfNeeded();
// Remove the old root group that was tied to the old data model
ClearChildren();
@@ -100,6 +105,19 @@ namespace Artemis.Core
{
EventArgumentType = null;
}
+
+ LastTrigger = GetDataModelEvent()?.LastTrigger ?? DateTime.Now;
+ }
+
+ ///
+ /// Returns the this is triggered by
+ ///
+ /// The this is triggered by
+ public IDataModelEvent? GetDataModelEvent()
+ {
+ if (_valueChangedEvent != null)
+ return _valueChangedEvent;
+ return EventPath?.GetValue() as IDataModelEvent;
}
#region IDisposable
@@ -153,14 +171,10 @@ namespace Artemis.Core
if (Entity.EventPath == null)
return;
- // Ensure the list path is valid and points to a list
DataModelPath eventPath = new(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();
+ CreateValueChangedEventIfNeeded();
EventArgumentType = GetEventArgumentType();
// There should only be one child and it should be a group
@@ -174,8 +188,7 @@ namespace Artemis.Core
AddChild(new DataModelConditionGroup(this));
}
- if (EventPath?.GetValue() is IDataModelEvent dataModelEvent)
- LastTrigger = dataModelEvent.LastTrigger;
+ LastTrigger = GetDataModelEvent()?.LastTrigger ?? DateTime.Now;
}
private Type? GetEventArgumentType()
@@ -183,20 +196,14 @@ namespace Artemis.Core
if (EventPath == null || !EventPath.IsValid)
return null;
+ if (_valueChangedEvent != null)
+ return _valueChangedEvent.ArgumentsType;
+
// Cannot rely on EventPath.GetValue() because part of the path might be null
Type eventType = EventPath.GetPropertyType()!;
return eventType.IsGenericType ? eventType.GetGenericArguments()[0] : typeof(DataModelEventArgs);
}
- 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;
@@ -204,6 +211,23 @@ namespace Artemis.Core
EventPath.PathInvalidated += EventPathOnPathInvalidated;
}
+ private void CreateValueChangedEventIfNeeded()
+ {
+ Type? propertyType = EventPath?.GetPropertyType();
+ if (propertyType == null)
+ return;
+
+ if (!typeof(IDataModelEvent).IsAssignableFrom(propertyType))
+ {
+ IDataModelEvent? instance = (IDataModelEvent?) Activator.CreateInstance(typeof(DataModelValueChangedEvent<>).MakeGenericType(propertyType), EventPath);
+ _valueChangedEvent = instance ?? throw new ArtemisCoreException("Failed to create a DataModelValueChangedEvent for a property changed data model event");
+ }
+ else
+ {
+ _valueChangedEvent = null;
+ }
+ }
+
#region Event handlers
private void EventPathOnPathValidated(object? sender, EventArgs e)
diff --git a/src/Artemis.Core/Models/Profile/DataModel/DataModelEvent.cs b/src/Artemis.Core/Models/Profile/DataModel/DataModelEvent.cs
index e4165a125..aeca78a60 100644
--- a/src/Artemis.Core/Models/Profile/DataModel/DataModelEvent.cs
+++ b/src/Artemis.Core/Models/Profile/DataModel/DataModelEvent.cs
@@ -84,6 +84,9 @@ namespace Artemis.Core
[DataModelIgnore]
public Type ArgumentsType => typeof(T);
+ ///
+ public string TriggerPastParticiple => "triggered";
+
///
[DataModelIgnore]
public bool TrackHistory
@@ -113,6 +116,11 @@ namespace Artemis.Core
TriggerCount = 0;
EventArgumentsHistory.Clear();
}
+
+ ///
+ public void Update()
+ {
+ }
}
///
@@ -192,6 +200,9 @@ namespace Artemis.Core
[DataModelIgnore]
public Type ArgumentsType => typeof(DataModelEventArgs);
+ ///
+ public string TriggerPastParticiple => "triggered";
+
///
[DataModelIgnore]
public bool TrackHistory
@@ -221,5 +232,10 @@ namespace Artemis.Core
TriggerCount = 0;
EventArgumentsHistory.Clear();
}
+
+ ///
+ public void Update()
+ {
+ }
}
}
\ 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
index 3e20a9b1c..4a0431155 100644
--- a/src/Artemis.Core/Models/Profile/DataModel/DataModelEventArgs.cs
+++ b/src/Artemis.Core/Models/Profile/DataModel/DataModelEventArgs.cs
@@ -1,4 +1,5 @@
using System;
+using Artemis.Core.DataModelExpansions;
namespace Artemis.Core
{
@@ -10,6 +11,7 @@ namespace Artemis.Core
///
/// Gets the time at which the event with these arguments was triggered
///
+ [DataModelIgnore]
public DateTime TriggerTime { get; internal set; }
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Models/Profile/DataModel/IDataModelEvent.cs b/src/Artemis.Core/Models/Profile/DataModel/IDataModelEvent.cs
index 36b9c3824..954c2b7a6 100644
--- a/src/Artemis.Core/Models/Profile/DataModel/IDataModelEvent.cs
+++ b/src/Artemis.Core/Models/Profile/DataModel/IDataModelEvent.cs
@@ -3,7 +3,10 @@ using System.Collections.Generic;
namespace Artemis.Core
{
- internal interface IDataModelEvent
+ ///
+ /// Represents a data model event that can trigger s.
+ ///
+ public interface IDataModelEvent
{
///
/// Gets the last time the event was triggered
@@ -20,6 +23,11 @@ namespace Artemis.Core
///
Type ArgumentsType { get; }
+ ///
+ /// Gets the past participle for this event shown in the UI
+ ///
+ string TriggerPastParticiple { get; }
+
///
/// Gets or sets a boolean indicating whether the last 20 events should be tracked
/// Note: setting this to will clear the current history
@@ -46,5 +54,11 @@ namespace Artemis.Core
/// Resets the trigger count and history of this data model event
///
void Reset();
+
+ ///
+ /// Updates the event, not required for standard events but included in case your custom event needs to update every
+ /// tick
+ ///
+ void Update();
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Models/Profile/DataModel/ValueChangedEvent/DataModelValueChangedEvent.cs b/src/Artemis.Core/Models/Profile/DataModel/ValueChangedEvent/DataModelValueChangedEvent.cs
new file mode 100644
index 000000000..3a2ee7de8
--- /dev/null
+++ b/src/Artemis.Core/Models/Profile/DataModel/ValueChangedEvent/DataModelValueChangedEvent.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections.Generic;
+
+namespace Artemis.Core
+{
+ internal class DataModelValueChangedEvent : IDataModelEvent
+ {
+ public DataModelValueChangedEvent(DataModelPath path)
+ {
+ Path = path;
+ }
+
+ public DataModelPath Path { get; }
+ public T? LastValue { get; private set; }
+ public T? CurrentValue { get; private set; }
+ public DateTime LastTrigger { get; private set; }
+ public int TriggerCount { get; private set; }
+ public Type ArgumentsType { get; } = typeof(DataModelValueChangedEventArgs);
+ public string TriggerPastParticiple => "changed";
+ public bool TrackHistory { get; set; } = false;
+ public DataModelEventArgs? LastEventArgumentsUntyped { get; private set; }
+ public List EventArgumentsHistoryUntyped { get; } = new();
+
+ public void Update()
+ {
+ object? value = Path.GetValue();
+ if (value != null)
+ CurrentValue = (T?) value;
+ else
+ CurrentValue = default;
+
+ if (!Equals(LastValue, CurrentValue))
+ Trigger();
+
+ LastValue = CurrentValue;
+ }
+
+ public void Reset()
+ {
+ TriggerCount = 0;
+ }
+
+ private void Trigger()
+ {
+ LastEventArgumentsUntyped = new DataModelValueChangedEventArgs(CurrentValue, LastValue);
+ LastTrigger = DateTime.Now;
+ TriggerCount++;
+
+ OnEventTriggered();
+ }
+
+ #region Events
+
+ public event EventHandler? EventTriggered;
+
+ internal virtual void OnEventTriggered()
+ {
+ EventTriggered?.Invoke(this, EventArgs.Empty);
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.Core/Models/Profile/DataModel/ValueChangedEvent/DataModelValueChangedEventArgs.cs b/src/Artemis.Core/Models/Profile/DataModel/ValueChangedEvent/DataModelValueChangedEventArgs.cs
new file mode 100644
index 000000000..f82169770
--- /dev/null
+++ b/src/Artemis.Core/Models/Profile/DataModel/ValueChangedEvent/DataModelValueChangedEventArgs.cs
@@ -0,0 +1,18 @@
+using Artemis.Core.DataModelExpansions;
+
+namespace Artemis.Core
+{
+ internal class DataModelValueChangedEventArgs : DataModelEventArgs
+ {
+ public DataModelValueChangedEventArgs(T? currentValue, T? previousValue)
+ {
+ CurrentValue = currentValue;
+ PreviousValue = previousValue;
+ }
+
+ [DataModelProperty(Description = "The current value of the property")]
+ public T? CurrentValue { get; }
+ [DataModelProperty(Description = "The previous value of the property")]
+ public T? PreviousValue { get; }
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/ProfileEditor/Conditions/DataModelConditionEventView.xaml b/src/Artemis.UI/Screens/ProfileEditor/Conditions/DataModelConditionEventView.xaml
index 8b9a2b81b..0c93f64b5 100644
--- a/src/Artemis.UI/Screens/ProfileEditor/Conditions/DataModelConditionEventView.xaml
+++ b/src/Artemis.UI/Screens/ProfileEditor/Conditions/DataModelConditionEventView.xaml
@@ -56,8 +56,8 @@
- triggered
+ Margin="5 0 0 0" Text="{Binding TriggerPastParticiple}">
+
SetAndNotify(ref _lastTrigger, value);
}
+ public string TriggerPastParticiple
+ {
+ get => _triggerPastParticiple;
+ set => SetAndNotify(ref _triggerPastParticiple, value);
+ }
+
public void Initialize()
{
LeftSideSelectionViewModel = _dataModelUIService.GetDynamicSelectionViewModel(_profileEditorService.GetCurrentModule());
@@ -44,7 +51,10 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
LeftSideSelectionViewModel.LoadEventChildren = false;
IReadOnlyCollection editors = _dataModelUIService.RegisteredDataModelEditors;
- List supportedInputTypes = new() {typeof(DataModelEvent), typeof(DataModelEvent<>)};
+ List supportedInputTypes = editors.Select(e => e.SupportedType).ToList();
+ supportedInputTypes.AddRange(editors.Where(e => e.CompatibleConversionTypes != null).SelectMany(e => e.CompatibleConversionTypes));
+ supportedInputTypes.Add(typeof(DataModelEvent));
+ supportedInputTypes.Add(typeof(DataModelEvent<>));
LeftSideSelectionViewModel.FilterTypes = supportedInputTypes.ToArray();
LeftSideSelectionViewModel.ButtonBrush = new SolidColorBrush(Color.FromRgb(185, 164, 10));
@@ -63,6 +73,7 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
if (DataModelConditionEvent.EventPath == null || !DataModelConditionEvent.EventPath.IsValid)
return;
+ TriggerPastParticiple = DataModelConditionEvent.GetDataModelEvent()?.TriggerPastParticiple;
List viewModels = new();
foreach (DataModelConditionPart childModel in Model.Children)
{
diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs
index 4c4088d79..4d27041d7 100644
--- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs
+++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs
@@ -322,8 +322,6 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
.Where(l => l.LayerPropertyGroup.LayerEffect != null && !SelectedProfileElement.LayerEffects.Contains(l.LayerPropertyGroup.LayerEffect))
.ToList();
Items.RemoveRange(toRemove);
- foreach (LayerPropertyGroupViewModel layerPropertyGroupViewModel in toRemove)
- layerPropertyGroupViewModel.RequestClose();
foreach (BaseLayerEffect layerEffect in SelectedProfileElement.LayerEffects)
{
diff --git a/src/Artemis.UI/Screens/Settings/Device/Tabs/DevicePropertiesTabViewModel.cs b/src/Artemis.UI/Screens/Settings/Device/Tabs/DevicePropertiesTabViewModel.cs
index 59f3ddc57..a03ce103e 100644
--- a/src/Artemis.UI/Screens/Settings/Device/Tabs/DevicePropertiesTabViewModel.cs
+++ b/src/Artemis.UI/Screens/Settings/Device/Tabs/DevicePropertiesTabViewModel.cs
@@ -149,7 +149,7 @@ namespace Artemis.UI.Screens.Settings.Device.Tabs
Device.GreenScale = GreenScale / 100f;
Device.BlueScale = BlueScale / 100f;
_rgbService.SaveDevice(Device);
-
+
_coreService.ModuleRenderingDisabled = false;
}