mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
186 lines
5.8 KiB
C#
186 lines
5.8 KiB
C#
using System;
|
|
using System.Linq;
|
|
using Artemis.Core.Internal;
|
|
using Artemis.Storage.Entities.Profile.Abstract;
|
|
using Artemis.Storage.Entities.Profile.Conditions;
|
|
|
|
namespace Artemis.Core
|
|
{
|
|
public class EventCondition : CorePropertyChanged, INodeScriptCondition
|
|
{
|
|
private readonly string _displayName;
|
|
private readonly EventConditionEntity _entity;
|
|
private EventDefaultNode _eventNode;
|
|
private TimeLineEventOverlapMode _eventOverlapMode;
|
|
private DataModelPath? _eventPath;
|
|
private DateTime _lastProcessedTrigger;
|
|
|
|
public EventCondition(ProfileElement profileElement)
|
|
{
|
|
_entity = new EventConditionEntity();
|
|
_displayName = profileElement.GetType().Name;
|
|
|
|
ProfileElement = profileElement;
|
|
Script = new NodeScript<bool>($"Activate {_displayName}", $"Whether or not the event should activate the {_displayName}", profileElement.Profile);
|
|
}
|
|
|
|
internal EventCondition(EventConditionEntity entity, ProfileElement profileElement)
|
|
{
|
|
_entity = entity;
|
|
_displayName = profileElement.GetType().Name;
|
|
|
|
ProfileElement = profileElement;
|
|
Load();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the script that drives the event condition
|
|
/// </summary>
|
|
public NodeScript<bool> Script { get; private set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the path to the event that drives this event condition
|
|
/// </summary>
|
|
public DataModelPath? EventPath
|
|
{
|
|
set => SetAndNotify(ref _eventPath, value);
|
|
get => _eventPath;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Gets or sets how the condition behaves when events trigger before the timeline finishes
|
|
/// </summary>
|
|
public TimeLineEventOverlapMode EventOverlapMode
|
|
{
|
|
get => _eventOverlapMode;
|
|
set => SetAndNotify(ref _eventOverlapMode, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Updates the event node, applying the selected event
|
|
/// </summary>
|
|
public void UpdateEventNode()
|
|
{
|
|
if (EventPath?.GetValue() is not IDataModelEvent dataModelEvent)
|
|
return;
|
|
|
|
if (Script.Nodes.FirstOrDefault(n => n is EventDefaultNode) is EventDefaultNode existing)
|
|
{
|
|
existing.UpdateDataModelEvent(dataModelEvent);
|
|
_eventNode = existing;
|
|
}
|
|
else
|
|
{
|
|
_eventNode = new EventDefaultNode();
|
|
_eventNode.UpdateDataModelEvent(dataModelEvent);
|
|
}
|
|
|
|
if (_eventNode.Pins.Any() && !Script.Nodes.Contains(_eventNode))
|
|
Script.AddNode(_eventNode);
|
|
else
|
|
Script.RemoveNode(_eventNode);
|
|
}
|
|
|
|
private bool Evaluate()
|
|
{
|
|
if (EventPath?.GetValue() is not IDataModelEvent dataModelEvent || dataModelEvent.LastTrigger <= _lastProcessedTrigger)
|
|
return false;
|
|
|
|
_lastProcessedTrigger = dataModelEvent.LastTrigger;
|
|
if (!Script.ExitNodeConnected)
|
|
return true;
|
|
|
|
Script.Run();
|
|
return Script.Result;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public IConditionEntity Entity => _entity;
|
|
|
|
/// <inheritdoc />
|
|
public ProfileElement ProfileElement { get; }
|
|
|
|
/// <inheritdoc />
|
|
public bool IsMet { get; private set; }
|
|
|
|
/// <inheritdoc />
|
|
public void Update()
|
|
{
|
|
if (EventOverlapMode == TimeLineEventOverlapMode.Toggle)
|
|
{
|
|
if (Evaluate())
|
|
IsMet = !IsMet;
|
|
}
|
|
else
|
|
{
|
|
IsMet = Evaluate();
|
|
}
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public void ApplyToTimeline(bool isMet, bool wasMet, Timeline timeline)
|
|
{
|
|
if (!isMet)
|
|
{
|
|
if (EventOverlapMode == TimeLineEventOverlapMode.Toggle)
|
|
timeline.JumpToEnd();
|
|
return;
|
|
}
|
|
|
|
// Event overlap mode doesn't apply in this case
|
|
if (timeline.IsFinished)
|
|
{
|
|
timeline.JumpToStart();
|
|
return;
|
|
}
|
|
|
|
// If the timeline was already running, look at the event overlap mode
|
|
if (EventOverlapMode == TimeLineEventOverlapMode.Restart)
|
|
timeline.JumpToStart();
|
|
else if (EventOverlapMode == TimeLineEventOverlapMode.Copy)
|
|
timeline.AddExtraTimeline();
|
|
else if (EventOverlapMode == TimeLineEventOverlapMode.Toggle && !wasMet)
|
|
timeline.JumpToStart();
|
|
|
|
// The remaining overlap mode is 'ignore' which requires no further action
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public void Dispose()
|
|
{
|
|
Script.Dispose();
|
|
EventPath?.Dispose();
|
|
}
|
|
|
|
#region Storage
|
|
|
|
/// <inheritdoc />
|
|
public void Load()
|
|
{
|
|
EventOverlapMode = (TimeLineEventOverlapMode) _entity.EventOverlapMode;
|
|
Script = new NodeScript<bool>($"Activate {_displayName}", $"Whether or not the event should activate the {_displayName}", _entity.Script, ProfileElement.Profile);
|
|
EventPath = new DataModelPath(_entity.EventPath);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public void Save()
|
|
{
|
|
_entity.EventOverlapMode = (int) EventOverlapMode;
|
|
Script.Save();
|
|
_entity.Script = Script.Entity;
|
|
EventPath?.Save();
|
|
_entity.EventPath = EventPath?.Entity;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public void LoadNodeScript()
|
|
{
|
|
Script.Load();
|
|
UpdateEventNode();
|
|
Script.LoadConnections();
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
} |