mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-01-02 10:43:31 +00:00
Profiles - Moved timeline logic to separate class (WIP)
This commit is contained in:
parent
df2f364cbe
commit
4ede3876d4
@ -74,7 +74,7 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
public override void Update(double deltaTime)
|
public override void Update(double deltaTime)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (Disposed)
|
||||||
throw new ObjectDisposedException("Folder");
|
throw new ObjectDisposedException("Folder");
|
||||||
|
|
||||||
if (!Enabled)
|
if (!Enabled)
|
||||||
@ -104,7 +104,7 @@ namespace Artemis.Core
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void AddChild(ProfileElement child, int? order = null)
|
public override void AddChild(ProfileElement child, int? order = null)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (Disposed)
|
||||||
throw new ObjectDisposedException("Folder");
|
throw new ObjectDisposedException("Folder");
|
||||||
|
|
||||||
base.AddChild(child, order);
|
base.AddChild(child, order);
|
||||||
@ -115,7 +115,7 @@ namespace Artemis.Core
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void RemoveChild(ProfileElement child)
|
public override void RemoveChild(ProfileElement child)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (Disposed)
|
||||||
throw new ObjectDisposedException("Folder");
|
throw new ObjectDisposedException("Folder");
|
||||||
|
|
||||||
base.RemoveChild(child);
|
base.RemoveChild(child);
|
||||||
@ -130,7 +130,7 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
public void CalculateRenderProperties()
|
public void CalculateRenderProperties()
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (Disposed)
|
||||||
throw new ObjectDisposedException("Folder");
|
throw new ObjectDisposedException("Folder");
|
||||||
|
|
||||||
SKPath path = new SKPath {FillType = SKPathFillType.Winding};
|
SKPath path = new SKPath {FillType = SKPathFillType.Winding};
|
||||||
@ -159,7 +159,7 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
protected override void Dispose(bool disposing)
|
protected override void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
_disposed = true;
|
Disposed = true;
|
||||||
|
|
||||||
foreach (ProfileElement profileElement in Children)
|
foreach (ProfileElement profileElement in Children)
|
||||||
profileElement.Dispose();
|
profileElement.Dispose();
|
||||||
@ -189,7 +189,7 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
internal override void Save()
|
internal override void Save()
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (Disposed)
|
||||||
throw new ObjectDisposedException("Folder");
|
throw new ObjectDisposedException("Folder");
|
||||||
|
|
||||||
FolderEntity.Id = EntityId;
|
FolderEntity.Id = EntityId;
|
||||||
@ -212,7 +212,7 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
public override void Render(SKCanvas canvas, SKImageInfo canvasInfo)
|
public override void Render(SKCanvas canvas, SKImageInfo canvasInfo)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (Disposed)
|
||||||
throw new ObjectDisposedException("Folder");
|
throw new ObjectDisposedException("Folder");
|
||||||
|
|
||||||
if (!Enabled || !Children.Any(c => c.Enabled))
|
if (!Enabled || !Children.Any(c => c.Enabled))
|
||||||
|
|||||||
@ -138,7 +138,7 @@ namespace Artemis.Core
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void Dispose(bool disposing)
|
protected override void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
_disposed = true;
|
Disposed = true;
|
||||||
|
|
||||||
// Brush first in case it depends on any of the other disposables during it's own disposal
|
// Brush first in case it depends on any of the other disposables during it's own disposal
|
||||||
_layerBrush?.Dispose();
|
_layerBrush?.Dispose();
|
||||||
@ -199,7 +199,7 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
internal override void Save()
|
internal override void Save()
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (Disposed)
|
||||||
throw new ObjectDisposedException("Layer");
|
throw new ObjectDisposedException("Layer");
|
||||||
|
|
||||||
// Properties
|
// Properties
|
||||||
@ -264,7 +264,7 @@ namespace Artemis.Core
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Update(double deltaTime)
|
public override void Update(double deltaTime)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (Disposed)
|
||||||
throw new ObjectDisposedException("Layer");
|
throw new ObjectDisposedException("Layer");
|
||||||
|
|
||||||
if (!Enabled)
|
if (!Enabled)
|
||||||
@ -285,7 +285,7 @@ namespace Artemis.Core
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Render(SKCanvas canvas, SKImageInfo canvasInfo)
|
public override void Render(SKCanvas canvas, SKImageInfo canvasInfo)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (Disposed)
|
||||||
throw new ObjectDisposedException("Layer");
|
throw new ObjectDisposedException("Layer");
|
||||||
|
|
||||||
if (!Enabled)
|
if (!Enabled)
|
||||||
@ -446,7 +446,7 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
internal void CalculateRenderProperties()
|
internal void CalculateRenderProperties()
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (Disposed)
|
||||||
throw new ObjectDisposedException("Layer");
|
throw new ObjectDisposedException("Layer");
|
||||||
|
|
||||||
if (!Leds.Any())
|
if (!Leds.Any())
|
||||||
@ -475,7 +475,7 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
internal SKPoint GetLayerAnchorPosition(SKPath layerPath, bool zeroBased = false)
|
internal SKPoint GetLayerAnchorPosition(SKPath layerPath, bool zeroBased = false)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (Disposed)
|
||||||
throw new ObjectDisposedException("Layer");
|
throw new ObjectDisposedException("Layer");
|
||||||
|
|
||||||
SKPoint positionProperty = Transform.Position.CurrentValue;
|
SKPoint positionProperty = Transform.Position.CurrentValue;
|
||||||
@ -499,7 +499,7 @@ namespace Artemis.Core
|
|||||||
/// <param name="path"></param>
|
/// <param name="path"></param>
|
||||||
public void IncludePathInTranslation(SKPath path, bool zeroBased)
|
public void IncludePathInTranslation(SKPath path, bool zeroBased)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (Disposed)
|
||||||
throw new ObjectDisposedException("Layer");
|
throw new ObjectDisposedException("Layer");
|
||||||
|
|
||||||
SKSize sizeProperty = Transform.Scale.CurrentValue;
|
SKSize sizeProperty = Transform.Scale.CurrentValue;
|
||||||
@ -535,7 +535,7 @@ namespace Artemis.Core
|
|||||||
/// <returns>The transformation matrix containing the current transformation settings</returns>
|
/// <returns>The transformation matrix containing the current transformation settings</returns>
|
||||||
public SKMatrix GetTransformMatrix(bool zeroBased)
|
public SKMatrix GetTransformMatrix(bool zeroBased)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (Disposed)
|
||||||
throw new ObjectDisposedException("Layer");
|
throw new ObjectDisposedException("Layer");
|
||||||
|
|
||||||
SKSize sizeProperty = Transform.Scale.CurrentValue;
|
SKSize sizeProperty = Transform.Scale.CurrentValue;
|
||||||
@ -569,7 +569,7 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void ExcludePathFromTranslation(SKPath path, bool zeroBased)
|
public void ExcludePathFromTranslation(SKPath path, bool zeroBased)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (Disposed)
|
||||||
throw new ObjectDisposedException("Layer");
|
throw new ObjectDisposedException("Layer");
|
||||||
|
|
||||||
SKSize sizeProperty = Transform.Scale.CurrentValue;
|
SKSize sizeProperty = Transform.Scale.CurrentValue;
|
||||||
@ -605,7 +605,7 @@ namespace Artemis.Core
|
|||||||
/// <returns>The number of transformations applied</returns>
|
/// <returns>The number of transformations applied</returns>
|
||||||
public int ExcludeCanvasFromTranslation(SKCanvas canvas, bool zeroBased)
|
public int ExcludeCanvasFromTranslation(SKCanvas canvas, bool zeroBased)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (Disposed)
|
||||||
throw new ObjectDisposedException("Layer");
|
throw new ObjectDisposedException("Layer");
|
||||||
|
|
||||||
SKSize sizeProperty = Transform.Scale.CurrentValue;
|
SKSize sizeProperty = Transform.Scale.CurrentValue;
|
||||||
@ -645,7 +645,7 @@ namespace Artemis.Core
|
|||||||
/// <param name="led">The LED to add</param>
|
/// <param name="led">The LED to add</param>
|
||||||
public void AddLed(ArtemisLed led)
|
public void AddLed(ArtemisLed led)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (Disposed)
|
||||||
throw new ObjectDisposedException("Layer");
|
throw new ObjectDisposedException("Layer");
|
||||||
|
|
||||||
_leds.Add(led);
|
_leds.Add(led);
|
||||||
@ -658,7 +658,7 @@ namespace Artemis.Core
|
|||||||
/// <param name="leds">The LEDs to add</param>
|
/// <param name="leds">The LEDs to add</param>
|
||||||
public void AddLeds(IEnumerable<ArtemisLed> leds)
|
public void AddLeds(IEnumerable<ArtemisLed> leds)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (Disposed)
|
||||||
throw new ObjectDisposedException("Layer");
|
throw new ObjectDisposedException("Layer");
|
||||||
|
|
||||||
_leds.AddRange(leds);
|
_leds.AddRange(leds);
|
||||||
@ -671,7 +671,7 @@ namespace Artemis.Core
|
|||||||
/// <param name="led">The LED to remove</param>
|
/// <param name="led">The LED to remove</param>
|
||||||
public void RemoveLed(ArtemisLed led)
|
public void RemoveLed(ArtemisLed led)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (Disposed)
|
||||||
throw new ObjectDisposedException("Layer");
|
throw new ObjectDisposedException("Layer");
|
||||||
|
|
||||||
_leds.Remove(led);
|
_leds.Remove(led);
|
||||||
@ -683,7 +683,7 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void ClearLeds()
|
public void ClearLeds()
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (Disposed)
|
||||||
throw new ObjectDisposedException("Layer");
|
throw new ObjectDisposedException("Layer");
|
||||||
|
|
||||||
_leds.Clear();
|
_leds.Clear();
|
||||||
@ -692,7 +692,7 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
internal void PopulateLeds(ArtemisSurface surface)
|
internal void PopulateLeds(ArtemisSurface surface)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (Disposed)
|
||||||
throw new ObjectDisposedException("Layer");
|
throw new ObjectDisposedException("Layer");
|
||||||
|
|
||||||
List<ArtemisLed> leds = new List<ArtemisLed>();
|
List<ArtemisLed> leds = new List<ArtemisLed>();
|
||||||
|
|||||||
@ -56,7 +56,7 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
lock (this)
|
lock (this)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (Disposed)
|
||||||
throw new ObjectDisposedException("Profile");
|
throw new ObjectDisposedException("Profile");
|
||||||
if (!IsActivated)
|
if (!IsActivated)
|
||||||
throw new ArtemisCoreException($"Cannot update inactive profile: {this}");
|
throw new ArtemisCoreException($"Cannot update inactive profile: {this}");
|
||||||
@ -70,7 +70,7 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
lock (this)
|
lock (this)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (Disposed)
|
||||||
throw new ObjectDisposedException("Profile");
|
throw new ObjectDisposedException("Profile");
|
||||||
if (!IsActivated)
|
if (!IsActivated)
|
||||||
throw new ArtemisCoreException($"Cannot render inactive profile: {this}");
|
throw new ArtemisCoreException($"Cannot render inactive profile: {this}");
|
||||||
@ -89,7 +89,7 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
public Folder GetRootFolder()
|
public Folder GetRootFolder()
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (Disposed)
|
||||||
throw new ObjectDisposedException("Profile");
|
throw new ObjectDisposedException("Profile");
|
||||||
|
|
||||||
return (Folder) Children.Single();
|
return (Folder) Children.Single();
|
||||||
@ -97,7 +97,7 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
internal override void Load()
|
internal override void Load()
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (Disposed)
|
||||||
throw new ObjectDisposedException("Profile");
|
throw new ObjectDisposedException("Profile");
|
||||||
|
|
||||||
Name = ProfileEntity.Name;
|
Name = ProfileEntity.Name;
|
||||||
@ -137,12 +137,12 @@ namespace Artemis.Core
|
|||||||
ChildrenList.Clear();
|
ChildrenList.Clear();
|
||||||
|
|
||||||
IsActivated = false;
|
IsActivated = false;
|
||||||
_disposed = true;
|
Disposed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override void Save()
|
internal override void Save()
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (Disposed)
|
||||||
throw new ObjectDisposedException("Profile");
|
throw new ObjectDisposedException("Profile");
|
||||||
|
|
||||||
ProfileEntity.Id = EntityId;
|
ProfileEntity.Id = EntityId;
|
||||||
@ -164,7 +164,7 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
lock (this)
|
lock (this)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (Disposed)
|
||||||
throw new ObjectDisposedException("Profile");
|
throw new ObjectDisposedException("Profile");
|
||||||
if (IsActivated)
|
if (IsActivated)
|
||||||
return;
|
return;
|
||||||
@ -177,7 +177,7 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
internal void PopulateLeds(ArtemisSurface surface)
|
internal void PopulateLeds(ArtemisSurface surface)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (Disposed)
|
||||||
throw new ObjectDisposedException("Profile");
|
throw new ObjectDisposedException("Profile");
|
||||||
|
|
||||||
foreach (Layer layer in GetAllLayers())
|
foreach (Layer layer in GetAllLayers())
|
||||||
|
|||||||
@ -9,13 +9,13 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
public abstract class ProfileElement : PropertyChangedBase, IDisposable
|
public abstract class ProfileElement : PropertyChangedBase, IDisposable
|
||||||
{
|
{
|
||||||
protected bool _disposed;
|
|
||||||
private bool _enabled;
|
private bool _enabled;
|
||||||
private Guid _entityId;
|
private Guid _entityId;
|
||||||
private string _name;
|
private string _name;
|
||||||
private int _order;
|
private int _order;
|
||||||
private ProfileElement _parent;
|
private ProfileElement _parent;
|
||||||
private Profile _profile;
|
private Profile _profile;
|
||||||
|
protected bool Disposed;
|
||||||
protected List<ProfileElement> ChildrenList;
|
protected List<ProfileElement> ChildrenList;
|
||||||
|
|
||||||
protected ProfileElement()
|
protected ProfileElement()
|
||||||
@ -113,7 +113,7 @@ namespace Artemis.Core
|
|||||||
/// <param name="order">The order where to place the child (1-based), defaults to the end of the collection</param>
|
/// <param name="order">The order where to place the child (1-based), defaults to the end of the collection</param>
|
||||||
public virtual void AddChild(ProfileElement child, int? order = null)
|
public virtual void AddChild(ProfileElement child, int? order = null)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (Disposed)
|
||||||
throw new ObjectDisposedException(GetType().Name);
|
throw new ObjectDisposedException(GetType().Name);
|
||||||
|
|
||||||
lock (ChildrenList)
|
lock (ChildrenList)
|
||||||
@ -157,7 +157,7 @@ namespace Artemis.Core
|
|||||||
/// <param name="child">The profile element to remove</param>
|
/// <param name="child">The profile element to remove</param>
|
||||||
public virtual void RemoveChild(ProfileElement child)
|
public virtual void RemoveChild(ProfileElement child)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (Disposed)
|
||||||
throw new ObjectDisposedException(GetType().Name);
|
throw new ObjectDisposedException(GetType().Name);
|
||||||
|
|
||||||
lock (ChildrenList)
|
lock (ChildrenList)
|
||||||
@ -180,7 +180,7 @@ namespace Artemis.Core
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public List<Folder> GetAllFolders()
|
public List<Folder> GetAllFolders()
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (Disposed)
|
||||||
throw new ObjectDisposedException(GetType().Name);
|
throw new ObjectDisposedException(GetType().Name);
|
||||||
|
|
||||||
List<Folder> folders = new List<Folder>();
|
List<Folder> folders = new List<Folder>();
|
||||||
@ -201,7 +201,7 @@ namespace Artemis.Core
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public List<Layer> GetAllLayers()
|
public List<Layer> GetAllLayers()
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (Disposed)
|
||||||
throw new ObjectDisposedException(GetType().Name);
|
throw new ObjectDisposedException(GetType().Name);
|
||||||
|
|
||||||
List<Layer> layers = new List<Layer>();
|
List<Layer> layers = new List<Layer>();
|
||||||
|
|||||||
@ -17,7 +17,6 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
ApplyDataBindingsEnabled = true;
|
ApplyDataBindingsEnabled = true;
|
||||||
ApplyKeyframesEnabled = true;
|
ApplyKeyframesEnabled = true;
|
||||||
ExtraTimeLines = new List<TimeSpan>();
|
|
||||||
|
|
||||||
LayerEffectStore.LayerEffectAdded += LayerEffectStoreOnLayerEffectAdded;
|
LayerEffectStore.LayerEffectAdded += LayerEffectStoreOnLayerEffectAdded;
|
||||||
LayerEffectStore.LayerEffectRemoved += LayerEffectStoreOnLayerEffectRemoved;
|
LayerEffectStore.LayerEffectRemoved += LayerEffectStoreOnLayerEffectRemoved;
|
||||||
@ -25,51 +24,21 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
public abstract List<ILayerProperty> GetAllLayerProperties();
|
public abstract List<ILayerProperty> GetAllLayerProperties();
|
||||||
|
|
||||||
#region IDisposable
|
|
||||||
|
|
||||||
protected override void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
LayerEffectStore.LayerEffectAdded -= LayerEffectStoreOnLayerEffectAdded;
|
|
||||||
LayerEffectStore.LayerEffectRemoved -= LayerEffectStoreOnLayerEffectRemoved;
|
|
||||||
|
|
||||||
foreach (BaseLayerEffect baseLayerEffect in LayerEffects)
|
|
||||||
baseLayerEffect.Dispose();
|
|
||||||
|
|
||||||
base.Dispose(disposing);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
internal void ApplyRenderElementDefaults()
|
|
||||||
{
|
|
||||||
MainSegmentLength = TimeSpan.FromSeconds(5);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void LoadRenderElement()
|
internal void LoadRenderElement()
|
||||||
{
|
{
|
||||||
StartSegmentLength = RenderElementEntity.StartSegmentLength;
|
|
||||||
MainSegmentLength = RenderElementEntity.MainSegmentLength;
|
|
||||||
EndSegmentLength = RenderElementEntity.EndSegmentLength;
|
|
||||||
PlayMode = (TimelinePlayMode) RenderElementEntity.PlayMode;
|
|
||||||
StopMode = (TimelineStopMode) RenderElementEntity.StopMode;
|
|
||||||
EventOverlapMode = (TimeLineEventOverlapMode) RenderElementEntity.EventOverlapMode;
|
|
||||||
|
|
||||||
DisplayCondition = RenderElementEntity.DisplayCondition != null
|
DisplayCondition = RenderElementEntity.DisplayCondition != null
|
||||||
? new DataModelConditionGroup(null, RenderElementEntity.DisplayCondition)
|
? new DataModelConditionGroup(null, RenderElementEntity.DisplayCondition)
|
||||||
: new DataModelConditionGroup(null);
|
: new DataModelConditionGroup(null);
|
||||||
|
|
||||||
|
Timeline = RenderElementEntity.Timeline != null
|
||||||
|
? new Timeline(RenderElementEntity.Timeline)
|
||||||
|
: new Timeline();
|
||||||
|
|
||||||
ActivateEffects();
|
ActivateEffects();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void SaveRenderElement()
|
internal void SaveRenderElement()
|
||||||
{
|
{
|
||||||
RenderElementEntity.StartSegmentLength = StartSegmentLength;
|
|
||||||
RenderElementEntity.MainSegmentLength = MainSegmentLength;
|
|
||||||
RenderElementEntity.EndSegmentLength = EndSegmentLength;
|
|
||||||
RenderElementEntity.PlayMode = (int) PlayMode;
|
|
||||||
RenderElementEntity.StopMode = (int) StopMode;
|
|
||||||
RenderElementEntity.EventOverlapMode = (int) EventOverlapMode;
|
|
||||||
|
|
||||||
RenderElementEntity.LayerEffects.Clear();
|
RenderElementEntity.LayerEffects.Clear();
|
||||||
foreach (BaseLayerEffect layerEffect in LayerEffects)
|
foreach (BaseLayerEffect layerEffect in LayerEffects)
|
||||||
{
|
{
|
||||||
@ -90,8 +59,36 @@ namespace Artemis.Core
|
|||||||
// Conditions
|
// Conditions
|
||||||
RenderElementEntity.DisplayCondition = DisplayCondition?.Entity;
|
RenderElementEntity.DisplayCondition = DisplayCondition?.Entity;
|
||||||
DisplayCondition?.Save();
|
DisplayCondition?.Save();
|
||||||
|
|
||||||
|
// Timeline
|
||||||
|
RenderElementEntity.Timeline = Timeline?.Entity;
|
||||||
|
Timeline?.Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region Timeline
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the timeline associated with this render element
|
||||||
|
/// </summary>
|
||||||
|
public Timeline? Timeline { get; private set; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IDisposable
|
||||||
|
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
LayerEffectStore.LayerEffectAdded -= LayerEffectStoreOnLayerEffectAdded;
|
||||||
|
LayerEffectStore.LayerEffectRemoved -= LayerEffectStoreOnLayerEffectRemoved;
|
||||||
|
|
||||||
|
foreach (BaseLayerEffect baseLayerEffect in LayerEffects)
|
||||||
|
baseLayerEffect.Dispose();
|
||||||
|
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region Properties
|
#region Properties
|
||||||
|
|
||||||
private SKPath _path;
|
private SKPath _path;
|
||||||
@ -144,168 +141,6 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Timeline
|
|
||||||
|
|
||||||
private TimeSpan _startSegmentLength;
|
|
||||||
private TimeSpan _mainSegmentLength;
|
|
||||||
private TimeSpan _endSegmentLength;
|
|
||||||
private TimeSpan _timeLine;
|
|
||||||
private TimelinePlayMode _playMode;
|
|
||||||
private TimelineStopMode _stopMode;
|
|
||||||
private TimeLineEventOverlapMode _eventOverlapMode;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the length of the start segment
|
|
||||||
/// </summary>
|
|
||||||
public TimeSpan StartSegmentLength
|
|
||||||
{
|
|
||||||
get => _startSegmentLength;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (!SetAndNotify(ref _startSegmentLength, value)) return;
|
|
||||||
UpdateTimeLineLength();
|
|
||||||
if (Parent is RenderProfileElement renderElement)
|
|
||||||
renderElement.UpdateTimeLineLength();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the length of the main segment
|
|
||||||
/// </summary>
|
|
||||||
public TimeSpan MainSegmentLength
|
|
||||||
{
|
|
||||||
get => _mainSegmentLength;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (!SetAndNotify(ref _mainSegmentLength, value)) return;
|
|
||||||
UpdateTimeLineLength();
|
|
||||||
if (Parent is RenderProfileElement renderElement)
|
|
||||||
renderElement.UpdateTimeLineLength();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the length of the end segment
|
|
||||||
/// </summary>
|
|
||||||
public TimeSpan EndSegmentLength
|
|
||||||
{
|
|
||||||
get => _endSegmentLength;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (!SetAndNotify(ref _endSegmentLength, value)) return;
|
|
||||||
UpdateTimeLineLength();
|
|
||||||
if (Parent is RenderProfileElement renderElement)
|
|
||||||
renderElement.UpdateTimeLineLength();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the current time line position
|
|
||||||
/// </summary>
|
|
||||||
public TimeSpan TimeLine
|
|
||||||
{
|
|
||||||
get => _timeLine;
|
|
||||||
protected set => SetAndNotify(ref _timeLine, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a list of extra time lines to render the element at each frame. Extra time lines are removed when they reach
|
|
||||||
/// their end
|
|
||||||
/// </summary>
|
|
||||||
public List<TimeSpan> ExtraTimeLines { get; }
|
|
||||||
|
|
||||||
/// <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 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 the max length of this element and any of its children
|
|
||||||
/// </summary>
|
|
||||||
public TimeSpan TimelineLength { get; protected set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Updates the time line and any extra time lines present in <see cref="ExtraTimeLines" />
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="deltaTime">The delta with which to move the time lines</param>
|
|
||||||
protected void UpdateTimeLines(double deltaTime)
|
|
||||||
{
|
|
||||||
bool repeatMainSegment = PlayMode == TimelinePlayMode.Repeat;
|
|
||||||
bool finishMainSegment = StopMode == TimelineStopMode.Finish;
|
|
||||||
|
|
||||||
// If the condition is event-based, never display continuously and always finish the timeline
|
|
||||||
if (DisplayCondition != null && DisplayCondition.ContainsEvents)
|
|
||||||
{
|
|
||||||
repeatMainSegment = false;
|
|
||||||
finishMainSegment = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
TimeSpan deltaTimeSpan = TimeSpan.FromSeconds(deltaTime);
|
|
||||||
TimeSpan mainSegmentEnd = StartSegmentLength + MainSegmentLength;
|
|
||||||
|
|
||||||
// Update the main time line
|
|
||||||
if (TimeLine != TimeSpan.Zero || DisplayConditionMet)
|
|
||||||
{
|
|
||||||
TimeLine += deltaTimeSpan;
|
|
||||||
|
|
||||||
// Apply play and stop mode
|
|
||||||
if (DisplayConditionMet && repeatMainSegment && TimeLine >= mainSegmentEnd)
|
|
||||||
TimeLine = StartSegmentLength;
|
|
||||||
else if (!DisplayConditionMet && !finishMainSegment)
|
|
||||||
TimeLine = mainSegmentEnd.Add(new TimeSpan(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (ExtraTimeLines)
|
|
||||||
{
|
|
||||||
// Remove extra time lines that have finished
|
|
||||||
ExtraTimeLines.RemoveAll(t => t >= mainSegmentEnd);
|
|
||||||
// Update remaining extra time lines
|
|
||||||
for (int index = 0; index < ExtraTimeLines.Count; index++)
|
|
||||||
ExtraTimeLines[index] += deltaTimeSpan;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Overrides the time line to the specified time and clears any extra time lines
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="time">The time to override to</param>
|
|
||||||
/// <param name="stickToMainSegment">Whether to stick to the main segment, wrapping around if needed</param>
|
|
||||||
public void OverrideTimeLines(TimeSpan time, bool stickToMainSegment)
|
|
||||||
{
|
|
||||||
ExtraTimeLines.Clear();
|
|
||||||
TimeLine = time;
|
|
||||||
|
|
||||||
if (stickToMainSegment && TimeLine > StartSegmentLength)
|
|
||||||
TimeLine = StartSegmentLength + TimeSpan.FromMilliseconds(time.TotalMilliseconds % MainSegmentLength.TotalMilliseconds);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected internal abstract void UpdateTimeLineLength();
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Effect management
|
#region Effect management
|
||||||
|
|
||||||
protected List<BaseLayerEffect> _layerEffects;
|
protected List<BaseLayerEffect> _layerEffects;
|
||||||
@ -475,20 +310,22 @@ namespace Artemis.Core
|
|||||||
// Regular conditions reset the timeline whenever their condition is met and was not met before that
|
// Regular conditions reset the timeline whenever their condition is met and was not met before that
|
||||||
if (!DisplayCondition.ContainsEvents)
|
if (!DisplayCondition.ContainsEvents)
|
||||||
{
|
{
|
||||||
if (conditionMet && !DisplayConditionMet && TimeLine > TimelineLength)
|
if (conditionMet && !DisplayConditionMet && Timeline.IsFinished)
|
||||||
TimeLine = TimeSpan.Zero;
|
Timeline.JumpToStart();
|
||||||
}
|
}
|
||||||
// Event conditions reset if the timeline finished and otherwise apply their overlap mode
|
// Event conditions reset if the timeline finished and otherwise apply their overlap mode
|
||||||
else if (conditionMet)
|
else if (conditionMet)
|
||||||
{
|
{
|
||||||
if (TimeLine > TimelineLength)
|
if (Timeline.IsFinished)
|
||||||
TimeLine = TimeSpan.Zero;
|
{
|
||||||
|
Timeline.JumpToStart();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (EventOverlapMode == TimeLineEventOverlapMode.Restart)
|
if (Timeline.EventOverlapMode == TimeLineEventOverlapMode.Restart)
|
||||||
TimeLine = TimeSpan.Zero;
|
Timeline.JumpToStart();
|
||||||
else if (EventOverlapMode == TimeLineEventOverlapMode.Copy)
|
else if (Timeline.EventOverlapMode == TimeLineEventOverlapMode.Copy)
|
||||||
ExtraTimeLines.Add(new TimeSpan());
|
Timeline.AddExtraTimeline();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -508,57 +345,4 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
350
src/Artemis.Core/Models/Profile/Timeline.cs
Normal file
350
src/Artemis.Core/Models/Profile/Timeline.cs
Normal file
@ -0,0 +1,350 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using Artemis.Storage.Entities.Profile;
|
||||||
|
using Stylet;
|
||||||
|
|
||||||
|
namespace Artemis.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a timeline used by profile elements
|
||||||
|
/// </summary>
|
||||||
|
public class Timeline : PropertyChangedBase, IStorageModel
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance of the <see cref="Timeline" /> class
|
||||||
|
/// </summary>
|
||||||
|
public Timeline()
|
||||||
|
{
|
||||||
|
Entity = new TimelineEntity();
|
||||||
|
_extraTimelines = new List<Timeline>();
|
||||||
|
MainSegmentLength = TimeSpan.FromSeconds(5);
|
||||||
|
|
||||||
|
Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Timeline(TimelineEntity entity)
|
||||||
|
{
|
||||||
|
Entity = entity;
|
||||||
|
_extraTimelines = new List<Timeline>();
|
||||||
|
|
||||||
|
Load();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Timeline(Timeline parent)
|
||||||
|
{
|
||||||
|
Parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Extra timelines
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds an extra timeline to this timeline
|
||||||
|
/// </summary>
|
||||||
|
public void AddExtraTimeline()
|
||||||
|
{
|
||||||
|
_extraTimelines.Add(new Timeline(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes all extra timelines from this timeline
|
||||||
|
/// </summary>
|
||||||
|
public void ClearExtraTimelines()
|
||||||
|
{
|
||||||
|
_extraTimelines.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
private TimeSpan _position;
|
||||||
|
private TimeSpan _lastDelta;
|
||||||
|
private TimeLineEventOverlapMode _eventOverlapMode;
|
||||||
|
private TimelinePlayMode _playMode;
|
||||||
|
private TimelineStopMode _stopMode;
|
||||||
|
private readonly List<Timeline> _extraTimelines;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the parent this timeline is an extra timeline of
|
||||||
|
/// </summary>
|
||||||
|
public Timeline Parent { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the current position of the timeline
|
||||||
|
/// </summary>
|
||||||
|
public TimeSpan Position
|
||||||
|
{
|
||||||
|
get => _position;
|
||||||
|
private set => SetAndNotify(ref _position, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the delta that was applied during the last call to <see cref="Update" />
|
||||||
|
/// </summary>
|
||||||
|
public TimeSpan LastDelta
|
||||||
|
{
|
||||||
|
get => _lastDelta;
|
||||||
|
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 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>
|
||||||
|
public ReadOnlyCollection<Timeline> ExtraTimelines => _extraTimelines.AsReadOnly();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a boolean indicating whether the timeline has finished its run
|
||||||
|
/// </summary>
|
||||||
|
public bool IsFinished => Position > Length;
|
||||||
|
|
||||||
|
#region Segments
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the total length of this timeline
|
||||||
|
/// </summary>
|
||||||
|
public TimeSpan Length => StartSegmentLength + MainSegmentLength + EndSegmentLength;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the length of the start segment
|
||||||
|
/// </summary>
|
||||||
|
public TimeSpan StartSegmentLength { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the length of the main segment
|
||||||
|
/// </summary>
|
||||||
|
public TimeSpan MainSegmentLength { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the length of the end segment
|
||||||
|
/// </summary>
|
||||||
|
public TimeSpan EndSegmentLength { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the start position of the main segment
|
||||||
|
/// </summary>
|
||||||
|
public TimeSpan MainSegmentStartPosition
|
||||||
|
{
|
||||||
|
get => StartSegmentEndPosition;
|
||||||
|
set => StartSegmentEndPosition = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the end position of the end segment
|
||||||
|
/// </summary>
|
||||||
|
public TimeSpan EndSegmentStartPosition
|
||||||
|
{
|
||||||
|
get => MainSegmentEndPosition;
|
||||||
|
set => MainSegmentEndPosition = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the end position of the start segment
|
||||||
|
/// </summary>
|
||||||
|
public TimeSpan StartSegmentEndPosition
|
||||||
|
{
|
||||||
|
get => StartSegmentLength;
|
||||||
|
set => StartSegmentLength = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the end position of the main segment
|
||||||
|
/// </summary>
|
||||||
|
public TimeSpan MainSegmentEndPosition
|
||||||
|
{
|
||||||
|
get => StartSegmentEndPosition + MainSegmentLength;
|
||||||
|
set => MainSegmentLength = value - StartSegmentEndPosition >= TimeSpan.Zero ? value - StartSegmentEndPosition : TimeSpan.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the end position of the end segment
|
||||||
|
/// </summary>
|
||||||
|
public TimeSpan EndSegmentEndPosition
|
||||||
|
{
|
||||||
|
get => MainSegmentEndPosition + EndSegmentLength;
|
||||||
|
set => EndSegmentLength = value - MainSegmentEndPosition >= TimeSpan.Zero ? value - MainSegmentEndPosition : TimeSpan.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal TimelineEntity Entity { get; set; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Updating
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the timeline, applying the provided <paramref name="delta" /> to the <see cref="Position" />
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="delta">The amount of time to apply to the position</param>
|
||||||
|
/// <param name="stickToMainSegment">Whether to stick to the main segment, wrapping around if needed</param>
|
||||||
|
public void Update(TimeSpan delta, bool stickToMainSegment)
|
||||||
|
{
|
||||||
|
LastDelta = delta;
|
||||||
|
Position += delta;
|
||||||
|
|
||||||
|
if (stickToMainSegment && Position >= MainSegmentStartPosition)
|
||||||
|
Position = MainSegmentStartPosition + TimeSpan.FromMilliseconds(Position.TotalMilliseconds % MainSegmentLength.TotalMilliseconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Moves the position of the timeline backwards to the very start of the timeline
|
||||||
|
/// </summary>
|
||||||
|
public void JumpToStart()
|
||||||
|
{
|
||||||
|
if (Position == TimeSpan.Zero)
|
||||||
|
return;
|
||||||
|
|
||||||
|
LastDelta = TimeSpan.Zero - Position;
|
||||||
|
Position = TimeSpan.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Moves the position of the timeline forwards to the beginning of the end segment
|
||||||
|
/// </summary>
|
||||||
|
public void JumpToEndSegment()
|
||||||
|
{
|
||||||
|
if (Position >= EndSegmentStartPosition)
|
||||||
|
return;
|
||||||
|
|
||||||
|
LastDelta = EndSegmentStartPosition - Position;
|
||||||
|
Position = EndSegmentStartPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Moves the position of the timeline forwards to the very end of the timeline
|
||||||
|
/// </summary>
|
||||||
|
public void JumpToEnd()
|
||||||
|
{
|
||||||
|
if (Position >= EndSegmentEndPosition)
|
||||||
|
return;
|
||||||
|
|
||||||
|
LastDelta = EndSegmentEndPosition - Position;
|
||||||
|
Position = EndSegmentEndPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Overrides the <see cref="Position" /> 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 void Override(TimeSpan position, bool stickToMainSegment)
|
||||||
|
{
|
||||||
|
_extraTimelines.Clear();
|
||||||
|
|
||||||
|
LastDelta = position - Position;
|
||||||
|
Position = position;
|
||||||
|
if (stickToMainSegment && Position >= MainSegmentStartPosition)
|
||||||
|
Position = MainSegmentStartPosition + TimeSpan.FromMilliseconds(Position.TotalMilliseconds % MainSegmentLength.TotalMilliseconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Storage
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void Load()
|
||||||
|
{
|
||||||
|
StartSegmentLength = Entity.StartSegmentLength;
|
||||||
|
MainSegmentLength = Entity.MainSegmentLength;
|
||||||
|
EndSegmentLength = Entity.EndSegmentLength;
|
||||||
|
PlayMode = (TimelinePlayMode) Entity.PlayMode;
|
||||||
|
StopMode = (TimelineStopMode) Entity.StopMode;
|
||||||
|
EventOverlapMode = (TimeLineEventOverlapMode) Entity.EventOverlapMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void Save()
|
||||||
|
{
|
||||||
|
Entity.StartSegmentLength = StartSegmentLength;
|
||||||
|
Entity.MainSegmentLength = MainSegmentLength;
|
||||||
|
Entity.EndSegmentLength = EndSegmentLength;
|
||||||
|
Entity.PlayMode = (int) PlayMode;
|
||||||
|
Entity.StopMode = (int) StopMode;
|
||||||
|
Entity.EventOverlapMode = (int) EventOverlapMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -6,18 +6,11 @@ namespace Artemis.Storage.Entities.Profile.Abstract
|
|||||||
{
|
{
|
||||||
public abstract class RenderElementEntity
|
public abstract class RenderElementEntity
|
||||||
{
|
{
|
||||||
public TimeSpan StartSegmentLength { get; set; }
|
|
||||||
public TimeSpan MainSegmentLength { get; set; }
|
|
||||||
public TimeSpan EndSegmentLength { get; set; }
|
|
||||||
|
|
||||||
public int PlayMode { get; set; }
|
|
||||||
public int StopMode { get; set; }
|
|
||||||
public int EventOverlapMode { get; set; }
|
|
||||||
|
|
||||||
public List<LayerEffectEntity> LayerEffects { get; set; }
|
public List<LayerEffectEntity> LayerEffects { get; set; }
|
||||||
public List<PropertyEntity> PropertyEntities { get; set; }
|
public List<PropertyEntity> PropertyEntities { get; set; }
|
||||||
public List<string> ExpandedPropertyGroups { get; set; }
|
public List<string> ExpandedPropertyGroups { get; set; }
|
||||||
|
|
||||||
public DataModelConditionGroupEntity DisplayCondition { get; set; }
|
public DataModelConditionGroupEntity DisplayCondition { get; set; }
|
||||||
|
public TimelineEntity Timeline { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
15
src/Artemis.Storage/Entities/Profile/TimelineEntity.cs
Normal file
15
src/Artemis.Storage/Entities/Profile/TimelineEntity.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Artemis.Storage.Entities.Profile
|
||||||
|
{
|
||||||
|
public class TimelineEntity
|
||||||
|
{
|
||||||
|
public TimeSpan StartSegmentLength { get; set; }
|
||||||
|
public TimeSpan MainSegmentLength { get; set; }
|
||||||
|
public TimeSpan EndSegmentLength { get; set; }
|
||||||
|
|
||||||
|
public int PlayMode { get; set; }
|
||||||
|
public int StopMode { get; set; }
|
||||||
|
public int EventOverlapMode { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -221,4 +221,5 @@
|
|||||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAlwaysTreatStructAsNotReorderableMigration/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAlwaysTreatStructAsNotReorderableMigration/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=luma/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=luma/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Timelines/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||||
Loading…
x
Reference in New Issue
Block a user