Core - Refactored display conditions

Profile editor - Added UIs for each condition type
This commit is contained in:
Robert committed 2022-04-09 00:11:22 +02:00
1 parent 66ea718316
commit 3dfc25b092
47 files changed
+1305 -546

No files matched your search

@@ -0,0 +1,78 @@
using System;
using Artemis.Storage.Entities.Profile.Abstract;
using Artemis.Storage.Entities.Profile.Conditions;
namespace Artemis.Core
{
public class AlwaysOnCondition : ICondition
{
public AlwaysOnCondition(RenderProfileElement profileElement)
{
ProfileElement = profileElement;
Entity = new AlwaysOnConditionEntity();
}
public AlwaysOnCondition(AlwaysOnConditionEntity alwaysOnConditionEntity, RenderProfileElement profileElement)
{
ProfileElement = profileElement;
Entity = alwaysOnConditionEntity;
}
#region Implementation of IDisposable
/// <inheritdoc />
public void Dispose()
{
}
#endregion
#region Implementation of IStorageModel
/// <inheritdoc />
public void Load()
{
}
/// <inheritdoc />
public void Save()
{
}
#endregion
#region Implementation of ICondition
/// <inheritdoc />
public IConditionEntity Entity { get; }
/// <inheritdoc />
public RenderProfileElement ProfileElement { get; }
/// <inheritdoc />
public bool IsMet { get; private set; }
/// <inheritdoc />
public void Update()
{
if (ProfileElement.Parent is RenderProfileElement parent)
IsMet = parent.DisplayConditionMet;
else
IsMet = true;
}
/// <inheritdoc />
public void UpdateTimeline(double deltaTime)
{
ProfileElement.Timeline.Update(TimeSpan.FromSeconds(deltaTime), true);
}
/// <inheritdoc />
public void OverrideTimeline(TimeSpan position)
{
ProfileElement.Timeline.Override(position, position > ProfileElement.Timeline.Length);
}
#endregion
}
}
@@ -4,211 +4,262 @@ using Artemis.Core.Internal;
using Artemis.Storage.Entities.Profile.Abstract;
using Artemis.Storage.Entities.Profile.Conditions;
namespace Artemis.Core
namespace Artemis.Core;
/// <summary>
/// Represents a condition that is based on a <see cref="DataModelEvent" />
/// </summary>
public class EventCondition : CorePropertyChanged, INodeScriptCondition
{
private readonly string _displayName;
private readonly EventConditionEntity _entity;
private readonly EventDefaultNode _eventNode;
private DataModelPath? _eventPath;
private DateTime _lastProcessedTrigger;
private EventOverlapMode _overlapMode;
private NodeScript<bool> _script;
private EventTriggerMode _triggerMode;
private bool _wasMet;
/// <summary>
/// Creates a new instance of the <see cref="EventCondition" /> class
/// </summary>
public EventCondition(RenderProfileElement profileElement)
{
ProfileElement = profileElement;
_entity = new EventConditionEntity();
_displayName = profileElement.GetType().Name;
_eventNode = new EventDefaultNode {X = -300};
_script = new NodeScript<bool>($"Activate {_displayName}", $"Whether or not the event should activate the {_displayName}", ProfileElement.Profile);
}
internal EventCondition(EventConditionEntity entity, RenderProfileElement profileElement)
{
ProfileElement = profileElement;
_entity = entity;
_displayName = profileElement.GetType().Name;
_eventNode = new EventDefaultNode();
_script = null!;
Load();
}
/// <summary>
/// Gets the script that drives the event condition
/// </summary>
public NodeScript<bool> Script
{
get => _script;
set => SetAndNotify(ref _script, value);
}
/// <summary>
/// Gets or sets the path to the event that drives this event condition
/// </summary>
public DataModelPath? EventPath
{
get => _eventPath;
set => SetAndNotify(ref _eventPath, value);
}
/// <summary>
/// Gets or sets how the condition behaves when the event fires.
/// </summary>
public EventTriggerMode TriggerMode
{
get => _triggerMode;
set => SetAndNotify(ref _triggerMode, value);
}
/// <summary>
/// Gets or sets how the condition behaves when events trigger before the timeline finishes in the
/// <see cref="EventTriggerMode.Play" /> event trigger mode.
/// </summary>
public EventOverlapMode OverlapMode
{
get => _overlapMode;
set => SetAndNotify(ref _overlapMode, value);
}
/// <summary>
/// Updates the event node, applying the selected event
/// </summary>
public void UpdateEventNode()
{
IDataModelEvent? dataModelEvent = EventPath?.GetValue() as IDataModelEvent;
_eventNode.CreatePins(dataModelEvent);
if (dataModelEvent != null && !Script.Nodes.Contains(_eventNode))
Script.AddNode(_eventNode);
else if (dataModelEvent == null && Script.Nodes.Contains(_eventNode))
Script.RemoveNode(_eventNode);
}
/// <summary>
/// Gets the start node of the event script, if any
/// </summary>
/// <returns>The start node of the event script, if any.</returns>
public INode GetStartNode()
{
return _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 RenderProfileElement ProfileElement { get; }
/// <inheritdoc />
public bool IsMet { get; private set; }
/// <inheritdoc />
public void Update()
{
_wasMet = IsMet;
if (TriggerMode == EventTriggerMode.Toggle)
{
if (Evaluate())
IsMet = !IsMet;
}
else
{
IsMet = Evaluate();
}
}
/// <inheritdoc />
public void UpdateTimeline(double deltaTime)
{
if (TriggerMode == EventTriggerMode.Toggle)
{
if (!IsMet && _wasMet)
ProfileElement.Timeline.JumpToEnd();
else if (IsMet && !_wasMet)
ProfileElement.Timeline.JumpToStart();
}
else
{
if (IsMet && ProfileElement.Timeline.IsFinished)
{
ProfileElement.Timeline.JumpToStart();
}
else if (IsMet)
{
if (OverlapMode == EventOverlapMode.Restart)
ProfileElement.Timeline.JumpToStart();
else if (OverlapMode == EventOverlapMode.Copy && ProfileElement is Layer layer)
layer.CreateCopyAsChild();
}
}
ProfileElement.Timeline.Update(TimeSpan.FromSeconds(deltaTime), TriggerMode == EventTriggerMode.Toggle);
}
/// <inheritdoc />
public void OverrideTimeline(TimeSpan position)
{
ProfileElement.Timeline.Override(position, TriggerMode == EventTriggerMode.Toggle && position > ProfileElement.Timeline.Length);
}
/// <inheritdoc />
public void Dispose()
{
Script?.Dispose();
EventPath?.Dispose();
}
#region Storage
/// <inheritdoc />
public void Load()
{
TriggerMode = (EventTriggerMode) _entity.TriggerMode;
OverlapMode = (EventOverlapMode) _entity.OverlapMode;
if (_entity.EventPath != null)
EventPath = new DataModelPath(_entity.EventPath);
Script = _entity.Script != null
? new NodeScript<bool>($"Activate {_displayName}", $"Whether or not the event should activate the {_displayName}", _entity.Script, ProfileElement.Profile)
: new NodeScript<bool>($"Activate {_displayName}", $"Whether or not the event should activate the {_displayName}", ProfileElement.Profile);
}
/// <inheritdoc />
public void Save()
{
_entity.TriggerMode = (int) TriggerMode;
_entity.OverlapMode = (int) OverlapMode;
Script.Save();
_entity.Script = Script?.Entity;
EventPath?.Save();
_entity.EventPath = EventPath?.Entity;
}
/// <inheritdoc />
public INodeScript NodeScript => Script;
/// <inheritdoc />
public void LoadNodeScript()
{
Script.Load();
UpdateEventNode();
Script.LoadConnections();
}
#endregion
}
/// <summary>
/// Represents a mode for render elements to start their timeline when display conditions events are fired.
/// </summary>
public enum EventTriggerMode
{
/// <summary>
/// Represents a condition that is based on a <see cref="DataModelEvent" />
/// Play the timeline once.
/// </summary>
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;
private NodeScript<bool>? _script;
Play,
/// <summary>
/// Creates a new instance of the <see cref="EventCondition" /> class
/// </summary>
public EventCondition(ProfileElement profileElement)
{
_entity = new EventConditionEntity();
_displayName = profileElement.GetType().Name;
/// <summary>
/// Toggle repeating the timeline.
/// </summary>
Toggle
}
ProfileElement = profileElement;
}
/// <summary>
/// Represents a mode for render elements to configure the behaviour of events that overlap i.e. trigger again before
/// the timeline finishes.
/// </summary>
public enum EventOverlapMode
{
/// <summary>
/// Stop the current run and restart the timeline
/// </summary>
Restart,
internal EventCondition(EventConditionEntity entity, ProfileElement profileElement)
{
_entity = entity;
_displayName = profileElement.GetType().Name;
/// <summary>
/// Ignore subsequent event fires until the timeline finishes
/// </summary>
Ignore,
ProfileElement = profileElement;
Load();
}
/// <summary>
/// Gets the script that drives the event condition
/// </summary>
public NodeScript<bool>? Script
{
get => _script;
set => SetAndNotify(ref _script, value);
}
/// <summary>
/// Gets or sets the path to the event that drives this event condition
/// </summary>
public DataModelPath? EventPath
{
get => _eventPath;
set => SetAndNotify(ref _eventPath, value);
}
/// <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 (Script == null || 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 {X = -300};
_eventNode.UpdateDataModelEvent(dataModelEvent);
}
if (_eventNode.Pins.Any() && !Script.Nodes.Contains(_eventNode))
Script.AddNode(_eventNode);
else
Script.RemoveNode(_eventNode);
}
/// <summary>
/// Updates the <see cref="Script" /> with a new empty node script
/// </summary>
public void CreateEmptyNodeScript()
{
Script?.Dispose();
Script = new NodeScript<bool>($"Activate {_displayName}", $"Whether or not the event should activate the {_displayName}", ProfileElement.Profile);
UpdateEventNode();
}
private bool Evaluate()
{
if (EventPath?.GetValue() is not IDataModelEvent dataModelEvent || dataModelEvent.LastTrigger <= _lastProcessedTrigger)
return false;
_lastProcessedTrigger = dataModelEvent.LastTrigger;
if (Script == null)
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 && ProfileElement is Layer layer)
layer.CreateCopyAsChild();
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;
if (_entity.Script != null)
Script = new NodeScript<bool>($"Activate {_displayName}", $"Whether or not the event should activate the {_displayName}", _entity.Script, ProfileElement.Profile);
if (_entity.EventPath != null)
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 INodeScript NodeScript => Script;
/// <inheritdoc />
public void LoadNodeScript()
{
if (Script == null)
return;
Script.Load();
UpdateEventNode();
Script.LoadConnections();
}
#endregion
}
/// <summary>
/// Play another copy of the timeline on top of the current run
/// </summary>
Copy
}
@@ -16,7 +16,7 @@ public interface ICondition : IDisposable, IStorageModel
/// <summary>
/// Gets the profile element this condition applies to
/// </summary>
public ProfileElement ProfileElement { get; }
public RenderProfileElement ProfileElement { get; }
/// <summary>
/// Gets a boolean indicating whether the condition is currently met
@@ -30,12 +30,11 @@ public interface ICondition : IDisposable, IStorageModel
void Update();
/// <summary>
/// Applies the display condition to the provided timeline
/// Updates the timeline according to the provided <paramref name="deltaTime" /> as the display condition sees fit.
/// </summary>
/// <param name="isMet"></param>
/// <param name="wasMet"></param>
/// <param name="timeline">The timeline to apply the display condition to</param>
void ApplyToTimeline(bool isMet, bool wasMet, Timeline timeline);
void UpdateTimeline(double deltaTime);
void OverrideTimeline(TimeSpan position);
}
/// <summary>
@@ -0,0 +1,78 @@
using System;
using Artemis.Storage.Entities.Profile.Abstract;
using Artemis.Storage.Entities.Profile.Conditions;
namespace Artemis.Core
{
public class PlayOnceCondition : ICondition
{
public PlayOnceCondition(RenderProfileElement profileElement)
{
ProfileElement = profileElement;
Entity = new PlayOnceConditionEntity();
}
public PlayOnceCondition(PlayOnceConditionEntity entity, RenderProfileElement profileElement)
{
ProfileElement = profileElement;
Entity = entity;
}
#region Implementation of IDisposable
/// <inheritdoc />
public void Dispose()
{
}
#endregion
#region Implementation of IStorageModel
/// <inheritdoc />
public void Load()
{
}
/// <inheritdoc />
public void Save()
{
}
#endregion
#region Implementation of ICondition
/// <inheritdoc />
public IConditionEntity Entity { get; }
/// <inheritdoc />
public RenderProfileElement ProfileElement { get; }
/// <inheritdoc />
public bool IsMet { get; private set; }
/// <inheritdoc />
public void Update()
{
if (ProfileElement.Parent is RenderProfileElement parent)
IsMet = parent.DisplayConditionMet;
else
IsMet = true;
}
/// <inheritdoc />
public void UpdateTimeline(double deltaTime)
{
ProfileElement.Timeline.Update(TimeSpan.FromSeconds(deltaTime), false);
}
/// <inheritdoc />
public void OverrideTimeline(TimeSpan position)
{
ProfileElement.Timeline.Override(position, false);
}
#endregion
}
}
@@ -1,4 +1,5 @@
using Artemis.Storage.Entities.Profile.Abstract;
using System;
using Artemis.Storage.Entities.Profile.Abstract;
using Artemis.Storage.Entities.Profile.Conditions;
namespace Artemis.Core
@@ -10,11 +11,14 @@ namespace Artemis.Core
{
private readonly string _displayName;
private readonly StaticConditionEntity _entity;
private StaticPlayMode _playMode;
private StaticStopMode _stopMode;
private bool _wasMet;
/// <summary>
/// Creates a new instance of the <see cref="StaticCondition" /> class
/// </summary>
public StaticCondition(ProfileElement profileElement)
public StaticCondition(RenderProfileElement profileElement)
{
_entity = new StaticConditionEntity();
_displayName = profileElement.GetType().Name;
@@ -23,7 +27,7 @@ namespace Artemis.Core
Script = new NodeScript<bool>($"Activate {_displayName}", $"Whether or not this {_displayName} should be active", profileElement.Profile);
}
internal StaticCondition(StaticConditionEntity entity, ProfileElement profileElement)
internal StaticCondition(StaticConditionEntity entity, RenderProfileElement profileElement)
{
_entity = entity;
_displayName = profileElement.GetType().Name;
@@ -43,31 +47,66 @@ namespace Artemis.Core
public IConditionEntity Entity => _entity;
/// <inheritdoc />
public ProfileElement ProfileElement { get; }
public RenderProfileElement ProfileElement { get; }
/// <inheritdoc />
public bool IsMet { get; private set; }
/// <inheritdoc />
public void Update()
/// <summary>
/// Gets or sets the mode in which the render element starts its timeline when display conditions are met
/// </summary>
public StaticPlayMode PlayMode
{
if (!Script.ExitNodeConnected)
{
IsMet = true;
return;
}
get => _playMode;
set => SetAndNotify(ref _playMode, value);
}
Script.Run();
IsMet = Script.Result;
/// <summary>
/// Gets or sets the mode in which the render element stops its timeline when display conditions are no longer met
/// </summary>
public StaticStopMode StopMode
{
get => _stopMode;
set => SetAndNotify(ref _stopMode, value);
}
/// <inheritdoc />
public void ApplyToTimeline(bool isMet, bool wasMet, Timeline timeline)
public void Update()
{
if (isMet && !wasMet && timeline.IsFinished)
timeline.JumpToStart();
else if (!isMet && wasMet && timeline.StopMode == TimelineStopMode.SkipToEnd)
timeline.JumpToEndSegment();
_wasMet = IsMet;
// No need to run the script if the parent isn't met anyway
bool parentConditionMet = ProfileElement.Parent is not RenderProfileElement renderProfileElement || renderProfileElement.DisplayConditionMet;
if (!parentConditionMet)
{
IsMet = false;
return;
}
if (!Script.ExitNodeConnected)
IsMet = true;
else
{
Script.Run();
IsMet = Script.Result;
}
}
/// <inheritdoc />
public void UpdateTimeline(double deltaTime)
{
if (IsMet && !_wasMet && ProfileElement.Timeline.IsFinished)
ProfileElement.Timeline.JumpToStart();
else if (!IsMet && _wasMet && StopMode == StaticStopMode.SkipToEnd)
ProfileElement.Timeline.JumpToEndSegment();
ProfileElement.Timeline.Update(TimeSpan.FromSeconds(deltaTime), PlayMode == StaticPlayMode.Repeat && IsMet);
}
/// <inheritdoc />
public void OverrideTimeline(TimeSpan position)
{
ProfileElement.Timeline.Override(position, PlayMode == StaticPlayMode.Repeat && position > ProfileElement.Timeline.Length);
}
/// <inheritdoc />
@@ -81,12 +120,18 @@ namespace Artemis.Core
/// <inheritdoc />
public void Load()
{
PlayMode = (StaticPlayMode) _entity.PlayMode;
StopMode = (StaticStopMode) _entity.StopMode;
Script = new NodeScript<bool>($"Activate {_displayName}", $"Whether or not this {_displayName} should be active", _entity.Script, ProfileElement.Profile);
}
/// <inheritdoc />
public void Save()
{
_entity.PlayMode = (int) PlayMode;
_entity.StopMode = (int) StopMode;
Script.Save();
_entity.Script = Script.Entity;
}
@@ -102,4 +147,36 @@ namespace Artemis.Core
#endregion
}
/// <summary>
/// Represents a mode for render elements to start their timeline when display conditions are met
/// </summary>
public enum StaticPlayMode
{
/// <summary>
/// Continue repeating the main segment of the timeline while the condition is met
/// </summary>
Repeat,
/// <summary>
/// Only play the timeline once when the condition is met
/// </summary>
Once
}
/// <summary>
/// Represents a mode for render elements to stop their timeline when display conditions are no longer met
/// </summary>
public enum StaticStopMode
{
/// <summary>
/// When conditions are no longer met, finish the the current run of the main timeline
/// </summary>
Finish,
/// <summary>
/// When conditions are no longer met, skip to the end segment of the timeline
/// </summary>
SkipToEnd
}
}
+3 -3
View File
@@ -237,11 +237,11 @@ namespace Artemis.Core
}
/// <inheritdoc />
public override void OverrideTimelineAndApply(TimeSpan position, bool stickToMainSegment)
public override void OverrideTimelineAndApply(TimeSpan position)
{
Timeline.Override(position, stickToMainSegment);
DisplayCondition.OverrideTimeline(position);
foreach (BaseLayerEffect baseLayerEffect in LayerEffects.Where(e => !e.Suspended))
baseLayerEffect.InternalUpdate(Timeline);
baseLayerEffect.InternalUpdate(Timeline); ;
}
/// <inheritdoc />
+2 -2
View File
@@ -476,9 +476,9 @@ namespace Artemis.Core
}
/// <inheritdoc />
public override void OverrideTimelineAndApply(TimeSpan position, bool stickToMainSegment)
public override void OverrideTimelineAndApply(TimeSpan position)
{
Timeline.Override(position, stickToMainSegment);
DisplayCondition.OverrideTimeline(position);
General.Update(Timeline);
Transform.Update(Timeline);
@@ -27,6 +27,7 @@ namespace Artemis.Core
LayerEffectsList = new List<BaseLayerEffect>();
LayerEffects = new ReadOnlyCollection<BaseLayerEffect>(LayerEffectsList);
Parent = parent ?? throw new ArgumentNullException(nameof(parent));
_displayCondition = new AlwaysOnCondition(this);
LayerEffectStore.LayerEffectAdded += LayerEffectStoreOnLayerEffectAdded;
LayerEffectStore.LayerEffectRemoved += LayerEffectStoreOnLayerEffectRemoved;
@@ -52,7 +53,7 @@ namespace Artemis.Core
/// Occurs when a layer effect has been added or removed to this render element
/// </summary>
public event EventHandler? LayerEffectsUpdated;
/// <inheritdoc />
protected override void Dispose(bool disposing)
{
@@ -76,8 +77,10 @@ namespace Artemis.Core
DisplayCondition = RenderElementEntity.DisplayCondition switch
{
StaticConditionEntity staticConditionEntity => new StaticCondition(staticConditionEntity, this),
EventConditionEntity eventConditionEntity => new EventCondition(eventConditionEntity, this),
AlwaysOnConditionEntity entity => new AlwaysOnCondition(entity, this),
PlayOnceConditionEntity entity => new PlayOnceCondition(entity, this),
StaticConditionEntity entity => new StaticCondition(entity, this),
EventConditionEntity entity => new EventCondition(entity, this),
_ => DisplayCondition
};
@@ -124,17 +127,11 @@ namespace Artemis.Core
public Timeline Timeline { get; private set; }
/// <summary>
/// Updates the <see cref="Timeline" /> according to the provided <paramref name="deltaTime" /> and current display
/// condition status
/// Updates the <see cref="Timeline" /> according to the provided <paramref name="deltaTime" /> and current display condition
/// </summary>
protected 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 && DisplayConditionMet;
Timeline.Update(TimeSpan.FromSeconds(deltaTime), stickToMainSegment);
DisplayCondition.UpdateTimeline(deltaTime);
}
#endregion
@@ -317,7 +314,7 @@ namespace Artemis.Core
OrderEffects();
}
internal void ActivateLayerEffect(BaseLayerEffect layerEffect)
{
@@ -365,13 +362,13 @@ namespace Artemis.Core
/// <summary>
/// Gets or sets the display condition used to determine whether this element is active or not
/// </summary>
public ICondition? DisplayCondition
public ICondition DisplayCondition
{
get => _displayCondition;
set => SetAndNotify(ref _displayCondition, value);
}
private ICondition? _displayCondition;
private ICondition _displayCondition;
/// <summary>
/// Evaluates the display conditions on this element and applies any required changes to the <see cref="Timeline" />
@@ -384,14 +381,7 @@ namespace Artemis.Core
return;
}
if (DisplayCondition == null)
{
DisplayConditionMet = true;
return;
}
DisplayCondition.Update();
DisplayCondition.ApplyToTimeline(DisplayCondition.IsMet, DisplayConditionMet, Timeline);
DisplayConditionMet = DisplayCondition.IsMet;
}
@@ -401,7 +391,6 @@ namespace Artemis.Core
/// Overrides the main timeline to the specified time and clears any extra time lines
/// </summary>
/// <param name="position">The position to set the timeline to</param>
/// <param name="stickToMainSegment">Whether to stick to the main segment, wrapping around if needed</param>
public abstract void OverrideTimelineAndApply(TimeSpan position, bool stickToMainSegment);
public abstract void OverrideTimelineAndApply(TimeSpan position);
}
}
+1 -80
View File
@@ -41,8 +41,7 @@ public class Timeline : CorePropertyChanged, IStorageModel
private TimeSpan _position;
private TimeSpan _lastDelta;
private TimelinePlayMode _playMode;
private TimelineStopMode _stopMode;
private TimeSpan _startSegmentLength;
private TimeSpan _mainSegmentLength;
private TimeSpan _endSegmentLength;
@@ -67,23 +66,7 @@ public class Timeline : CorePropertyChanged, IStorageModel
private set => SetAndNotify(ref _lastDelta, value);
}
/// <summary>
/// Gets or sets the mode in which the render element starts its timeline when display conditions are met
/// </summary>
public TimelinePlayMode PlayMode
{
get => _playMode;
set => SetAndNotify(ref _playMode, value);
}
/// <summary>
/// Gets or sets the mode in which the render element stops its timeline when display conditions are no longer met
/// </summary>
public TimelineStopMode StopMode
{
get => _stopMode;
set => SetAndNotify(ref _stopMode, value);
}
/// <summary>
/// Gets a boolean indicating whether the timeline has finished its run
@@ -388,8 +371,6 @@ public class Timeline : CorePropertyChanged, IStorageModel
StartSegmentLength = Entity.StartSegmentLength;
MainSegmentLength = Entity.MainSegmentLength;
EndSegmentLength = Entity.EndSegmentLength;
PlayMode = (TimelinePlayMode) Entity.PlayMode;
StopMode = (TimelineStopMode) Entity.StopMode;
JumpToEnd();
}
@@ -400,8 +381,6 @@ public class Timeline : CorePropertyChanged, IStorageModel
Entity.StartSegmentLength = StartSegmentLength;
Entity.MainSegmentLength = MainSegmentLength;
Entity.EndSegmentLength = EndSegmentLength;
Entity.PlayMode = (int) PlayMode;
Entity.StopMode = (int) StopMode;
}
#endregion
@@ -413,61 +392,3 @@ internal enum TimelineSegment
Main,
End
}
/// <summary>
/// Represents a mode for render elements to start their timeline when display conditions are met
/// </summary>
public enum TimelinePlayMode
{
/// <summary>
/// Continue repeating the main segment of the timeline while the condition is met
/// </summary>
Repeat,
/// <summary>
/// Only play the timeline once when the condition is met
/// </summary>
Once
}
/// <summary>
/// Represents a mode for render elements to stop their timeline when display conditions are no longer met
/// </summary>
public enum TimelineStopMode
{
/// <summary>
/// When conditions are no longer met, finish the the current run of the main timeline
/// </summary>
Finish,
/// <summary>
/// When conditions are no longer met, skip to the end segment of the timeline
/// </summary>
SkipToEnd
}
/// <summary>
/// Represents a mode for render elements to start their timeline when display conditions events are fired
/// </summary>
public enum TimeLineEventOverlapMode
{
/// <summary>
/// Stop the current run and restart the timeline
/// </summary>
Restart,
/// <summary>
/// Ignore subsequent event fires until the timeline finishes
/// </summary>
Ignore,
/// <summary>
/// Play another copy of the timeline on top of the current run
/// </summary>
Copy,
/// <summary>
/// Repeat the timeline until the event fires again
/// </summary>
Toggle
}