mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-11-11 19:36:28 +00:00
Event condition - Simplify to only one event per layer
This commit is contained in:
1 parent
d657e7844e
commit
00125d1478
24 files changed
+350
-617
No files matched your search
@@ -1,35 +1,35 @@
|
||||
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, IDisposable, IStorageModel
|
||||
public class EventCondition : CorePropertyChanged, INodeScriptCondition
|
||||
{
|
||||
private readonly string _displayName;
|
||||
private readonly object? _context;
|
||||
private DateTime _lastProcessedTrigger;
|
||||
private readonly EventConditionEntity _entity;
|
||||
private EventDefaultNode _eventNode;
|
||||
private TimeLineEventOverlapMode _eventOverlapMode;
|
||||
private DataModelPath? _eventPath;
|
||||
private DateTime _lastProcessedTrigger;
|
||||
|
||||
internal EventCondition(string displayName, object? context)
|
||||
public EventCondition(ProfileElement profileElement)
|
||||
{
|
||||
_displayName = displayName;
|
||||
_context = context;
|
||||
_entity = new EventConditionEntity();
|
||||
_displayName = profileElement.GetType().Name;
|
||||
|
||||
Entity = new EventConditionEntity();
|
||||
Script = new NodeScript<bool>($"Activate {displayName}", $"Whether or not the event should activate the {displayName}", context);
|
||||
UpdateEventNode();
|
||||
ProfileElement = profileElement;
|
||||
Script = new NodeScript<bool>($"Activate {_displayName}", $"Whether or not the event should activate the {_displayName}", profileElement.Profile);
|
||||
}
|
||||
|
||||
internal EventCondition(EventConditionEntity entity, string displayName, object? context)
|
||||
internal EventCondition(EventConditionEntity entity, ProfileElement profileElement)
|
||||
{
|
||||
_displayName = displayName;
|
||||
_context = context;
|
||||
|
||||
Entity = entity;
|
||||
Script = null!;
|
||||
_entity = entity;
|
||||
_displayName = profileElement.GetType().Name;
|
||||
|
||||
ProfileElement = profileElement;
|
||||
Load();
|
||||
}
|
||||
|
||||
@@ -47,22 +47,104 @@ namespace Artemis.Core
|
||||
get => _eventPath;
|
||||
}
|
||||
|
||||
internal EventConditionEntity Entity { get; }
|
||||
|
||||
internal bool Evaluate()
|
||||
/// <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;
|
||||
|
||||
// TODO: Place dataModelEvent.LastEventArgumentsUntyped; in the start node
|
||||
Script.Run();
|
||||
|
||||
_lastProcessedTrigger = dataModelEvent.LastTrigger;
|
||||
if (!Script.ExitNodeConnected)
|
||||
return true;
|
||||
|
||||
Script.Run();
|
||||
return Script.Result;
|
||||
}
|
||||
|
||||
#region IDisposable
|
||||
/// <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()
|
||||
@@ -71,49 +153,32 @@ namespace Artemis.Core
|
||||
EventPath?.Dispose();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
internal void LoadNodeScript()
|
||||
{
|
||||
Script.Load();
|
||||
UpdateEventNode();
|
||||
}
|
||||
|
||||
/// <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 EventStartNode) is EventStartNode existing)
|
||||
existing.UpdateDataModelEvent(dataModelEvent);
|
||||
else
|
||||
{
|
||||
EventStartNode node = new();
|
||||
node.UpdateDataModelEvent(dataModelEvent);
|
||||
Script.AddNode(node);
|
||||
}
|
||||
}
|
||||
|
||||
#region Implementation of IStorageModel
|
||||
#region Storage
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Load()
|
||||
{
|
||||
EventPath = new DataModelPath(null, Entity.EventPath);
|
||||
Script = new NodeScript<bool>($"Activate {_displayName}", $"Whether or not the event should activate the {_displayName}", Entity.Script, _context);
|
||||
UpdateEventNode();
|
||||
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()
|
||||
{
|
||||
EventPath?.Save();
|
||||
Entity.EventPath = EventPath?.Entity;
|
||||
_entity.EventOverlapMode = (int) EventOverlapMode;
|
||||
Script.Save();
|
||||
Entity.Script = Script.Entity;
|
||||
_entity.Script = Script.Entity;
|
||||
EventPath?.Save();
|
||||
_entity.EventPath = EventPath?.Entity;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void LoadNodeScript()
|
||||
{
|
||||
Script.Load();
|
||||
UpdateEventNode();
|
||||
Script.LoadConnections();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -1,175 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using Artemis.Storage.Entities.Profile.Abstract;
|
||||
using Artemis.Storage.Entities.Profile.Conditions;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
public class EventsCondition : CorePropertyChanged, INodeScriptCondition
|
||||
{
|
||||
private readonly EventsConditionEntity _entity;
|
||||
private readonly List<EventCondition> _eventsList;
|
||||
private TimeLineEventOverlapMode _eventOverlapMode;
|
||||
|
||||
public EventsCondition(ProfileElement profileElement)
|
||||
{
|
||||
_entity = new EventsConditionEntity();
|
||||
_eventsList = new List<EventCondition>();
|
||||
|
||||
ProfileElement = profileElement;
|
||||
Events = new ReadOnlyCollection<EventCondition>(_eventsList);
|
||||
}
|
||||
|
||||
internal EventsCondition(EventsConditionEntity entity, ProfileElement profileElement)
|
||||
{
|
||||
_entity = entity;
|
||||
_eventsList = new List<EventCondition>();
|
||||
|
||||
ProfileElement = profileElement;
|
||||
Events = new ReadOnlyCollection<EventCondition>(_eventsList);
|
||||
|
||||
Load();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of events this condition reacts to
|
||||
/// </summary>
|
||||
public IReadOnlyCollection<EventCondition> Events { get; }
|
||||
|
||||
/// <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);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IConditionEntity Entity => _entity;
|
||||
|
||||
/// <inheritdoc />
|
||||
public ProfileElement ProfileElement { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsMet { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new event condition
|
||||
/// </summary>
|
||||
/// <returns>The newly created event condition</returns>
|
||||
public EventCondition AddEventCondition()
|
||||
{
|
||||
EventCondition eventCondition = new(ProfileElement.GetType().Name.ToLower(), ProfileElement.Profile);
|
||||
lock (_eventsList)
|
||||
{
|
||||
_eventsList.Add(eventCondition);
|
||||
}
|
||||
|
||||
return eventCondition;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the provided event condition
|
||||
/// </summary>
|
||||
/// <param name="eventCondition">The event condition to remove</param>
|
||||
public void RemoveEventCondition(EventCondition eventCondition)
|
||||
{
|
||||
lock (_eventsList)
|
||||
{
|
||||
_eventsList.Remove(eventCondition);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Update()
|
||||
{
|
||||
lock (_eventsList)
|
||||
{
|
||||
if (EventOverlapMode == TimeLineEventOverlapMode.Toggle)
|
||||
{
|
||||
if (_eventsList.Any(c => c.Evaluate()))
|
||||
IsMet = !IsMet;
|
||||
}
|
||||
else
|
||||
{
|
||||
IsMet = _eventsList.Any(c => c.Evaluate());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ApplyToTimeline(bool isMet, bool wasMet, Timeline timeline)
|
||||
{
|
||||
if (!isMet)
|
||||
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()
|
||||
{
|
||||
foreach (EventCondition eventCondition in Events)
|
||||
eventCondition.Dispose();
|
||||
}
|
||||
|
||||
#region Storage
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Load()
|
||||
{
|
||||
EventOverlapMode = (TimeLineEventOverlapMode) _entity.EventOverlapMode;
|
||||
lock (_eventsList)
|
||||
{
|
||||
_eventsList.Clear();
|
||||
foreach (EventConditionEntity eventCondition in _entity.Events)
|
||||
_eventsList.Add(new EventCondition(eventCondition, ProfileElement.GetType().Name.ToLower(), ProfileElement.Profile));
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Save()
|
||||
{
|
||||
_entity.EventOverlapMode = (int) EventOverlapMode;
|
||||
_entity.Events.Clear();
|
||||
lock (_eventsList)
|
||||
{
|
||||
foreach (EventCondition eventCondition in _eventsList)
|
||||
{
|
||||
eventCondition.Save();
|
||||
_entity.Events.Add(eventCondition.Entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void LoadNodeScript()
|
||||
{
|
||||
lock (_eventsList)
|
||||
{
|
||||
foreach (EventCondition eventCondition in _eventsList)
|
||||
eventCondition.LoadNodeScript();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Artemis.Storage.Entities.Profile.Abstract;
|
||||
using Artemis.Storage.Entities.Profile.Abstract;
|
||||
using Artemis.Storage.Entities.Profile.Conditions;
|
||||
|
||||
namespace Artemis.Core
|
||||
@@ -8,19 +6,21 @@ namespace Artemis.Core
|
||||
public class StaticCondition : CorePropertyChanged, INodeScriptCondition
|
||||
{
|
||||
private readonly StaticConditionEntity _entity;
|
||||
private readonly string _displayName;
|
||||
|
||||
public StaticCondition(ProfileElement profileElement)
|
||||
{
|
||||
_entity = new StaticConditionEntity();
|
||||
|
||||
_displayName = profileElement.GetType().Name;
|
||||
|
||||
ProfileElement = profileElement;
|
||||
string typeDisplayName = profileElement.GetType().Name.ToLower();
|
||||
Script = new NodeScript<bool>($"Activate {typeDisplayName}", $"Whether or not this {typeDisplayName} should be active", profileElement.Profile);
|
||||
Script = new NodeScript<bool>($"Activate {_displayName}", $"Whether or not this {_displayName} should be active", profileElement.Profile);
|
||||
}
|
||||
|
||||
internal StaticCondition(StaticConditionEntity entity, ProfileElement profileElement)
|
||||
{
|
||||
_entity = entity;
|
||||
_displayName = profileElement.GetType().Name;
|
||||
|
||||
ProfileElement = profileElement;
|
||||
Script = null!;
|
||||
@@ -45,7 +45,7 @@ namespace Artemis.Core
|
||||
/// <inheritdoc />
|
||||
public void Update()
|
||||
{
|
||||
if (!Script.HasNodes)
|
||||
if (!Script.ExitNodeConnected)
|
||||
{
|
||||
IsMet = true;
|
||||
return;
|
||||
@@ -64,23 +64,18 @@ namespace Artemis.Core
|
||||
timeline.JumpToEndSegment();
|
||||
}
|
||||
|
||||
#region IDisposable
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
Script.Dispose();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Storage
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Load()
|
||||
{
|
||||
string typeDisplayName = ProfileElement.GetType().Name.ToLower();
|
||||
Script = new NodeScript<bool>($"Activate {typeDisplayName}", $"Whether or not this {typeDisplayName} should be active", _entity.Script, ProfileElement.Profile);
|
||||
Script = new NodeScript<bool>($"Activate {_displayName}", $"Whether or not this {_displayName} should be active", _entity.Script, ProfileElement.Profile);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -12,13 +12,14 @@ namespace Artemis.Core
|
||||
private readonly List<IDataBindingProperty> _properties = new();
|
||||
private bool _disposed;
|
||||
private bool _isEnabled;
|
||||
private DataBindingNodeScript<TLayerProperty> _script;
|
||||
|
||||
internal DataBinding(LayerProperty<TLayerProperty> layerProperty)
|
||||
{
|
||||
LayerProperty = layerProperty;
|
||||
|
||||
Entity = new DataBindingEntity();
|
||||
Script = new DataBindingNodeScript<TLayerProperty>(GetScriptName(), "The value to put into the data binding", this, LayerProperty.ProfileElement.Profile);
|
||||
_script = new DataBindingNodeScript<TLayerProperty>(GetScriptName(), "The value to put into the data binding", this, LayerProperty.ProfileElement.Profile);
|
||||
|
||||
Save();
|
||||
}
|
||||
@@ -28,7 +29,7 @@ namespace Artemis.Core
|
||||
LayerProperty = layerProperty;
|
||||
|
||||
Entity = entity;
|
||||
Script = new DataBindingNodeScript<TLayerProperty>(GetScriptName(), "The value to put into the data binding", this, LayerProperty.ProfileElement.Profile);
|
||||
_script = new DataBindingNodeScript<TLayerProperty>(GetScriptName(), "The value to put into the data binding", this, LayerProperty.ProfileElement.Profile);
|
||||
|
||||
// Load will add children so be initialized before that
|
||||
Load();
|
||||
@@ -42,7 +43,7 @@ namespace Artemis.Core
|
||||
/// <summary>
|
||||
/// Gets the script used to populate the data binding
|
||||
/// </summary>
|
||||
public DataBindingNodeScript<TLayerProperty> Script { get; private set; }
|
||||
public INodeScript Script => _script;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the data binding entity this data binding uses for persistent storage
|
||||
@@ -183,7 +184,7 @@ namespace Artemis.Core
|
||||
if (!IsEnabled)
|
||||
return;
|
||||
|
||||
Script.DataBindingExitNode.ApplyToDataBinding();
|
||||
_script.DataBindingExitNode.ApplyToDataBinding();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -220,8 +221,8 @@ namespace Artemis.Core
|
||||
/// <inheritdoc />
|
||||
public void LoadNodeScript()
|
||||
{
|
||||
Script.Dispose();
|
||||
Script = Entity.NodeScript != null
|
||||
_script.Dispose();
|
||||
_script = Entity.NodeScript != null
|
||||
? new DataBindingNodeScript<TLayerProperty>(GetScriptName(), "The value to put into the data binding", this, Entity.NodeScript, LayerProperty.ProfileElement.Profile)
|
||||
: new DataBindingNodeScript<TLayerProperty>(GetScriptName(), "The value to put into the data binding", this, LayerProperty.ProfileElement.Profile);
|
||||
}
|
||||
@@ -232,9 +233,9 @@ namespace Artemis.Core
|
||||
if (_disposed)
|
||||
throw new ObjectDisposedException("DataBinding");
|
||||
|
||||
Script.Save();
|
||||
_script.Save();
|
||||
Entity.IsEnabled = IsEnabled;
|
||||
Entity.NodeScript = Script.Entity.Nodes.Any() ? Script.Entity : null;
|
||||
Entity.NodeScript = _script.Entity.Nodes.Any() ? _script.Entity : null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -75,11 +75,9 @@ namespace Artemis.Core
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="DataModelPath" /> class based on a <see cref="DataModelPathEntity" />
|
||||
/// </summary>
|
||||
/// <param name="target"></param>
|
||||
/// <param name="entity"></param>
|
||||
public DataModelPath(DataModel? target, DataModelPathEntity entity)
|
||||
public DataModelPath(DataModelPathEntity entity)
|
||||
{
|
||||
Target = target;
|
||||
Path = entity.Path;
|
||||
Entity = entity;
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ using Artemis.Core.LayerEffects.Placeholder;
|
||||
using Artemis.Core.Properties;
|
||||
using Artemis.Storage.Entities.Profile;
|
||||
using Artemis.Storage.Entities.Profile.Abstract;
|
||||
using Artemis.Storage.Entities.Profile.Conditions;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Artemis.Core
|
||||
@@ -72,6 +73,13 @@ namespace Artemis.Core
|
||||
? new Timeline(RenderElementEntity.Timeline)
|
||||
: new Timeline();
|
||||
|
||||
DisplayCondition = RenderElementEntity.DisplayCondition switch
|
||||
{
|
||||
StaticConditionEntity staticConditionEntity => new StaticCondition(staticConditionEntity, this),
|
||||
EventConditionEntity eventConditionEntity => new EventCondition(eventConditionEntity, this),
|
||||
_ => DisplayCondition
|
||||
};
|
||||
|
||||
ActivateEffects();
|
||||
}
|
||||
|
||||
@@ -130,10 +138,10 @@ namespace Artemis.Core
|
||||
/// </summary>
|
||||
public void UpdateTimeline(double deltaTime)
|
||||
{
|
||||
// TODO: Move to conditions
|
||||
|
||||
// The play mode dictates whether to stick to the main segment unless the display conditions contains events
|
||||
bool stickToMainSegment = (Timeline.PlayMode == TimelinePlayMode.Repeat || Timeline.EventOverlapMode == TimeLineEventOverlapMode.Toggle) && DisplayConditionMet;
|
||||
// if (DisplayCondition != null && DisplayCondition.ContainsEvents && Timeline.EventOverlapMode != TimeLineEventOverlapMode.Toggle)
|
||||
// stickToMainSegment = false;
|
||||
bool stickToMainSegment = Timeline.PlayMode == TimelinePlayMode.Repeat && DisplayConditionMet;
|
||||
|
||||
Timeline.Update(TimeSpan.FromSeconds(deltaTime), stickToMainSegment);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Artemis.Core
|
||||
public class Timeline : CorePropertyChanged, IStorageModel
|
||||
{
|
||||
private const int MaxExtraTimelines = 15;
|
||||
private readonly object _lock = new ();
|
||||
private readonly object _lock = new();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="Timeline" /> class
|
||||
@@ -24,7 +24,7 @@ namespace Artemis.Core
|
||||
MainSegmentLength = TimeSpan.FromSeconds(5);
|
||||
|
||||
_extraTimelines = new List<Timeline>();
|
||||
ExtraTimelines = new(_extraTimelines);
|
||||
ExtraTimelines = new ReadOnlyCollection<Timeline>(_extraTimelines);
|
||||
|
||||
Save();
|
||||
}
|
||||
@@ -33,7 +33,7 @@ namespace Artemis.Core
|
||||
{
|
||||
Entity = entity;
|
||||
_extraTimelines = new List<Timeline>();
|
||||
ExtraTimelines = new(_extraTimelines);
|
||||
ExtraTimelines = new ReadOnlyCollection<Timeline>(_extraTimelines);
|
||||
|
||||
Load();
|
||||
}
|
||||
@@ -47,7 +47,7 @@ namespace Artemis.Core
|
||||
EndSegmentLength = Parent.EndSegmentLength;
|
||||
|
||||
_extraTimelines = new List<Timeline>();
|
||||
ExtraTimelines = new(_extraTimelines);
|
||||
ExtraTimelines = new ReadOnlyCollection<Timeline>(_extraTimelines);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -139,17 +139,7 @@ namespace Artemis.Core
|
||||
get => _stopMode;
|
||||
set => SetAndNotify(ref _stopMode, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the mode in which the render element responds to display condition events being fired before the
|
||||
/// timeline finished
|
||||
/// </summary>
|
||||
public TimeLineEventOverlapMode EventOverlapMode
|
||||
{
|
||||
get => _eventOverlapMode;
|
||||
set => SetAndNotify(ref _eventOverlapMode, value);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of extra copies of the timeline applied to this timeline
|
||||
/// </summary>
|
||||
@@ -326,7 +316,7 @@ namespace Artemis.Core
|
||||
|
||||
IsOverridden = false;
|
||||
_lastOverridePosition = Position;
|
||||
|
||||
|
||||
if (stickToMainSegment && Position > MainSegmentEndPosition)
|
||||
{
|
||||
// If the main segment has no length, simply stick to the start of the segment
|
||||
@@ -445,7 +435,8 @@ namespace Artemis.Core
|
||||
EndSegmentLength = Entity.EndSegmentLength;
|
||||
PlayMode = (TimelinePlayMode) Entity.PlayMode;
|
||||
StopMode = (TimelineStopMode) Entity.StopMode;
|
||||
EventOverlapMode = (TimeLineEventOverlapMode) Entity.EventOverlapMode;
|
||||
|
||||
JumpToEnd();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -456,7 +447,6 @@ namespace Artemis.Core
|
||||
Entity.EndSegmentLength = EndSegmentLength;
|
||||
Entity.PlayMode = (int) PlayMode;
|
||||
Entity.StopMode = (int) StopMode;
|
||||
Entity.EventOverlapMode = (int) EventOverlapMode;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -171,7 +171,7 @@ namespace Artemis.Core
|
||||
if (_disposed)
|
||||
throw new ObjectDisposedException("ProfileConfiguration");
|
||||
|
||||
if (!ActivationCondition.HasNodes)
|
||||
if (!ActivationCondition.ExitNodeConnected)
|
||||
ActivationConditionMet = true;
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Artemis.Core.Internal;
|
||||
using Artemis.Storage.Entities.Profile.Nodes;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
public class DataBindingNodeScript<TLayerProperty> : NodeScript
|
||||
internal class DataBindingNodeScript<TLayerProperty> : NodeScript
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
internal DataBindingExitNode<TLayerProperty> DataBindingExitNode { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool ExitNodeConnected => DataBindingExitNode.Pins.Any(p => p.ConnectedTo.Any());
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Type ResultType => typeof(object);
|
||||
|
||||
|
||||
@@ -9,8 +9,7 @@ namespace Artemis.Core
|
||||
{
|
||||
string Name { get; }
|
||||
string Description { get; }
|
||||
bool HasNodes { get; }
|
||||
|
||||
|
||||
IEnumerable<INode> Nodes { get; }
|
||||
|
||||
Type ResultType { get; }
|
||||
|
||||
+8
-9
@@ -1,20 +1,23 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Artemis.Core.Modules;
|
||||
using Humanizer;
|
||||
|
||||
namespace Artemis.Core.Internal
|
||||
{
|
||||
internal class EventStartNode : Node
|
||||
internal class EventDefaultNode : Node
|
||||
{
|
||||
private IDataModelEvent? _dataModelEvent;
|
||||
private readonly Dictionary<PropertyInfo, OutputPin> _propertyPins;
|
||||
private IDataModelEvent? _dataModelEvent;
|
||||
|
||||
public EventStartNode() : base("Event Arguments", "Contains the event arguments that triggered the evaluation")
|
||||
public EventDefaultNode() : base("Event Arguments", "Contains the event arguments that triggered the evaluation")
|
||||
{
|
||||
_propertyPins = new Dictionary<PropertyInfo, OutputPin>();
|
||||
}
|
||||
|
||||
public override bool IsDefaultNode => true;
|
||||
|
||||
public void UpdateDataModelEvent(IDataModelEvent dataModelEvent)
|
||||
{
|
||||
if (_dataModelEvent == dataModelEvent)
|
||||
@@ -25,13 +28,11 @@ namespace Artemis.Core.Internal
|
||||
_propertyPins.Clear();
|
||||
|
||||
_dataModelEvent = dataModelEvent;
|
||||
foreach (PropertyInfo propertyInfo in dataModelEvent.ArgumentsType.GetProperties(BindingFlags.Instance | BindingFlags.Public))
|
||||
foreach (PropertyInfo propertyInfo in dataModelEvent.ArgumentsType.GetProperties(BindingFlags.Instance | BindingFlags.Public)
|
||||
.Where(p => p.CustomAttributes.All(a => a.AttributeType != typeof(DataModelIgnoreAttribute))))
|
||||
_propertyPins.Add(propertyInfo, CreateOutputPin(propertyInfo.PropertyType, propertyInfo.Name.Humanize()));
|
||||
}
|
||||
|
||||
#region Overrides of Node
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Evaluate()
|
||||
{
|
||||
if (_dataModelEvent?.LastEventArgumentsUntyped == null)
|
||||
@@ -43,7 +44,5 @@ namespace Artemis.Core.Internal
|
||||
outputPin.Value = propertyInfo.GetValue(_dataModelEvent.LastEventArgumentsUntyped) ?? outputPin.Type.GetDefault()!;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -25,12 +25,12 @@ namespace Artemis.Core
|
||||
|
||||
public string Name { get; }
|
||||
public string Description { get; }
|
||||
public bool HasNodes => _nodes.Count > 1;
|
||||
|
||||
private readonly List<INode> _nodes = new();
|
||||
public IEnumerable<INode> Nodes => new ReadOnlyCollection<INode>(_nodes);
|
||||
|
||||
protected INode ExitNode { get; set; }
|
||||
public abstract bool ExitNodeConnected { get; }
|
||||
public abstract Type ResultType { get; }
|
||||
|
||||
public object? Context { get; set; }
|
||||
@@ -149,7 +149,7 @@ namespace Artemis.Core
|
||||
{
|
||||
IPinCollection? collection = node.PinCollections.FirstOrDefault(c => c.Name == entityNodePinCollection.Name &&
|
||||
c.Type.Name == entityNodePinCollection.Type &&
|
||||
(int)c.Direction == entityNodePinCollection.Direction);
|
||||
(int) c.Direction == entityNodePinCollection.Direction);
|
||||
if (collection == null)
|
||||
continue;
|
||||
|
||||
@@ -231,7 +231,7 @@ namespace Artemis.Core
|
||||
{
|
||||
Name = nodePinCollection.Name,
|
||||
Type = nodePinCollection.Type.Name,
|
||||
Direction = (int)nodePinCollection.Direction,
|
||||
Direction = (int) nodePinCollection.Direction,
|
||||
Amount = nodePinCollection.Count()
|
||||
});
|
||||
}
|
||||
@@ -301,8 +301,9 @@ namespace Artemis.Core
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public T Result => ((ExitNode<T>)ExitNode).Value;
|
||||
public T Result => ((ExitNode<T>) ExitNode).Value;
|
||||
|
||||
public override bool ExitNodeConnected => ((ExitNode<T>) ExitNode).Input.ConnectedTo.Any();
|
||||
public override Type ResultType => typeof(T);
|
||||
|
||||
#endregion
|
||||
|
||||
Reference in new issue
Block a user