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

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
}
}