mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Event condition - Simplify to only one event per layer
This commit is contained in:
parent
d657e7844e
commit
00125d1478
@ -1,35 +1,35 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Artemis.Core.Internal;
|
using Artemis.Core.Internal;
|
||||||
|
using Artemis.Storage.Entities.Profile.Abstract;
|
||||||
using Artemis.Storage.Entities.Profile.Conditions;
|
using Artemis.Storage.Entities.Profile.Conditions;
|
||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
public class EventCondition : CorePropertyChanged, IDisposable, IStorageModel
|
public class EventCondition : CorePropertyChanged, INodeScriptCondition
|
||||||
{
|
{
|
||||||
private readonly string _displayName;
|
private readonly string _displayName;
|
||||||
private readonly object? _context;
|
private readonly EventConditionEntity _entity;
|
||||||
private DateTime _lastProcessedTrigger;
|
private EventDefaultNode _eventNode;
|
||||||
|
private TimeLineEventOverlapMode _eventOverlapMode;
|
||||||
private DataModelPath? _eventPath;
|
private DataModelPath? _eventPath;
|
||||||
|
private DateTime _lastProcessedTrigger;
|
||||||
|
|
||||||
internal EventCondition(string displayName, object? context)
|
public EventCondition(ProfileElement profileElement)
|
||||||
{
|
{
|
||||||
_displayName = displayName;
|
_entity = new EventConditionEntity();
|
||||||
_context = context;
|
_displayName = profileElement.GetType().Name;
|
||||||
|
|
||||||
Entity = new EventConditionEntity();
|
ProfileElement = profileElement;
|
||||||
Script = new NodeScript<bool>($"Activate {displayName}", $"Whether or not the event should activate the {displayName}", context);
|
Script = new NodeScript<bool>($"Activate {_displayName}", $"Whether or not the event should activate the {_displayName}", profileElement.Profile);
|
||||||
UpdateEventNode();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal EventCondition(EventConditionEntity entity, string displayName, object? context)
|
internal EventCondition(EventConditionEntity entity, ProfileElement profileElement)
|
||||||
{
|
{
|
||||||
_displayName = displayName;
|
_entity = entity;
|
||||||
_context = context;
|
_displayName = profileElement.GetType().Name;
|
||||||
|
|
||||||
Entity = entity;
|
|
||||||
Script = null!;
|
|
||||||
|
|
||||||
|
ProfileElement = profileElement;
|
||||||
Load();
|
Load();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,36 +47,14 @@ namespace Artemis.Core
|
|||||||
get => _eventPath;
|
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
|
||||||
{
|
{
|
||||||
if (EventPath?.GetValue() is not IDataModelEvent dataModelEvent || dataModelEvent.LastTrigger <= _lastProcessedTrigger)
|
get => _eventOverlapMode;
|
||||||
return false;
|
set => SetAndNotify(ref _eventOverlapMode, value);
|
||||||
|
|
||||||
// TODO: Place dataModelEvent.LastEventArgumentsUntyped; in the start node
|
|
||||||
Script.Run();
|
|
||||||
|
|
||||||
_lastProcessedTrigger = dataModelEvent.LastTrigger;
|
|
||||||
|
|
||||||
return Script.Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#region IDisposable
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Script.Dispose();
|
|
||||||
EventPath?.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
internal void LoadNodeScript()
|
|
||||||
{
|
|
||||||
Script.Load();
|
|
||||||
UpdateEventNode();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -87,33 +65,120 @@ namespace Artemis.Core
|
|||||||
if (EventPath?.GetValue() is not IDataModelEvent dataModelEvent)
|
if (EventPath?.GetValue() is not IDataModelEvent dataModelEvent)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (Script.Nodes.FirstOrDefault(n => n is EventStartNode) is EventStartNode existing)
|
if (Script.Nodes.FirstOrDefault(n => n is EventDefaultNode) is EventDefaultNode existing)
|
||||||
|
{
|
||||||
existing.UpdateDataModelEvent(dataModelEvent);
|
existing.UpdateDataModelEvent(dataModelEvent);
|
||||||
|
_eventNode = existing;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EventStartNode node = new();
|
_eventNode = new EventDefaultNode();
|
||||||
node.UpdateDataModelEvent(dataModelEvent);
|
_eventNode.UpdateDataModelEvent(dataModelEvent);
|
||||||
Script.AddNode(node);
|
}
|
||||||
|
|
||||||
|
if (_eventNode.Pins.Any() && !Script.Nodes.Contains(_eventNode))
|
||||||
|
Script.AddNode(_eventNode);
|
||||||
|
else
|
||||||
|
Script.RemoveNode(_eventNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool Evaluate()
|
||||||
|
{
|
||||||
|
if (EventPath?.GetValue() is not IDataModelEvent dataModelEvent || dataModelEvent.LastTrigger <= _lastProcessedTrigger)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
_lastProcessedTrigger = dataModelEvent.LastTrigger;
|
||||||
|
if (!Script.ExitNodeConnected)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
Script.Run();
|
||||||
|
return Script.Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public IConditionEntity Entity => _entity;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public ProfileElement ProfileElement { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public bool IsMet { get; private set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
if (EventOverlapMode == TimeLineEventOverlapMode.Toggle)
|
||||||
|
{
|
||||||
|
if (Evaluate())
|
||||||
|
IsMet = !IsMet;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IsMet = Evaluate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Implementation of IStorageModel
|
/// <inheritdoc />
|
||||||
|
public void ApplyToTimeline(bool isMet, bool wasMet, Timeline timeline)
|
||||||
|
{
|
||||||
|
if (!isMet)
|
||||||
|
{
|
||||||
|
if (EventOverlapMode == TimeLineEventOverlapMode.Toggle)
|
||||||
|
timeline.JumpToEnd();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Event overlap mode doesn't apply in this case
|
||||||
|
if (timeline.IsFinished)
|
||||||
|
{
|
||||||
|
timeline.JumpToStart();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the timeline was already running, look at the event overlap mode
|
||||||
|
if (EventOverlapMode == TimeLineEventOverlapMode.Restart)
|
||||||
|
timeline.JumpToStart();
|
||||||
|
else if (EventOverlapMode == TimeLineEventOverlapMode.Copy)
|
||||||
|
timeline.AddExtraTimeline();
|
||||||
|
else if (EventOverlapMode == TimeLineEventOverlapMode.Toggle && !wasMet)
|
||||||
|
timeline.JumpToStart();
|
||||||
|
|
||||||
|
// The remaining overlap mode is 'ignore' which requires no further action
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Script.Dispose();
|
||||||
|
EventPath?.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Storage
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void Load()
|
public void Load()
|
||||||
{
|
{
|
||||||
EventPath = new DataModelPath(null, Entity.EventPath);
|
EventOverlapMode = (TimeLineEventOverlapMode) _entity.EventOverlapMode;
|
||||||
Script = new NodeScript<bool>($"Activate {_displayName}", $"Whether or not the event should activate the {_displayName}", Entity.Script, _context);
|
Script = new NodeScript<bool>($"Activate {_displayName}", $"Whether or not the event should activate the {_displayName}", _entity.Script, ProfileElement.Profile);
|
||||||
UpdateEventNode();
|
EventPath = new DataModelPath(_entity.EventPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void Save()
|
public void Save()
|
||||||
{
|
{
|
||||||
EventPath?.Save();
|
_entity.EventOverlapMode = (int) EventOverlapMode;
|
||||||
Entity.EventPath = EventPath?.Entity;
|
|
||||||
Script.Save();
|
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
|
#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 Artemis.Storage.Entities.Profile.Abstract;
|
||||||
using System.Linq;
|
|
||||||
using Artemis.Storage.Entities.Profile.Abstract;
|
|
||||||
using Artemis.Storage.Entities.Profile.Conditions;
|
using Artemis.Storage.Entities.Profile.Conditions;
|
||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
@ -8,19 +6,21 @@ namespace Artemis.Core
|
|||||||
public class StaticCondition : CorePropertyChanged, INodeScriptCondition
|
public class StaticCondition : CorePropertyChanged, INodeScriptCondition
|
||||||
{
|
{
|
||||||
private readonly StaticConditionEntity _entity;
|
private readonly StaticConditionEntity _entity;
|
||||||
|
private readonly string _displayName;
|
||||||
|
|
||||||
public StaticCondition(ProfileElement profileElement)
|
public StaticCondition(ProfileElement profileElement)
|
||||||
{
|
{
|
||||||
_entity = new StaticConditionEntity();
|
_entity = new StaticConditionEntity();
|
||||||
|
_displayName = profileElement.GetType().Name;
|
||||||
|
|
||||||
ProfileElement = profileElement;
|
ProfileElement = profileElement;
|
||||||
string typeDisplayName = profileElement.GetType().Name.ToLower();
|
Script = new NodeScript<bool>($"Activate {_displayName}", $"Whether or not this {_displayName} should be active", profileElement.Profile);
|
||||||
Script = new NodeScript<bool>($"Activate {typeDisplayName}", $"Whether or not this {typeDisplayName} should be active", profileElement.Profile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal StaticCondition(StaticConditionEntity entity, ProfileElement profileElement)
|
internal StaticCondition(StaticConditionEntity entity, ProfileElement profileElement)
|
||||||
{
|
{
|
||||||
_entity = entity;
|
_entity = entity;
|
||||||
|
_displayName = profileElement.GetType().Name;
|
||||||
|
|
||||||
ProfileElement = profileElement;
|
ProfileElement = profileElement;
|
||||||
Script = null!;
|
Script = null!;
|
||||||
@ -45,7 +45,7 @@ namespace Artemis.Core
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void Update()
|
public void Update()
|
||||||
{
|
{
|
||||||
if (!Script.HasNodes)
|
if (!Script.ExitNodeConnected)
|
||||||
{
|
{
|
||||||
IsMet = true;
|
IsMet = true;
|
||||||
return;
|
return;
|
||||||
@ -64,23 +64,18 @@ namespace Artemis.Core
|
|||||||
timeline.JumpToEndSegment();
|
timeline.JumpToEndSegment();
|
||||||
}
|
}
|
||||||
|
|
||||||
#region IDisposable
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
Script.Dispose();
|
Script.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Storage
|
#region Storage
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void Load()
|
public void Load()
|
||||||
{
|
{
|
||||||
string typeDisplayName = ProfileElement.GetType().Name.ToLower();
|
Script = new NodeScript<bool>($"Activate {_displayName}", $"Whether or not this {_displayName} should be active", _entity.Script, ProfileElement.Profile);
|
||||||
Script = new NodeScript<bool>($"Activate {typeDisplayName}", $"Whether or not this {typeDisplayName} should be active", _entity.Script, ProfileElement.Profile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@ -12,13 +12,14 @@ namespace Artemis.Core
|
|||||||
private readonly List<IDataBindingProperty> _properties = new();
|
private readonly List<IDataBindingProperty> _properties = new();
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
private bool _isEnabled;
|
private bool _isEnabled;
|
||||||
|
private DataBindingNodeScript<TLayerProperty> _script;
|
||||||
|
|
||||||
internal DataBinding(LayerProperty<TLayerProperty> layerProperty)
|
internal DataBinding(LayerProperty<TLayerProperty> layerProperty)
|
||||||
{
|
{
|
||||||
LayerProperty = layerProperty;
|
LayerProperty = layerProperty;
|
||||||
|
|
||||||
Entity = new DataBindingEntity();
|
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();
|
Save();
|
||||||
}
|
}
|
||||||
@ -28,7 +29,7 @@ namespace Artemis.Core
|
|||||||
LayerProperty = layerProperty;
|
LayerProperty = layerProperty;
|
||||||
|
|
||||||
Entity = entity;
|
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 will add children so be initialized before that
|
||||||
Load();
|
Load();
|
||||||
@ -42,7 +43,7 @@ namespace Artemis.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the script used to populate the data binding
|
/// Gets the script used to populate the data binding
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DataBindingNodeScript<TLayerProperty> Script { get; private set; }
|
public INodeScript Script => _script;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the data binding entity this data binding uses for persistent storage
|
/// Gets the data binding entity this data binding uses for persistent storage
|
||||||
@ -183,7 +184,7 @@ namespace Artemis.Core
|
|||||||
if (!IsEnabled)
|
if (!IsEnabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Script.DataBindingExitNode.ApplyToDataBinding();
|
_script.DataBindingExitNode.ApplyToDataBinding();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -220,8 +221,8 @@ namespace Artemis.Core
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void LoadNodeScript()
|
public void LoadNodeScript()
|
||||||
{
|
{
|
||||||
Script.Dispose();
|
_script.Dispose();
|
||||||
Script = Entity.NodeScript != null
|
_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, Entity.NodeScript, LayerProperty.ProfileElement.Profile)
|
||||||
: new DataBindingNodeScript<TLayerProperty>(GetScriptName(), "The value to put into the data binding", this, 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)
|
if (_disposed)
|
||||||
throw new ObjectDisposedException("DataBinding");
|
throw new ObjectDisposedException("DataBinding");
|
||||||
|
|
||||||
Script.Save();
|
_script.Save();
|
||||||
Entity.IsEnabled = IsEnabled;
|
Entity.IsEnabled = IsEnabled;
|
||||||
Entity.NodeScript = Script.Entity.Nodes.Any() ? Script.Entity : null;
|
Entity.NodeScript = _script.Entity.Nodes.Any() ? _script.Entity : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@ -75,11 +75,9 @@ namespace Artemis.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new instance of the <see cref="DataModelPath" /> class based on a <see cref="DataModelPathEntity" />
|
/// Creates a new instance of the <see cref="DataModelPath" /> class based on a <see cref="DataModelPathEntity" />
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="target"></param>
|
|
||||||
/// <param name="entity"></param>
|
/// <param name="entity"></param>
|
||||||
public DataModelPath(DataModel? target, DataModelPathEntity entity)
|
public DataModelPath(DataModelPathEntity entity)
|
||||||
{
|
{
|
||||||
Target = target;
|
|
||||||
Path = entity.Path;
|
Path = entity.Path;
|
||||||
Entity = entity;
|
Entity = entity;
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,7 @@ using Artemis.Core.LayerEffects.Placeholder;
|
|||||||
using Artemis.Core.Properties;
|
using Artemis.Core.Properties;
|
||||||
using Artemis.Storage.Entities.Profile;
|
using Artemis.Storage.Entities.Profile;
|
||||||
using Artemis.Storage.Entities.Profile.Abstract;
|
using Artemis.Storage.Entities.Profile.Abstract;
|
||||||
|
using Artemis.Storage.Entities.Profile.Conditions;
|
||||||
using SkiaSharp;
|
using SkiaSharp;
|
||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
@ -72,6 +73,13 @@ namespace Artemis.Core
|
|||||||
? new Timeline(RenderElementEntity.Timeline)
|
? new Timeline(RenderElementEntity.Timeline)
|
||||||
: new Timeline();
|
: new Timeline();
|
||||||
|
|
||||||
|
DisplayCondition = RenderElementEntity.DisplayCondition switch
|
||||||
|
{
|
||||||
|
StaticConditionEntity staticConditionEntity => new StaticCondition(staticConditionEntity, this),
|
||||||
|
EventConditionEntity eventConditionEntity => new EventCondition(eventConditionEntity, this),
|
||||||
|
_ => DisplayCondition
|
||||||
|
};
|
||||||
|
|
||||||
ActivateEffects();
|
ActivateEffects();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,10 +138,10 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void UpdateTimeline(double deltaTime)
|
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
|
// 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;
|
bool stickToMainSegment = Timeline.PlayMode == TimelinePlayMode.Repeat && DisplayConditionMet;
|
||||||
// if (DisplayCondition != null && DisplayCondition.ContainsEvents && Timeline.EventOverlapMode != TimeLineEventOverlapMode.Toggle)
|
|
||||||
// stickToMainSegment = false;
|
|
||||||
|
|
||||||
Timeline.Update(TimeSpan.FromSeconds(deltaTime), stickToMainSegment);
|
Timeline.Update(TimeSpan.FromSeconds(deltaTime), stickToMainSegment);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,7 +13,7 @@ namespace Artemis.Core
|
|||||||
public class Timeline : CorePropertyChanged, IStorageModel
|
public class Timeline : CorePropertyChanged, IStorageModel
|
||||||
{
|
{
|
||||||
private const int MaxExtraTimelines = 15;
|
private const int MaxExtraTimelines = 15;
|
||||||
private readonly object _lock = new ();
|
private readonly object _lock = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new instance of the <see cref="Timeline" /> class
|
/// Creates a new instance of the <see cref="Timeline" /> class
|
||||||
@ -24,7 +24,7 @@ namespace Artemis.Core
|
|||||||
MainSegmentLength = TimeSpan.FromSeconds(5);
|
MainSegmentLength = TimeSpan.FromSeconds(5);
|
||||||
|
|
||||||
_extraTimelines = new List<Timeline>();
|
_extraTimelines = new List<Timeline>();
|
||||||
ExtraTimelines = new(_extraTimelines);
|
ExtraTimelines = new ReadOnlyCollection<Timeline>(_extraTimelines);
|
||||||
|
|
||||||
Save();
|
Save();
|
||||||
}
|
}
|
||||||
@ -33,7 +33,7 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
Entity = entity;
|
Entity = entity;
|
||||||
_extraTimelines = new List<Timeline>();
|
_extraTimelines = new List<Timeline>();
|
||||||
ExtraTimelines = new(_extraTimelines);
|
ExtraTimelines = new ReadOnlyCollection<Timeline>(_extraTimelines);
|
||||||
|
|
||||||
Load();
|
Load();
|
||||||
}
|
}
|
||||||
@ -47,7 +47,7 @@ namespace Artemis.Core
|
|||||||
EndSegmentLength = Parent.EndSegmentLength;
|
EndSegmentLength = Parent.EndSegmentLength;
|
||||||
|
|
||||||
_extraTimelines = new List<Timeline>();
|
_extraTimelines = new List<Timeline>();
|
||||||
ExtraTimelines = new(_extraTimelines);
|
ExtraTimelines = new ReadOnlyCollection<Timeline>(_extraTimelines);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -140,16 +140,6 @@ namespace Artemis.Core
|
|||||||
set => SetAndNotify(ref _stopMode, value);
|
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>
|
/// <summary>
|
||||||
/// Gets a list of extra copies of the timeline applied to this timeline
|
/// Gets a list of extra copies of the timeline applied to this timeline
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -445,7 +435,8 @@ namespace Artemis.Core
|
|||||||
EndSegmentLength = Entity.EndSegmentLength;
|
EndSegmentLength = Entity.EndSegmentLength;
|
||||||
PlayMode = (TimelinePlayMode) Entity.PlayMode;
|
PlayMode = (TimelinePlayMode) Entity.PlayMode;
|
||||||
StopMode = (TimelineStopMode) Entity.StopMode;
|
StopMode = (TimelineStopMode) Entity.StopMode;
|
||||||
EventOverlapMode = (TimeLineEventOverlapMode) Entity.EventOverlapMode;
|
|
||||||
|
JumpToEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -456,7 +447,6 @@ namespace Artemis.Core
|
|||||||
Entity.EndSegmentLength = EndSegmentLength;
|
Entity.EndSegmentLength = EndSegmentLength;
|
||||||
Entity.PlayMode = (int) PlayMode;
|
Entity.PlayMode = (int) PlayMode;
|
||||||
Entity.StopMode = (int) StopMode;
|
Entity.StopMode = (int) StopMode;
|
||||||
Entity.EventOverlapMode = (int) EventOverlapMode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@ -171,7 +171,7 @@ namespace Artemis.Core
|
|||||||
if (_disposed)
|
if (_disposed)
|
||||||
throw new ObjectDisposedException("ProfileConfiguration");
|
throw new ObjectDisposedException("ProfileConfiguration");
|
||||||
|
|
||||||
if (!ActivationCondition.HasNodes)
|
if (!ActivationCondition.ExitNodeConnected)
|
||||||
ActivationConditionMet = true;
|
ActivationConditionMet = true;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,15 +1,19 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using Artemis.Core.Internal;
|
using Artemis.Core.Internal;
|
||||||
using Artemis.Storage.Entities.Profile.Nodes;
|
using Artemis.Storage.Entities.Profile.Nodes;
|
||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
public class DataBindingNodeScript<TLayerProperty> : NodeScript
|
internal class DataBindingNodeScript<TLayerProperty> : NodeScript
|
||||||
{
|
{
|
||||||
#region Properties & Fields
|
#region Properties & Fields
|
||||||
|
|
||||||
internal DataBindingExitNode<TLayerProperty> DataBindingExitNode { get; }
|
internal DataBindingExitNode<TLayerProperty> DataBindingExitNode { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool ExitNodeConnected => DataBindingExitNode.Pins.Any(p => p.ConnectedTo.Any());
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Type ResultType => typeof(object);
|
public override Type ResultType => typeof(object);
|
||||||
|
|
||||||
|
|||||||
@ -9,7 +9,6 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
string Name { get; }
|
string Name { get; }
|
||||||
string Description { get; }
|
string Description { get; }
|
||||||
bool HasNodes { get; }
|
|
||||||
|
|
||||||
IEnumerable<INode> Nodes { get; }
|
IEnumerable<INode> Nodes { get; }
|
||||||
|
|
||||||
|
|||||||
@ -1,20 +1,23 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using Artemis.Core.Modules;
|
||||||
using Humanizer;
|
using Humanizer;
|
||||||
|
|
||||||
namespace Artemis.Core.Internal
|
namespace Artemis.Core.Internal
|
||||||
{
|
{
|
||||||
internal class EventStartNode : Node
|
internal class EventDefaultNode : Node
|
||||||
{
|
{
|
||||||
private IDataModelEvent? _dataModelEvent;
|
|
||||||
private readonly Dictionary<PropertyInfo, OutputPin> _propertyPins;
|
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>();
|
_propertyPins = new Dictionary<PropertyInfo, OutputPin>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool IsDefaultNode => true;
|
||||||
|
|
||||||
public void UpdateDataModelEvent(IDataModelEvent dataModelEvent)
|
public void UpdateDataModelEvent(IDataModelEvent dataModelEvent)
|
||||||
{
|
{
|
||||||
if (_dataModelEvent == dataModelEvent)
|
if (_dataModelEvent == dataModelEvent)
|
||||||
@ -25,13 +28,11 @@ namespace Artemis.Core.Internal
|
|||||||
_propertyPins.Clear();
|
_propertyPins.Clear();
|
||||||
|
|
||||||
_dataModelEvent = dataModelEvent;
|
_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()));
|
_propertyPins.Add(propertyInfo, CreateOutputPin(propertyInfo.PropertyType, propertyInfo.Name.Humanize()));
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Overrides of Node
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override void Evaluate()
|
public override void Evaluate()
|
||||||
{
|
{
|
||||||
if (_dataModelEvent?.LastEventArgumentsUntyped == null)
|
if (_dataModelEvent?.LastEventArgumentsUntyped == null)
|
||||||
@ -43,7 +44,5 @@ namespace Artemis.Core.Internal
|
|||||||
outputPin.Value = propertyInfo.GetValue(_dataModelEvent.LastEventArgumentsUntyped) ?? outputPin.Type.GetDefault()!;
|
outputPin.Value = propertyInfo.GetValue(_dataModelEvent.LastEventArgumentsUntyped) ?? outputPin.Type.GetDefault()!;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -25,12 +25,12 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
public string Description { get; }
|
public string Description { get; }
|
||||||
public bool HasNodes => _nodes.Count > 1;
|
|
||||||
|
|
||||||
private readonly List<INode> _nodes = new();
|
private readonly List<INode> _nodes = new();
|
||||||
public IEnumerable<INode> Nodes => new ReadOnlyCollection<INode>(_nodes);
|
public IEnumerable<INode> Nodes => new ReadOnlyCollection<INode>(_nodes);
|
||||||
|
|
||||||
protected INode ExitNode { get; set; }
|
protected INode ExitNode { get; set; }
|
||||||
|
public abstract bool ExitNodeConnected { get; }
|
||||||
public abstract Type ResultType { get; }
|
public abstract Type ResultType { get; }
|
||||||
|
|
||||||
public object? Context { get; set; }
|
public object? Context { get; set; }
|
||||||
@ -149,7 +149,7 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
IPinCollection? collection = node.PinCollections.FirstOrDefault(c => c.Name == entityNodePinCollection.Name &&
|
IPinCollection? collection = node.PinCollections.FirstOrDefault(c => c.Name == entityNodePinCollection.Name &&
|
||||||
c.Type.Name == entityNodePinCollection.Type &&
|
c.Type.Name == entityNodePinCollection.Type &&
|
||||||
(int)c.Direction == entityNodePinCollection.Direction);
|
(int) c.Direction == entityNodePinCollection.Direction);
|
||||||
if (collection == null)
|
if (collection == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -231,7 +231,7 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
Name = nodePinCollection.Name,
|
Name = nodePinCollection.Name,
|
||||||
Type = nodePinCollection.Type.Name,
|
Type = nodePinCollection.Type.Name,
|
||||||
Direction = (int)nodePinCollection.Direction,
|
Direction = (int) nodePinCollection.Direction,
|
||||||
Amount = nodePinCollection.Count()
|
Amount = nodePinCollection.Count()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -301,8 +301,9 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
#region Properties & Fields
|
#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);
|
public override Type ResultType => typeof(T);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@ -1,17 +1,11 @@
|
|||||||
using System.Collections.Generic;
|
using Artemis.Storage.Entities.Profile.Abstract;
|
||||||
using Artemis.Storage.Entities.Profile.Abstract;
|
|
||||||
using Artemis.Storage.Entities.Profile.Nodes;
|
using Artemis.Storage.Entities.Profile.Nodes;
|
||||||
|
|
||||||
namespace Artemis.Storage.Entities.Profile.Conditions
|
namespace Artemis.Storage.Entities.Profile.Conditions
|
||||||
{
|
{
|
||||||
public class EventsConditionEntity : IConditionEntity
|
public class EventConditionEntity : IConditionEntity
|
||||||
{
|
{
|
||||||
public int EventOverlapMode { get; set; }
|
public int EventOverlapMode { get; set; }
|
||||||
public List<EventConditionEntity> Events { get; set; } = new();
|
|
||||||
}
|
|
||||||
|
|
||||||
public class EventConditionEntity
|
|
||||||
{
|
|
||||||
public DataModelPathEntity EventPath { get; set; }
|
public DataModelPathEntity EventPath { get; set; }
|
||||||
public NodeScriptEntity Script { get; set; }
|
public NodeScriptEntity Script { get; set; }
|
||||||
}
|
}
|
||||||
@ -10,6 +10,5 @@ namespace Artemis.Storage.Entities.Profile
|
|||||||
|
|
||||||
public int PlayMode { get; set; }
|
public int PlayMode { get; set; }
|
||||||
public int StopMode { get; set; }
|
public int StopMode { get; set; }
|
||||||
public int EventOverlapMode { get; set; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -97,7 +97,6 @@ namespace Artemis.UI.Ninject.Factories
|
|||||||
public interface IConditionVmFactory : IVmFactory
|
public interface IConditionVmFactory : IVmFactory
|
||||||
{
|
{
|
||||||
StaticConditionViewModel StaticConditionViewModel(StaticCondition staticCondition);
|
StaticConditionViewModel StaticConditionViewModel(StaticCondition staticCondition);
|
||||||
EventsConditionViewModel EventsConditionViewModel(EventsCondition eventsCondition);
|
|
||||||
EventConditionViewModel EventConditionViewModel(EventCondition eventCondition);
|
EventConditionViewModel EventConditionViewModel(EventCondition eventCondition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -81,13 +81,13 @@
|
|||||||
<RadioButton.ToolTip>
|
<RadioButton.ToolTip>
|
||||||
<ToolTip Placement="Center" VerticalOffset="-40">
|
<ToolTip Placement="Center" VerticalOffset="-40">
|
||||||
<TextBlock>
|
<TextBlock>
|
||||||
A condition that checks whenever one or more events fire and acts in a configurable way
|
A condition triggers on a selectable event
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
</ToolTip>
|
</ToolTip>
|
||||||
</RadioButton.ToolTip>
|
</RadioButton.ToolTip>
|
||||||
<TextBlock VerticalAlignment="Center" FontSize="12">
|
<TextBlock VerticalAlignment="Center" FontSize="12">
|
||||||
<materialDesign:PackIcon Kind="LightningBolt" VerticalAlignment="Center" Margin="0 0 2 -3" />
|
<materialDesign:PackIcon Kind="LightningBolt" VerticalAlignment="Center" Margin="0 0 2 -3" />
|
||||||
EVENTS
|
EVENT
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
</RadioButton>
|
</RadioButton>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@ -50,7 +50,7 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
|||||||
if (DisplayConditionType == DisplayConditionType.Static)
|
if (DisplayConditionType == DisplayConditionType.Static)
|
||||||
_profileEditorService.SelectedProfileElement.ChangeDisplayCondition(new StaticCondition(_profileEditorService.SelectedProfileElement));
|
_profileEditorService.SelectedProfileElement.ChangeDisplayCondition(new StaticCondition(_profileEditorService.SelectedProfileElement));
|
||||||
else if (DisplayConditionType == DisplayConditionType.Events)
|
else if (DisplayConditionType == DisplayConditionType.Events)
|
||||||
_profileEditorService.SelectedProfileElement.ChangeDisplayCondition(new EventsCondition(_profileEditorService.SelectedProfileElement));
|
_profileEditorService.SelectedProfileElement.ChangeDisplayCondition(new EventCondition(_profileEditorService.SelectedProfileElement));
|
||||||
else
|
else
|
||||||
_profileEditorService.SelectedProfileElement.ChangeDisplayCondition(null);
|
_profileEditorService.SelectedProfileElement.ChangeDisplayCondition(null);
|
||||||
|
|
||||||
@ -71,9 +71,9 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
|||||||
ActiveItem = _conditionVmFactory.StaticConditionViewModel(staticCondition);
|
ActiveItem = _conditionVmFactory.StaticConditionViewModel(staticCondition);
|
||||||
_displayConditionType = DisplayConditionType.Static;
|
_displayConditionType = DisplayConditionType.Static;
|
||||||
}
|
}
|
||||||
else if (renderProfileElement.DisplayCondition is EventsCondition eventsCondition)
|
else if (renderProfileElement.DisplayCondition is EventCondition eventsCondition)
|
||||||
{
|
{
|
||||||
ActiveItem = _conditionVmFactory.EventsConditionViewModel(eventsCondition);
|
ActiveItem = _conditionVmFactory.EventConditionViewModel(eventsCondition);
|
||||||
_displayConditionType = DisplayConditionType.Events;
|
_displayConditionType = DisplayConditionType.Events;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@ -4,43 +4,45 @@
|
|||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:local="clr-namespace:Artemis.UI.Screens.ProfileEditor.DisplayConditions.Event"
|
xmlns:local="clr-namespace:Artemis.UI.Screens.ProfileEditor.DisplayConditions.Event"
|
||||||
|
xmlns:converters="clr-namespace:Artemis.UI.Converters"
|
||||||
xmlns:s="https://github.com/canton7/Stylet"
|
xmlns:s="https://github.com/canton7/Stylet"
|
||||||
xmlns:controls="clr-namespace:Artemis.VisualScripting.Editor.Controls;assembly=Artemis.VisualScripting"
|
xmlns:controls="clr-namespace:Artemis.VisualScripting.Editor.Controls;assembly=Artemis.VisualScripting"
|
||||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||||
xmlns:shared="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared"
|
xmlns:core="clr-namespace:Artemis.Core;assembly=Artemis.Core"
|
||||||
|
xmlns:controls1="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DesignHeight="450" d:DesignWidth="800"
|
d:DesignHeight="450" d:DesignWidth="800"
|
||||||
d:DataContext="{d:DesignInstance {x:Type local:EventConditionViewModel}}">
|
d:DataContext="{d:DesignInstance {x:Type local:EventConditionViewModel}}">
|
||||||
|
<UserControl.Resources>
|
||||||
|
<converters:ComparisonConverter x:Key="ComparisonConverter" />
|
||||||
|
</UserControl.Resources>
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<ColumnDefinition />
|
<RowDefinition Height="*" />
|
||||||
<ColumnDefinition />
|
<RowDefinition Height="22" />
|
||||||
</Grid.ColumnDefinitions>
|
<RowDefinition Height="Auto" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<Grid Grid.Row="0" VerticalAlignment="Stretch">
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="*" />
|
<RowDefinition Height="*" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
<shared:DataModelPicker Grid.Row="0"
|
<controls1:DataModelPicker Grid.Row="0"
|
||||||
Grid.Column="0"
|
Margin="0 0 0 5"
|
||||||
Margin="0 5"
|
|
||||||
ButtonBrush="DarkGoldenrod"
|
ButtonBrush="DarkGoldenrod"
|
||||||
DataModelPath="{Binding EventCondition.EventPath}"
|
DataModelPath="{Binding EventCondition.EventPath}"
|
||||||
DataModelPathSelected="{s:Action DataModelPathSelected}"
|
DataModelPathSelected="{s:Action DataModelPathSelected}"
|
||||||
FilterTypes="{Binding FilterTypes}"
|
FilterTypes="{Binding FilterTypes}"
|
||||||
|
ShowFullPath="True"
|
||||||
Modules="{Binding Modules}" />
|
Modules="{Binding Modules}" />
|
||||||
<Button Grid.Row="0"
|
|
||||||
Grid.Column="1"
|
|
||||||
Margin="0 5"
|
|
||||||
Command="{s:Action AddEvent}"
|
|
||||||
s:View.ActionTarget="{Binding Parent}"
|
|
||||||
Content="ADD EVENT" />
|
|
||||||
|
|
||||||
<Grid Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" MouseUp="{s:Action ScriptGridMouseUp}" Cursor="Hand">
|
<Grid Grid.Row="1" MouseUp="{s:Action ScriptGridMouseUp}" Cursor="Hand">
|
||||||
<controls:VisualScriptPresenter Script="{Binding EventCondition.Script}" AutoFitScript="True" />
|
<controls:VisualScriptPresenter Script="{Binding EventCondition.Script}" AutoFitScript="True" />
|
||||||
<Border VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
|
<Border VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
|
||||||
<Border.Background>
|
<Border.Background>
|
||||||
<SolidColorBrush Color="{Binding Color, Source={StaticResource MaterialDesignPaper}}" Opacity="0.75" />
|
<SolidColorBrush Color="{Binding Color, Source={StaticResource MaterialDesignCardBackground}}" Opacity="0.75" />
|
||||||
</Border.Background>
|
</Border.Background>
|
||||||
<Border.Style>
|
<Border.Style>
|
||||||
<Style>
|
<Style>
|
||||||
@ -64,18 +66,101 @@
|
|||||||
</Style.Triggers>
|
</Style.Triggers>
|
||||||
</Style>
|
</Style>
|
||||||
</Border.Style>
|
</Border.Style>
|
||||||
<Grid HorizontalAlignment="Center">
|
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||||
<Grid.ColumnDefinitions>
|
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||||
<ColumnDefinition />
|
<TextBlock Style="{StaticResource MaterialDesignHeadline5TextBlock}" VerticalAlignment="Center">
|
||||||
<ColumnDefinition />
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<TextBlock Style="{StaticResource MaterialDesignHeadline5TextBlock}" VerticalAlignment="Center" Grid.Column="0">
|
|
||||||
Click to edit script
|
Click to edit script
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
<materialDesign:PackIcon Kind="OpenInNew" Margin="10 " Width="30" Height="30" Grid.Column="1" VerticalAlignment="Center" />
|
<materialDesign:PackIcon Kind="OpenInNew" Margin="10 " Width="30" Height="30" VerticalAlignment="Center" />
|
||||||
</Grid>
|
</StackPanel>
|
||||||
|
<TextBlock Style="{StaticResource MaterialDesignSubtitle1TextBlock}" TextWrapping="Wrap" TextAlignment="Center">
|
||||||
|
Scripts with nothing connected to their end-node are always true.
|
||||||
|
</TextBlock>
|
||||||
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
|
<!-- Trigger mode -->
|
||||||
|
<TextBlock Grid.Row="1" Grid.Column="0" Text="Trigger mode" VerticalAlignment="Center">
|
||||||
|
<TextBlock.ToolTip>
|
||||||
|
<ToolTip Placement="Center" VerticalOffset="-30">
|
||||||
|
<TextBlock>
|
||||||
|
Configure how the layer should act when the event(s) trigger
|
||||||
|
</TextBlock>
|
||||||
|
</ToolTip>
|
||||||
|
</TextBlock.ToolTip>
|
||||||
|
</TextBlock>
|
||||||
|
|
||||||
|
<materialDesign:ColorZone Grid.Row="2" Grid.Column="0" Mode="Standard" CornerRadius="3">
|
||||||
|
<Grid HorizontalAlignment="Stretch">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition />
|
||||||
|
<ColumnDefinition />
|
||||||
|
<ColumnDefinition />
|
||||||
|
<ColumnDefinition />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<RadioButton Grid.Column="0"
|
||||||
|
Style="{StaticResource MaterialDesignTabRadioButton}"
|
||||||
|
IsChecked="{Binding Path=EventOverlapMode, Converter={StaticResource ComparisonConverter}, ConverterParameter={x:Static core:TimeLineEventOverlapMode.Restart}}">
|
||||||
|
<TextBlock VerticalAlignment="Center" FontSize="12">
|
||||||
|
<materialDesign:PackIcon Kind="Repeat" VerticalAlignment="Center" Margin="-3 0 0 -3" />
|
||||||
|
RESTART
|
||||||
|
</TextBlock>
|
||||||
|
<RadioButton.ToolTip>
|
||||||
|
<ToolTip Placement="Center" VerticalOffset="-40">
|
||||||
|
<TextBlock>
|
||||||
|
Stop the current run and restart the timeline
|
||||||
|
</TextBlock>
|
||||||
|
</ToolTip>
|
||||||
|
</RadioButton.ToolTip>
|
||||||
|
</RadioButton>
|
||||||
|
<RadioButton Grid.Column="1"
|
||||||
|
Style="{StaticResource MaterialDesignTabRadioButton}"
|
||||||
|
IsChecked="{Binding Path=EventOverlapMode, Converter={StaticResource ComparisonConverter}, ConverterParameter={x:Static core:TimeLineEventOverlapMode.Toggle}}">
|
||||||
|
<TextBlock VerticalAlignment="Center" FontSize="12">
|
||||||
|
<materialDesign:PackIcon Kind="TrafficLight" VerticalAlignment="Center" Margin="-3 0 0 -3" />
|
||||||
|
TOGGLE
|
||||||
|
</TextBlock>
|
||||||
|
<RadioButton.ToolTip>
|
||||||
|
<ToolTip Placement="Center" VerticalOffset="-40">
|
||||||
|
<TextBlock>
|
||||||
|
Repeat the timeline until the event fires again
|
||||||
|
</TextBlock>
|
||||||
|
</ToolTip>
|
||||||
|
</RadioButton.ToolTip>
|
||||||
|
</RadioButton>
|
||||||
|
<RadioButton Grid.Column="2"
|
||||||
|
Style="{StaticResource MaterialDesignTabRadioButton}"
|
||||||
|
IsChecked="{Binding Path=EventOverlapMode, Converter={StaticResource ComparisonConverter}, ConverterParameter={x:Static core:TimeLineEventOverlapMode.Ignore}}">
|
||||||
|
<TextBlock VerticalAlignment="Center" FontSize="12">
|
||||||
|
<materialDesign:PackIcon Kind="EarHearingOff" VerticalAlignment="Center" Margin="-3 0 0 -3" />
|
||||||
|
IGNORE
|
||||||
|
</TextBlock>
|
||||||
|
<RadioButton.ToolTip>
|
||||||
|
<ToolTip Placement="Center" VerticalOffset="-40">
|
||||||
|
<TextBlock>
|
||||||
|
Ignore subsequent event fires until the timeline finishes
|
||||||
|
</TextBlock>
|
||||||
|
</ToolTip>
|
||||||
|
</RadioButton.ToolTip>
|
||||||
|
</RadioButton>
|
||||||
|
<RadioButton Grid.Column="3"
|
||||||
|
Style="{StaticResource MaterialDesignTabRadioButton}"
|
||||||
|
IsChecked="{Binding Path=EventOverlapMode, Converter={StaticResource ComparisonConverter}, ConverterParameter={x:Static core:TimeLineEventOverlapMode.Copy}}">
|
||||||
|
<TextBlock VerticalAlignment="Center" FontSize="12">
|
||||||
|
<materialDesign:PackIcon Kind="ContentCopy" VerticalAlignment="Center" Margin="-3 0 0 -3" />
|
||||||
|
COPY
|
||||||
|
</TextBlock>
|
||||||
|
<RadioButton.ToolTip>
|
||||||
|
<ToolTip Placement="Center" VerticalOffset="-40">
|
||||||
|
<TextBlock>
|
||||||
|
Play another copy of the timeline on top of the current run
|
||||||
|
</TextBlock>
|
||||||
|
</ToolTip>
|
||||||
|
</RadioButton.ToolTip>
|
||||||
|
</RadioButton>
|
||||||
|
</Grid>
|
||||||
|
</materialDesign:ColorZone>
|
||||||
|
</Grid>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Specialized;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
@ -13,33 +12,31 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions.Event
|
|||||||
{
|
{
|
||||||
public class EventConditionViewModel : Screen
|
public class EventConditionViewModel : Screen
|
||||||
{
|
{
|
||||||
private readonly INodeVmFactory _nodeVmFactory;
|
|
||||||
private readonly IProfileEditorService _profileEditorService;
|
private readonly IProfileEditorService _profileEditorService;
|
||||||
private readonly IWindowManager _windowManager;
|
private readonly IWindowManager _windowManager;
|
||||||
|
private readonly INodeVmFactory _nodeVmFactory;
|
||||||
|
|
||||||
public EventConditionViewModel(EventCondition eventCondition, IWindowManager windowManager, INodeVmFactory nodeVmFactory, IProfileEditorService profileEditorService)
|
public EventConditionViewModel(EventCondition eventCondition, IProfileEditorService profileEditorService, IWindowManager windowManager, INodeVmFactory nodeVmFactory)
|
||||||
{
|
{
|
||||||
|
_profileEditorService = profileEditorService;
|
||||||
_windowManager = windowManager;
|
_windowManager = windowManager;
|
||||||
_nodeVmFactory = nodeVmFactory;
|
_nodeVmFactory = nodeVmFactory;
|
||||||
_profileEditorService = profileEditorService;
|
|
||||||
|
|
||||||
EventCondition = eventCondition;
|
EventCondition = eventCondition;
|
||||||
DisplayName = EventCondition.EventPath?.Segments.LastOrDefault()?.GetPropertyDescription()?.Name ?? "Invalid event";
|
|
||||||
FilterTypes = new BindableCollection<Type> {typeof(IDataModelEvent) };
|
|
||||||
Modules = new BindableCollection<Module>();
|
|
||||||
|
|
||||||
if (_profileEditorService.SelectedProfileConfiguration?.Module != null)
|
|
||||||
Modules.Add(_profileEditorService.SelectedProfileConfiguration.Module);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public EventCondition EventCondition { get; }
|
public EventCondition EventCondition { get; }
|
||||||
public BindableCollection<Type> FilterTypes { get; }
|
public BindableCollection<Type> FilterTypes { get; }
|
||||||
public BindableCollection<Module> Modules { get; }
|
public BindableCollection<Module> Modules { get; }
|
||||||
public bool CanDeleteEvent => ((EventsConditionViewModel) Parent).Items.Count > 1;
|
|
||||||
|
|
||||||
public void DeleteEvent()
|
public TimeLineEventOverlapMode EventOverlapMode
|
||||||
{
|
{
|
||||||
((EventsConditionViewModel) Parent).DeleteEvent(this);
|
get => EventCondition.EventOverlapMode;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (EventCondition.EventOverlapMode == value) return;
|
||||||
|
EventCondition.EventOverlapMode = value;
|
||||||
|
_profileEditorService.SaveSelectedProfileElement();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DataModelPathSelected(object sender, DataModelSelectedEventArgs e)
|
public void DataModelPathSelected(object sender, DataModelSelectedEventArgs e)
|
||||||
@ -56,28 +53,5 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions.Event
|
|||||||
_windowManager.ShowDialog(_nodeVmFactory.NodeScriptWindowViewModel(EventCondition.Script));
|
_windowManager.ShowDialog(_nodeVmFactory.NodeScriptWindowViewModel(EventCondition.Script));
|
||||||
_profileEditorService.SaveSelectedProfileElement();
|
_profileEditorService.SaveSelectedProfileElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Overrides of Screen
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void OnInitialActivate()
|
|
||||||
{
|
|
||||||
((EventsConditionViewModel) Parent).Items.CollectionChanged += ItemsOnCollectionChanged;
|
|
||||||
base.OnInitialActivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void OnClose()
|
|
||||||
{
|
|
||||||
((EventsConditionViewModel) Parent).Items.CollectionChanged -= ItemsOnCollectionChanged;
|
|
||||||
base.OnClose();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
private void ItemsOnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
|
|
||||||
{
|
|
||||||
NotifyOfPropertyChange(nameof(CanDeleteEvent));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,139 +0,0 @@
|
|||||||
<UserControl x:Class="Artemis.UI.Screens.ProfileEditor.DisplayConditions.Event.EventsConditionView"
|
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
||||||
xmlns:local="clr-namespace:Artemis.UI.Screens.ProfileEditor.DisplayConditions.Event"
|
|
||||||
xmlns:converters="clr-namespace:Artemis.UI.Converters"
|
|
||||||
xmlns:s="https://github.com/canton7/Stylet"
|
|
||||||
xmlns:controls="clr-namespace:Artemis.VisualScripting.Editor.Controls;assembly=Artemis.VisualScripting"
|
|
||||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
|
||||||
xmlns:core="clr-namespace:Artemis.Core;assembly=Artemis.Core"
|
|
||||||
mc:Ignorable="d"
|
|
||||||
d:DesignHeight="450" d:DesignWidth="800"
|
|
||||||
d:DataContext="{d:DesignInstance {x:Type local:EventsConditionViewModel}}">
|
|
||||||
<UserControl.Resources>
|
|
||||||
<converters:ComparisonConverter x:Key="ComparisonConverter" />
|
|
||||||
</UserControl.Resources>
|
|
||||||
<Grid>
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition Height="*" />
|
|
||||||
<RowDefinition Height="22" />
|
|
||||||
<RowDefinition Height="Auto" />
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
|
|
||||||
<TabControl Grid.Row="0"
|
|
||||||
VerticalAlignment="Stretch"
|
|
||||||
ItemsSource="{Binding Items}"
|
|
||||||
SelectedItem="{Binding ActiveItem}"
|
|
||||||
Style="{StaticResource MaterialDesignTabControl}">
|
|
||||||
<TabControl.ItemTemplate>
|
|
||||||
<DataTemplate>
|
|
||||||
<DockPanel LastChildFill="True" Margin="-15 0">
|
|
||||||
<Button DockPanel.Dock="Right"
|
|
||||||
Style="{StaticResource MaterialDesignIconForegroundButton}"
|
|
||||||
Command="{s:Action DeleteEvent}"
|
|
||||||
s:View.ActionTarget="{Binding}"
|
|
||||||
CommandParameter="{Binding}"
|
|
||||||
Width="25"
|
|
||||||
Height="25">
|
|
||||||
<materialDesign:PackIcon Kind="Close" Width="15" Height="15" Foreground="{DynamicResource MaterialDesignBody}" />
|
|
||||||
</Button>
|
|
||||||
<Label Content="{Binding DisplayName}" DockPanel.Dock="Left" />
|
|
||||||
</DockPanel>
|
|
||||||
</DataTemplate>
|
|
||||||
</TabControl.ItemTemplate>
|
|
||||||
<TabControl.ContentTemplate>
|
|
||||||
<DataTemplate>
|
|
||||||
<ContentControl s:View.Model="{Binding IsAsync=True}"
|
|
||||||
VerticalContentAlignment="Stretch"
|
|
||||||
HorizontalContentAlignment="Stretch"
|
|
||||||
IsTabStop="False"
|
|
||||||
TextElement.Foreground="{DynamicResource MaterialDesignBody}" />
|
|
||||||
</DataTemplate>
|
|
||||||
</TabControl.ContentTemplate>
|
|
||||||
</TabControl>
|
|
||||||
|
|
||||||
<!-- Trigger mode -->
|
|
||||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="Trigger mode" VerticalAlignment="Center">
|
|
||||||
<TextBlock.ToolTip>
|
|
||||||
<ToolTip Placement="Center" VerticalOffset="-30">
|
|
||||||
<TextBlock>
|
|
||||||
Configure how the layer should act when the event(s) trigger
|
|
||||||
</TextBlock>
|
|
||||||
</ToolTip>
|
|
||||||
</TextBlock.ToolTip>
|
|
||||||
</TextBlock>
|
|
||||||
|
|
||||||
<materialDesign:ColorZone Grid.Row="2" Grid.Column="0" Mode="Standard" CornerRadius="3">
|
|
||||||
<Grid HorizontalAlignment="Stretch">
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition />
|
|
||||||
<ColumnDefinition />
|
|
||||||
<ColumnDefinition />
|
|
||||||
<ColumnDefinition />
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<RadioButton Grid.Column="0"
|
|
||||||
Style="{StaticResource MaterialDesignTabRadioButton}"
|
|
||||||
IsChecked="{Binding Path=EventOverlapMode, Converter={StaticResource ComparisonConverter}, ConverterParameter={x:Static core:TimeLineEventOverlapMode.Restart}}">
|
|
||||||
<TextBlock VerticalAlignment="Center" FontSize="12">
|
|
||||||
<materialDesign:PackIcon Kind="Repeat" VerticalAlignment="Center" Margin="-3 0 0 -3" />
|
|
||||||
RESTART
|
|
||||||
</TextBlock>
|
|
||||||
<RadioButton.ToolTip>
|
|
||||||
<ToolTip Placement="Center" VerticalOffset="-40">
|
|
||||||
<TextBlock>
|
|
||||||
Stop the current run and restart the timeline
|
|
||||||
</TextBlock>
|
|
||||||
</ToolTip>
|
|
||||||
</RadioButton.ToolTip>
|
|
||||||
</RadioButton>
|
|
||||||
<RadioButton Grid.Column="1"
|
|
||||||
Style="{StaticResource MaterialDesignTabRadioButton}"
|
|
||||||
IsChecked="{Binding Path=EventOverlapMode, Converter={StaticResource ComparisonConverter}, ConverterParameter={x:Static core:TimeLineEventOverlapMode.Toggle}}">
|
|
||||||
<TextBlock VerticalAlignment="Center" FontSize="12">
|
|
||||||
<materialDesign:PackIcon Kind="TrafficLight" VerticalAlignment="Center" Margin="-3 0 0 -3" />
|
|
||||||
TOGGLE
|
|
||||||
</TextBlock>
|
|
||||||
<RadioButton.ToolTip>
|
|
||||||
<ToolTip Placement="Center" VerticalOffset="-40">
|
|
||||||
<TextBlock>
|
|
||||||
Repeat the timeline until the event fires again
|
|
||||||
</TextBlock>
|
|
||||||
</ToolTip>
|
|
||||||
</RadioButton.ToolTip>
|
|
||||||
</RadioButton>
|
|
||||||
<RadioButton Grid.Column="2"
|
|
||||||
Style="{StaticResource MaterialDesignTabRadioButton}"
|
|
||||||
IsChecked="{Binding Path=EventOverlapMode, Converter={StaticResource ComparisonConverter}, ConverterParameter={x:Static core:TimeLineEventOverlapMode.Ignore}}">
|
|
||||||
<TextBlock VerticalAlignment="Center" FontSize="12">
|
|
||||||
<materialDesign:PackIcon Kind="EarHearingOff" VerticalAlignment="Center" Margin="-3 0 0 -3" />
|
|
||||||
IGNORE
|
|
||||||
</TextBlock>
|
|
||||||
<RadioButton.ToolTip>
|
|
||||||
<ToolTip Placement="Center" VerticalOffset="-40">
|
|
||||||
<TextBlock>
|
|
||||||
Ignore subsequent event fires until the timeline finishes
|
|
||||||
</TextBlock>
|
|
||||||
</ToolTip>
|
|
||||||
</RadioButton.ToolTip>
|
|
||||||
</RadioButton>
|
|
||||||
<RadioButton Grid.Column="3"
|
|
||||||
Style="{StaticResource MaterialDesignTabRadioButton}"
|
|
||||||
IsChecked="{Binding Path=EventOverlapMode, Converter={StaticResource ComparisonConverter}, ConverterParameter={x:Static core:TimeLineEventOverlapMode.Copy}}">
|
|
||||||
<TextBlock VerticalAlignment="Center" FontSize="12">
|
|
||||||
<materialDesign:PackIcon Kind="ContentCopy" VerticalAlignment="Center" Margin="-3 0 0 -3" />
|
|
||||||
COPY
|
|
||||||
</TextBlock>
|
|
||||||
<RadioButton.ToolTip>
|
|
||||||
<ToolTip Placement="Center" VerticalOffset="-40">
|
|
||||||
<TextBlock>
|
|
||||||
Play another copy of the timeline on top of the current run
|
|
||||||
</TextBlock>
|
|
||||||
</ToolTip>
|
|
||||||
</RadioButton.ToolTip>
|
|
||||||
</RadioButton>
|
|
||||||
</Grid>
|
|
||||||
</materialDesign:ColorZone>
|
|
||||||
</Grid>
|
|
||||||
</UserControl>
|
|
||||||
@ -1,65 +0,0 @@
|
|||||||
using System.Linq;
|
|
||||||
using Artemis.Core;
|
|
||||||
using Artemis.UI.Ninject.Factories;
|
|
||||||
using Artemis.UI.Shared.Services;
|
|
||||||
using Stylet;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions.Event
|
|
||||||
{
|
|
||||||
public class EventsConditionViewModel : Conductor<EventConditionViewModel>.Collection.OneActive
|
|
||||||
{
|
|
||||||
private readonly IConditionVmFactory _conditionVmFactory;
|
|
||||||
private readonly IProfileEditorService _profileEditorService;
|
|
||||||
|
|
||||||
public EventsConditionViewModel(EventsCondition eventsCondition, IConditionVmFactory conditionVmFactory, IProfileEditorService profileEditorService)
|
|
||||||
{
|
|
||||||
_conditionVmFactory = conditionVmFactory;
|
|
||||||
_profileEditorService = profileEditorService;
|
|
||||||
EventsCondition = eventsCondition;
|
|
||||||
}
|
|
||||||
|
|
||||||
public EventsCondition EventsCondition { get; }
|
|
||||||
|
|
||||||
public TimeLineEventOverlapMode EventOverlapMode
|
|
||||||
{
|
|
||||||
get => EventsCondition.EventOverlapMode;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (EventsCondition.EventOverlapMode == value) return;
|
|
||||||
EventsCondition.EventOverlapMode = value;
|
|
||||||
_profileEditorService.SaveSelectedProfileElement();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddEvent()
|
|
||||||
{
|
|
||||||
EventCondition eventCondition = EventsCondition.AddEventCondition();
|
|
||||||
Items.Add(_conditionVmFactory.EventConditionViewModel(eventCondition));
|
|
||||||
|
|
||||||
_profileEditorService.SaveSelectedProfileElement();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void DeleteEvent(EventConditionViewModel eventConditionViewModel)
|
|
||||||
{
|
|
||||||
EventsCondition.RemoveEventCondition(eventConditionViewModel.EventCondition);
|
|
||||||
Items.Remove(eventConditionViewModel);
|
|
||||||
|
|
||||||
_profileEditorService.SaveSelectedProfileElement();
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Overrides of Screen
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void OnInitialActivate()
|
|
||||||
{
|
|
||||||
if (!EventsCondition.Events.Any())
|
|
||||||
EventsCondition.AddEventCondition();
|
|
||||||
|
|
||||||
foreach (EventCondition eventCondition in EventsCondition.Events)
|
|
||||||
Items.Add(_conditionVmFactory.EventConditionViewModel(eventCondition));
|
|
||||||
base.OnInitialActivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -49,16 +49,17 @@
|
|||||||
</Style.Triggers>
|
</Style.Triggers>
|
||||||
</Style>
|
</Style>
|
||||||
</Border.Style>
|
</Border.Style>
|
||||||
<Grid HorizontalAlignment="Center">
|
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||||
<Grid.ColumnDefinitions>
|
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||||
<ColumnDefinition />
|
<TextBlock Style="{StaticResource MaterialDesignHeadline5TextBlock}" VerticalAlignment="Center">
|
||||||
<ColumnDefinition />
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<TextBlock Style="{StaticResource MaterialDesignHeadline5TextBlock}" VerticalAlignment="Center" Grid.Column="0">
|
|
||||||
Click to edit script
|
Click to edit script
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
<materialDesign:PackIcon Kind="OpenInNew" Margin="10 " Width="30" Height="30" Grid.Column="1" VerticalAlignment="Center" />
|
<materialDesign:PackIcon Kind="OpenInNew" Margin="10 " Width="30" Height="30" VerticalAlignment="Center" />
|
||||||
</Grid>
|
</StackPanel>
|
||||||
|
<TextBlock Style="{StaticResource MaterialDesignSubtitle1TextBlock}" TextWrapping="Wrap" TextAlignment="Center">
|
||||||
|
Scripts with nothing connected to their end-node are always true.
|
||||||
|
</TextBlock>
|
||||||
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid Grid.Row="1">
|
<Grid Grid.Row="1">
|
||||||
|
|||||||
@ -31,7 +31,7 @@ namespace Artemis.VisualScripting.Nodes
|
|||||||
if (Storage is not DataModelPathEntity pathEntity)
|
if (Storage is not DataModelPathEntity pathEntity)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DataModelPath = new DataModelPath(null, pathEntity);
|
DataModelPath = new DataModelPath(pathEntity);
|
||||||
DataModelPath.PathValidated += DataModelPathOnPathValidated;
|
DataModelPath.PathValidated += DataModelPathOnPathValidated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -32,7 +32,7 @@ namespace Artemis.VisualScripting.Nodes
|
|||||||
if (Storage is not DataModelPathEntity pathEntity)
|
if (Storage is not DataModelPathEntity pathEntity)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DataModelPath = new DataModelPath(null, pathEntity);
|
DataModelPath = new DataModelPath(pathEntity);
|
||||||
DataModelPath.PathValidated += DataModelPathOnPathValidated;
|
DataModelPath.PathValidated += DataModelPathOnPathValidated;
|
||||||
|
|
||||||
UpdateOutputPin(false);
|
UpdateOutputPin(false);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user