mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-31 17:53:32 +00:00
Core - Streamlined public parts of profile creation
UI - Started adjusting the VMs for the layer refactor
This commit is contained in:
parent
1de6fefc2a
commit
c07ea09c9d
@ -61,7 +61,7 @@ namespace Artemis.Core
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public abstract bool EvaluateObject(object target);
|
public abstract bool EvaluateObject(object target);
|
||||||
|
|
||||||
internal abstract void ApplyToEntity();
|
internal abstract void Save();
|
||||||
internal abstract DisplayConditionPartEntity GetEntity();
|
internal abstract DisplayConditionPartEntity GetEntity();
|
||||||
|
|
||||||
#region IDisposable
|
#region IDisposable
|
||||||
|
|||||||
@ -105,14 +105,14 @@ namespace Artemis.Core
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override void ApplyToEntity()
|
internal override void Save()
|
||||||
{
|
{
|
||||||
Entity.BooleanOperator = (int) BooleanOperator;
|
Entity.BooleanOperator = (int) BooleanOperator;
|
||||||
|
|
||||||
Entity.Children.Clear();
|
Entity.Children.Clear();
|
||||||
Entity.Children.AddRange(Children.Select(c => c.GetEntity()));
|
Entity.Children.AddRange(Children.Select(c => c.GetEntity()));
|
||||||
foreach (var child in Children)
|
foreach (var child in Children)
|
||||||
child.ApplyToEntity();
|
child.Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override DisplayConditionPartEntity GetEntity()
|
internal override DisplayConditionPartEntity GetEntity()
|
||||||
|
|||||||
@ -116,7 +116,7 @@ namespace Artemis.Core
|
|||||||
CompiledListAccessor = lambda.Compile();
|
CompiledListAccessor = lambda.Compile();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override void ApplyToEntity()
|
internal override void Save()
|
||||||
{
|
{
|
||||||
// Target list
|
// Target list
|
||||||
if (ListDataModel != null)
|
if (ListDataModel != null)
|
||||||
@ -132,7 +132,7 @@ namespace Artemis.Core
|
|||||||
Entity.Children.Clear();
|
Entity.Children.Clear();
|
||||||
Entity.Children.AddRange(Children.Select(c => c.GetEntity()));
|
Entity.Children.AddRange(Children.Select(c => c.GetEntity()));
|
||||||
foreach (var child in Children)
|
foreach (var child in Children)
|
||||||
child.ApplyToEntity();
|
child.Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override DisplayConditionPartEntity GetEntity()
|
internal override DisplayConditionPartEntity GetEntity()
|
||||||
|
|||||||
@ -190,22 +190,31 @@ namespace Artemis.Core
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override void ApplyToEntity()
|
internal override void Save()
|
||||||
{
|
{
|
||||||
Entity.PredicateType = (int) PredicateType;
|
Entity.PredicateType = (int) PredicateType;
|
||||||
Entity.ListDataModelGuid = ListDataModel?.PluginInfo?.Guid;
|
if (ListDataModel != null)
|
||||||
Entity.ListPropertyPath = ListPropertyPath;
|
{
|
||||||
|
Entity.ListDataModelGuid = ListDataModel.PluginInfo.Guid;
|
||||||
|
Entity.ListPropertyPath = ListPropertyPath;
|
||||||
|
}
|
||||||
|
|
||||||
Entity.LeftPropertyPath = LeftPropertyPath;
|
Entity.LeftPropertyPath = LeftPropertyPath;
|
||||||
Entity.RightPropertyPath = RightPropertyPath;
|
Entity.RightPropertyPath = RightPropertyPath;
|
||||||
Entity.RightStaticValue = JsonConvert.SerializeObject(RightStaticValue);
|
Entity.RightStaticValue = JsonConvert.SerializeObject(RightStaticValue);
|
||||||
|
|
||||||
Entity.OperatorPluginGuid = Operator?.PluginInfo?.Guid;
|
if (Operator != null)
|
||||||
Entity.OperatorType = Operator?.GetType().Name;
|
{
|
||||||
|
Entity.OperatorPluginGuid = Operator.PluginInfo.Guid;
|
||||||
|
Entity.OperatorType = Operator.GetType().Name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void Initialize()
|
private void Initialize()
|
||||||
{
|
{
|
||||||
|
ConditionOperatorStore.ConditionOperatorAdded += ConditionOperatorStoreOnConditionOperatorAdded;
|
||||||
|
ConditionOperatorStore.ConditionOperatorRemoved += ConditionOperatorStoreOnConditionOperatorRemoved;
|
||||||
|
|
||||||
// Left side
|
// Left side
|
||||||
if (Entity.LeftPropertyPath != null && ListContainsInnerPath(Entity.LeftPropertyPath))
|
if (Entity.LeftPropertyPath != null && ListContainsInnerPath(Entity.LeftPropertyPath))
|
||||||
UpdateLeftSide(Entity.LeftPropertyPath);
|
UpdateLeftSide(Entity.LeftPropertyPath);
|
||||||
@ -222,7 +231,7 @@ namespace Artemis.Core
|
|||||||
if (PredicateType == ProfileRightSideType.Dynamic && Entity.RightPropertyPath != null)
|
if (PredicateType == ProfileRightSideType.Dynamic && Entity.RightPropertyPath != null)
|
||||||
{
|
{
|
||||||
if (ListContainsInnerPath(Entity.RightPropertyPath))
|
if (ListContainsInnerPath(Entity.RightPropertyPath))
|
||||||
UpdateLeftSide(Entity.LeftPropertyPath);
|
UpdateRightSideDynamic(Entity.RightPropertyPath);
|
||||||
}
|
}
|
||||||
// Right side static
|
// Right side static
|
||||||
else if (PredicateType == ProfileRightSideType.Static && Entity.RightStaticValue != null)
|
else if (PredicateType == ProfileRightSideType.Static && Entity.RightStaticValue != null)
|
||||||
@ -384,5 +393,37 @@ namespace Artemis.Core
|
|||||||
Expression.Property
|
Expression.Property
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region Event handlers
|
||||||
|
|
||||||
|
private void ConditionOperatorStoreOnConditionOperatorAdded(object sender, ConditionOperatorStoreEvent e)
|
||||||
|
{
|
||||||
|
var conditionOperator = e.Registration.ConditionOperator;
|
||||||
|
if (Entity.OperatorPluginGuid == conditionOperator.PluginInfo.Guid && Entity.OperatorType == conditionOperator.GetType().Name)
|
||||||
|
UpdateOperator(conditionOperator);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ConditionOperatorStoreOnConditionOperatorRemoved(object sender, ConditionOperatorStoreEvent e)
|
||||||
|
{
|
||||||
|
if (e.Registration.ConditionOperator != Operator)
|
||||||
|
return;
|
||||||
|
Operator = null;
|
||||||
|
CompiledListPredicate = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IDisposable
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
ConditionOperatorStore.ConditionOperatorAdded -= ConditionOperatorStoreOnConditionOperatorAdded;
|
||||||
|
ConditionOperatorStore.ConditionOperatorRemoved -= ConditionOperatorStoreOnConditionOperatorRemoved;
|
||||||
|
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -232,7 +232,7 @@ namespace Artemis.Core
|
|||||||
return $"[Static] {LeftPropertyPath} {Operator.Description} {RightStaticValue}";
|
return $"[Static] {LeftPropertyPath} {Operator.Description} {RightStaticValue}";
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override void ApplyToEntity()
|
internal override void Save()
|
||||||
{
|
{
|
||||||
Entity.PredicateType = (int) PredicateType;
|
Entity.PredicateType = (int) PredicateType;
|
||||||
Entity.LeftDataModelGuid = LeftDataModel?.PluginInfo?.Guid;
|
Entity.LeftDataModelGuid = LeftDataModel?.PluginInfo?.Guid;
|
||||||
@ -250,6 +250,8 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
DataModelStore.DataModelAdded += DataModelStoreOnDataModelAdded;
|
DataModelStore.DataModelAdded += DataModelStoreOnDataModelAdded;
|
||||||
DataModelStore.DataModelRemoved += DataModelStoreOnDataModelRemoved;
|
DataModelStore.DataModelRemoved += DataModelStoreOnDataModelRemoved;
|
||||||
|
ConditionOperatorStore.ConditionOperatorAdded += ConditionOperatorStoreOnConditionOperatorAdded;
|
||||||
|
ConditionOperatorStore.ConditionOperatorRemoved += ConditionOperatorStoreOnConditionOperatorRemoved;
|
||||||
|
|
||||||
// Left side
|
// Left side
|
||||||
if (Entity.LeftDataModelGuid != null)
|
if (Entity.LeftDataModelGuid != null)
|
||||||
@ -415,19 +417,6 @@ namespace Artemis.Core
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Expression CreateListAccessor(DataModel dataModel, string path, ParameterExpression listParameter)
|
|
||||||
{
|
|
||||||
var listType = dataModel.GetListTypeInPath(path);
|
|
||||||
if (listType == null)
|
|
||||||
throw new ArtemisCoreException($"Cannot create a list accessor at path {path} because the path does not contain a list");
|
|
||||||
|
|
||||||
path = dataModel.GetListInnerPath(path);
|
|
||||||
return path.Split('.').Aggregate<string, Expression>(
|
|
||||||
Expression.Convert(listParameter, listType), // Cast to the appropriate type
|
|
||||||
Expression.Property
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Event handlers
|
#region Event handlers
|
||||||
|
|
||||||
private void DataModelStoreOnDataModelAdded(object sender, DataModelStoreEvent e)
|
private void DataModelStoreOnDataModelAdded(object sender, DataModelStoreEvent e)
|
||||||
@ -454,6 +443,23 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ConditionOperatorStoreOnConditionOperatorAdded(object sender, ConditionOperatorStoreEvent e)
|
||||||
|
{
|
||||||
|
var conditionOperator = e.Registration.ConditionOperator;
|
||||||
|
if (Entity.OperatorPluginGuid == conditionOperator.PluginInfo.Guid && Entity.OperatorType == conditionOperator.GetType().Name)
|
||||||
|
UpdateOperator(conditionOperator);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ConditionOperatorStoreOnConditionOperatorRemoved(object sender, ConditionOperatorStoreEvent e)
|
||||||
|
{
|
||||||
|
if (e.Registration.ConditionOperator != Operator)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Operator = null;
|
||||||
|
CompiledStaticPredicate = null;
|
||||||
|
CompiledDynamicPredicate = null;
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -461,6 +467,8 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
DataModelStore.DataModelAdded -= DataModelStoreOnDataModelAdded;
|
DataModelStore.DataModelAdded -= DataModelStoreOnDataModelAdded;
|
||||||
DataModelStore.DataModelRemoved -= DataModelStoreOnDataModelRemoved;
|
DataModelStore.DataModelRemoved -= DataModelStoreOnDataModelRemoved;
|
||||||
|
ConditionOperatorStore.ConditionOperatorAdded -= ConditionOperatorStoreOnConditionOperatorAdded;
|
||||||
|
ConditionOperatorStore.ConditionOperatorRemoved -= ConditionOperatorStoreOnConditionOperatorRemoved;
|
||||||
|
|
||||||
base.Dispose(disposing);
|
base.Dispose(disposing);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,24 +8,35 @@ using SkiaSharp;
|
|||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a folder in a <see cref="Profile" />
|
||||||
|
/// </summary>
|
||||||
public sealed class Folder : RenderProfileElement
|
public sealed class Folder : RenderProfileElement
|
||||||
{
|
{
|
||||||
private SKBitmap _folderBitmap;
|
private SKBitmap _folderBitmap;
|
||||||
|
|
||||||
public Folder(Profile profile, ProfileElement parent, string name)
|
/// <summary>
|
||||||
|
/// Creates a new instance of the <see cref="Folder" /> class and adds itself to the child collection of the provided
|
||||||
|
/// <paramref name="parent" />
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="parent">The parent of the folder</param>
|
||||||
|
/// <param name="name">The name of the folder</param>
|
||||||
|
public Folder(ProfileElement parent, string name)
|
||||||
{
|
{
|
||||||
FolderEntity = new FolderEntity();
|
FolderEntity = new FolderEntity();
|
||||||
EntityId = Guid.NewGuid();
|
EntityId = Guid.NewGuid();
|
||||||
|
|
||||||
Profile = profile;
|
Parent = parent ?? throw new ArgumentNullException(nameof(parent));
|
||||||
Parent = parent;
|
Profile = Parent.Profile;
|
||||||
Name = name;
|
Name = name;
|
||||||
Enabled = true;
|
Enabled = true;
|
||||||
DisplayContinuously = true;
|
DisplayContinuously = true;
|
||||||
|
|
||||||
_layerEffects = new List<BaseLayerEffect>();
|
_layerEffects = new List<BaseLayerEffect>();
|
||||||
_expandedPropertyGroups = new List<string>();
|
_expandedPropertyGroups = new List<string>();
|
||||||
|
|
||||||
ApplyRenderElementDefaults();
|
ApplyRenderElementDefaults();
|
||||||
|
Parent.AddChild(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal Folder(Profile profile, ProfileElement parent, FolderEntity folderEntity)
|
internal Folder(Profile profile, ProfileElement parent, FolderEntity folderEntity)
|
||||||
@ -182,22 +193,7 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
canvas.Restore();
|
canvas.Restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Adds a new folder to the bottom of this folder
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="name"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public Folder AddFolder(string name)
|
|
||||||
{
|
|
||||||
if (_disposed)
|
|
||||||
throw new ObjectDisposedException("Folder");
|
|
||||||
|
|
||||||
var folder = new Folder(Profile, this, name) {Order = Children.LastOrDefault()?.Order ?? 1};
|
|
||||||
AddChild(folder);
|
|
||||||
return folder;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void AddChild(ProfileElement child, int? order = null)
|
public override void AddChild(ProfileElement child, int? order = null)
|
||||||
{
|
{
|
||||||
@ -296,7 +292,7 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
// Conditions
|
// Conditions
|
||||||
RenderElementEntity.RootDisplayCondition = DisplayConditionGroup?.Entity;
|
RenderElementEntity.RootDisplayCondition = DisplayConditionGroup?.Entity;
|
||||||
DisplayConditionGroup?.ApplyToEntity();
|
DisplayConditionGroup?.Save();
|
||||||
|
|
||||||
SaveRenderElement();
|
SaveRenderElement();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,8 +11,7 @@ using SkiaSharp;
|
|||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a layer on a profile. To create new layers use the <see cref="RenderElementService" /> by injecting
|
/// Represents a layer in a <see cref="Profile" />
|
||||||
/// <see cref="IRenderElementService" /> into your code
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class Layer : RenderProfileElement
|
public sealed class Layer : RenderProfileElement
|
||||||
{
|
{
|
||||||
@ -23,13 +22,19 @@ namespace Artemis.Core
|
|||||||
private List<ArtemisLed> _leds;
|
private List<ArtemisLed> _leds;
|
||||||
private LayerTransformProperties _transform;
|
private LayerTransformProperties _transform;
|
||||||
|
|
||||||
internal Layer(Profile profile, ProfileElement parent, string name)
|
/// <summary>
|
||||||
|
/// Creates a new instance of the <see cref="Layer" /> class and adds itself to the child collection of the provided
|
||||||
|
/// <paramref name="parent" />
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="parent">The parent of the layer</param>
|
||||||
|
/// <param name="name">The name of the layer</param>
|
||||||
|
public Layer(ProfileElement parent, string name)
|
||||||
{
|
{
|
||||||
LayerEntity = new LayerEntity();
|
LayerEntity = new LayerEntity();
|
||||||
EntityId = Guid.NewGuid();
|
EntityId = Guid.NewGuid();
|
||||||
|
|
||||||
Profile = profile;
|
Parent = parent ?? throw new ArgumentNullException(nameof(parent));
|
||||||
Parent = parent;
|
Profile = Parent.Profile;
|
||||||
Name = name;
|
Name = name;
|
||||||
Enabled = true;
|
Enabled = true;
|
||||||
DisplayContinuously = true;
|
DisplayContinuously = true;
|
||||||
@ -40,10 +45,10 @@ namespace Artemis.Core
|
|||||||
_leds = new List<ArtemisLed>();
|
_leds = new List<ArtemisLed>();
|
||||||
_expandedPropertyGroups = new List<string>();
|
_expandedPropertyGroups = new List<string>();
|
||||||
|
|
||||||
InitializeDefaultGroups();
|
Initialize();
|
||||||
|
|
||||||
parent.AddChild(this);
|
|
||||||
ApplyRenderElementDefaults();
|
ApplyRenderElementDefaults();
|
||||||
|
|
||||||
|
Parent.AddChild(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal Layer(Profile profile, ProfileElement parent, LayerEntity layerEntity)
|
internal Layer(Profile profile, ProfileElement parent, LayerEntity layerEntity)
|
||||||
@ -58,8 +63,7 @@ namespace Artemis.Core
|
|||||||
_leds = new List<ArtemisLed>();
|
_leds = new List<ArtemisLed>();
|
||||||
_expandedPropertyGroups = new List<string>();
|
_expandedPropertyGroups = new List<string>();
|
||||||
|
|
||||||
InitializeDefaultGroups();
|
Initialize();
|
||||||
|
|
||||||
Load();
|
Load();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,6 +118,8 @@ namespace Artemis.Core
|
|||||||
return $"[Layer] {nameof(Name)}: {Name}, {nameof(Order)}: {Order}";
|
return $"[Layer] {nameof(Name)}: {Name}, {nameof(Order)}: {Order}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region IDisposable
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void Dispose(bool disposing)
|
protected override void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
@ -133,8 +139,13 @@ namespace Artemis.Core
|
|||||||
_transform?.Dispose();
|
_transform?.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitializeDefaultGroups()
|
#endregion
|
||||||
|
|
||||||
|
private void Initialize()
|
||||||
{
|
{
|
||||||
|
LayerBrushStore.LayerBrushAdded += LayerBrushStoreOnLayerBrushAdded;
|
||||||
|
LayerBrushStore.LayerBrushRemoved += LayerBrushStoreOnLayerBrushRemoved;
|
||||||
|
|
||||||
// Layers have two hardcoded property groups, instantiate them
|
// Layers have two hardcoded property groups, instantiate them
|
||||||
General.Initialize(this, "General.", Constants.CorePluginInfo);
|
General.Initialize(this, "General.", Constants.CorePluginInfo);
|
||||||
Transform.Initialize(this, "Transform.", Constants.CorePluginInfo);
|
Transform.Initialize(this, "Transform.", Constants.CorePluginInfo);
|
||||||
@ -191,7 +202,7 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
// Conditions
|
// Conditions
|
||||||
RenderElementEntity.RootDisplayCondition = DisplayConditionGroup?.Entity;
|
RenderElementEntity.RootDisplayCondition = DisplayConditionGroup?.Entity;
|
||||||
DisplayConditionGroup?.ApplyToEntity();
|
DisplayConditionGroup?.Save();
|
||||||
|
|
||||||
SaveRenderElement();
|
SaveRenderElement();
|
||||||
}
|
}
|
||||||
@ -711,6 +722,27 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Event handlers
|
||||||
|
|
||||||
|
private void LayerBrushStoreOnLayerBrushRemoved(object sender, LayerBrushStoreEvent e)
|
||||||
|
{
|
||||||
|
if (LayerBrush.Descriptor == e.Registration.LayerBrushDescriptor)
|
||||||
|
DeactivateLayerBrush();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LayerBrushStoreOnLayerBrushAdded(object sender, LayerBrushStoreEvent e)
|
||||||
|
{
|
||||||
|
if (LayerBrush != null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var current = General.BrushReference.CurrentValue;
|
||||||
|
if (e.Registration.Plugin.PluginInfo.Guid == current.BrushPluginGuid &&
|
||||||
|
e.Registration.LayerBrushDescriptor.LayerBrushType.Name == current.BrushType)
|
||||||
|
ActivateLayerBrush();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region Events
|
#region Events
|
||||||
|
|
||||||
public event EventHandler RenderPropertiesUpdated;
|
public event EventHandler RenderPropertiesUpdated;
|
||||||
|
|||||||
@ -16,17 +16,19 @@ namespace Artemis.Core
|
|||||||
ProfileEntity = new ProfileEntity();
|
ProfileEntity = new ProfileEntity();
|
||||||
EntityId = Guid.NewGuid();
|
EntityId = Guid.NewGuid();
|
||||||
|
|
||||||
|
Profile = this;
|
||||||
Module = module;
|
Module = module;
|
||||||
Name = name;
|
Name = name;
|
||||||
UndoStack = new Stack<string>();
|
UndoStack = new Stack<string>();
|
||||||
RedoStack = new Stack<string>();
|
RedoStack = new Stack<string>();
|
||||||
|
|
||||||
AddChild(new Folder(this, this, "Root folder"));
|
var _ = new Folder(this, "Root folder");
|
||||||
Save();
|
Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal Profile(ProfileModule module, ProfileEntity profileEntity)
|
internal Profile(ProfileModule module, ProfileEntity profileEntity)
|
||||||
{
|
{
|
||||||
|
Profile = this;
|
||||||
ProfileEntity = profileEntity;
|
ProfileEntity = profileEntity;
|
||||||
EntityId = profileEntity.Id;
|
EntityId = profileEntity.Id;
|
||||||
|
|
||||||
@ -103,7 +105,9 @@ namespace Artemis.Core
|
|||||||
// Populate the profile starting at the root, the rest is populated recursively
|
// Populate the profile starting at the root, the rest is populated recursively
|
||||||
var rootFolder = ProfileEntity.Folders.FirstOrDefault(f => f.ParentId == EntityId);
|
var rootFolder = ProfileEntity.Folders.FirstOrDefault(f => f.ParentId == EntityId);
|
||||||
if (rootFolder == null)
|
if (rootFolder == null)
|
||||||
AddChild(new Folder(this, this, "Root folder"));
|
{
|
||||||
|
var _ = new Folder(this, "Root folder");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
AddChild(new Folder(this, this, rootFolder));
|
AddChild(new Folder(this, this, rootFolder));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -110,9 +110,12 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
if (_disposed)
|
if (_disposed)
|
||||||
throw new ObjectDisposedException(GetType().Name);
|
throw new ObjectDisposedException(GetType().Name);
|
||||||
|
|
||||||
lock (ChildrenList)
|
lock (ChildrenList)
|
||||||
{
|
{
|
||||||
|
if (ChildrenList.Contains(child))
|
||||||
|
return;
|
||||||
|
|
||||||
// Add to the end of the list
|
// Add to the end of the list
|
||||||
if (order == null)
|
if (order == null)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Artemis.Core.LayerEffects;
|
using Artemis.Core.LayerEffects;
|
||||||
|
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;
|
||||||
@ -49,7 +50,7 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
Id = layerEffect.EntityId,
|
Id = layerEffect.EntityId,
|
||||||
PluginGuid = layerEffect.PluginInfo.Guid,
|
PluginGuid = layerEffect.PluginInfo.Guid,
|
||||||
EffectType = layerEffect.GetType().Name,
|
EffectType = layerEffect.GetEffectTypeName(),
|
||||||
Name = layerEffect.Name,
|
Name = layerEffect.Name,
|
||||||
Enabled = layerEffect.Enabled,
|
Enabled = layerEffect.Enabled,
|
||||||
HasBeenRenamed = layerEffect.HasBeenRenamed,
|
HasBeenRenamed = layerEffect.HasBeenRenamed,
|
||||||
@ -268,11 +269,29 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
foreach (var layerEffectEntity in RenderElementEntity.LayerEffects)
|
foreach (var layerEffectEntity in RenderElementEntity.LayerEffects)
|
||||||
{
|
{
|
||||||
if (_layerEffects.Any(e => e.EntityId == layerEffectEntity.Id))
|
// If there is a non-placeholder existing effect, skip this entity
|
||||||
|
var existing = _layerEffects.FirstOrDefault(e => e.EntityId == layerEffectEntity.Id);
|
||||||
|
if (existing != null && !existing.Descriptor.IsPlaceHolder)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var descriptor = LayerEffectStore.Get(layerEffectEntity.PluginGuid, layerEffectEntity.EffectType)?.LayerEffectDescriptor;
|
var descriptor = LayerEffectStore.Get(layerEffectEntity.PluginGuid, layerEffectEntity.EffectType)?.LayerEffectDescriptor;
|
||||||
descriptor?.CreateInstance(this, layerEffectEntity);
|
if (descriptor != null)
|
||||||
|
{
|
||||||
|
// If a descriptor is found but there is an existing placeholder, remove the placeholder
|
||||||
|
if (existing != null)
|
||||||
|
{
|
||||||
|
_layerEffects.Remove(existing);
|
||||||
|
existing.Dispose();
|
||||||
|
}
|
||||||
|
// Create an instance with the descriptor
|
||||||
|
descriptor.CreateInstance(this, layerEffectEntity);
|
||||||
|
}
|
||||||
|
else if (existing == null)
|
||||||
|
{
|
||||||
|
// If no descriptor was found and there was no existing placeholder, create a placeholder
|
||||||
|
descriptor = PlaceholderLayerEffectDescriptor.Create();
|
||||||
|
descriptor.CreateInstance(this, layerEffectEntity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,9 +316,10 @@ namespace Artemis.Core
|
|||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LayerEffectStoreOnLayerEffectAdded(object? sender, LayerEffectStoreEvent e)
|
private void LayerEffectStoreOnLayerEffectAdded(object sender, LayerEffectStoreEvent e)
|
||||||
{
|
{
|
||||||
ActivateEffects();
|
if (RenderElementEntity.LayerEffects.Any(ef => ef.PluginGuid == e.Registration.Plugin.PluginInfo.Guid))
|
||||||
|
ActivateEffects();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@ -148,5 +148,7 @@ namespace Artemis.Core.LayerEffects
|
|||||||
// Not only is this needed to initialize properties on the layer effects, it also prevents implementing anything
|
// Not only is this needed to initialize properties on the layer effects, it also prevents implementing anything
|
||||||
// but LayerEffect<T> outside the core
|
// but LayerEffect<T> outside the core
|
||||||
internal abstract void Initialize();
|
internal abstract void Initialize();
|
||||||
|
|
||||||
|
internal virtual string GetEffectTypeName() => GetType().Name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,6 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Artemis.Core.LayerBrushes;
|
|
||||||
using Artemis.Storage.Entities.Profile;
|
using Artemis.Storage.Entities.Profile;
|
||||||
using Ninject;
|
using Ninject;
|
||||||
|
|
||||||
@ -51,6 +50,11 @@ namespace Artemis.Core.LayerEffects
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
internal IKernel Kernel { get; set; }
|
internal IKernel Kernel { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a boolean indicating if this descriptor is a placeholder for a missing plugin
|
||||||
|
/// </summary>
|
||||||
|
public bool IsPlaceHolder { get; internal set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates an instance of the described effect and applies it to the render element
|
/// Creates an instance of the described effect and applies it to the render element
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -60,6 +64,12 @@ namespace Artemis.Core.LayerEffects
|
|||||||
if (renderElement.LayerEffects.Any(e => e.EntityId == entity.Id))
|
if (renderElement.LayerEffects.Any(e => e.EntityId == entity.Id))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (IsPlaceHolder)
|
||||||
|
{
|
||||||
|
CreatePlaceHolderInstance(renderElement, entity);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var effect = (BaseLayerEffect) Kernel.Get(LayerEffectType);
|
var effect = (BaseLayerEffect) Kernel.Get(LayerEffectType);
|
||||||
effect.ProfileElement = renderElement;
|
effect.ProfileElement = renderElement;
|
||||||
effect.EntityId = entity.Id;
|
effect.EntityId = entity.Id;
|
||||||
@ -73,5 +83,11 @@ namespace Artemis.Core.LayerEffects
|
|||||||
|
|
||||||
renderElement.ActivateLayerEffect(effect);
|
renderElement.ActivateLayerEffect(effect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void CreatePlaceHolderInstance(RenderProfileElement renderElement, LayerEffectEntity entity)
|
||||||
|
{
|
||||||
|
var effect = new PlaceholderLayerEffect(entity) {ProfileElement = renderElement, Descriptor = this};
|
||||||
|
renderElement.ActivateLayerEffect(effect);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -0,0 +1,58 @@
|
|||||||
|
using Artemis.Storage.Entities.Profile;
|
||||||
|
using SkiaSharp;
|
||||||
|
|
||||||
|
namespace Artemis.Core.LayerEffects
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a layer effect that could not be loaded due to a missing plugin
|
||||||
|
/// </summary>
|
||||||
|
public class PlaceholderLayerEffect : BaseLayerEffect
|
||||||
|
{
|
||||||
|
internal PlaceholderLayerEffect(LayerEffectEntity originalEntity)
|
||||||
|
{
|
||||||
|
OriginalEntity = originalEntity;
|
||||||
|
|
||||||
|
EntityId = OriginalEntity.Id;
|
||||||
|
Order = OriginalEntity.Order;
|
||||||
|
Name = OriginalEntity.Name;
|
||||||
|
Enabled = OriginalEntity.Enabled;
|
||||||
|
HasBeenRenamed = OriginalEntity.HasBeenRenamed;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal LayerEffectEntity OriginalEntity { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void EnableLayerEffect()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void DisableLayerEffect()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Update(double deltaTime)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void PreProcess(SKCanvas canvas, SKImageInfo canvasInfo, SKPath renderBounds, SKPaint paint)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void PostProcess(SKCanvas canvas, SKImageInfo canvasInfo, SKPath renderBounds, SKPaint paint)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override string GetEffectTypeName()
|
||||||
|
{
|
||||||
|
return OriginalEntity.EffectType;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override void Initialize()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
namespace Artemis.Core.LayerEffects.Placeholder
|
||||||
|
{
|
||||||
|
internal static class PlaceholderLayerEffectDescriptor
|
||||||
|
{
|
||||||
|
public static LayerEffectDescriptor Create()
|
||||||
|
{
|
||||||
|
var descriptor = new LayerEffectDescriptor("Missing effect", "This effect could not be loaded", "FileQuestion", null, null) {IsPlaceHolder = true};
|
||||||
|
return descriptor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -51,7 +51,8 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
lock (Registrations)
|
lock (Registrations)
|
||||||
{
|
{
|
||||||
return Registrations.FirstOrDefault(d => d.Plugin.PluginInfo.Guid == pluginGuid && d.LayerBrushDescriptor.LayerBrushType.Name == typeName);
|
return Registrations.FirstOrDefault(d => d.Plugin.PluginInfo.Guid == pluginGuid &&
|
||||||
|
d.LayerBrushDescriptor.LayerBrushType.Name == typeName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,7 @@ namespace Artemis.UI.Shared.Services
|
|||||||
{
|
{
|
||||||
Profile SelectedProfile { get; }
|
Profile SelectedProfile { get; }
|
||||||
RenderProfileElement SelectedProfileElement { get; }
|
RenderProfileElement SelectedProfileElement { get; }
|
||||||
BaseLayerProperty SelectedDataBinding { get; }
|
ILayerProperty SelectedDataBinding { get; }
|
||||||
TimeSpan CurrentTime { get; set; }
|
TimeSpan CurrentTime { get; set; }
|
||||||
int PixelsPerSecond { get; set; }
|
int PixelsPerSecond { get; set; }
|
||||||
IReadOnlyList<PropertyInputRegistration> RegisteredPropertyEditors { get; }
|
IReadOnlyList<PropertyInputRegistration> RegisteredPropertyEditors { get; }
|
||||||
@ -19,7 +19,7 @@ namespace Artemis.UI.Shared.Services
|
|||||||
void UpdateSelectedProfile();
|
void UpdateSelectedProfile();
|
||||||
void ChangeSelectedProfileElement(RenderProfileElement profileElement);
|
void ChangeSelectedProfileElement(RenderProfileElement profileElement);
|
||||||
void UpdateSelectedProfileElement();
|
void UpdateSelectedProfileElement();
|
||||||
void ChangeSelectedDataBinding(BaseLayerProperty layerProperty);
|
void ChangeSelectedDataBinding(ILayerProperty layerProperty);
|
||||||
void UpdateProfilePreview();
|
void UpdateProfilePreview();
|
||||||
bool UndoUpdateProfile();
|
bool UndoUpdateProfile();
|
||||||
bool RedoUpdateProfile();
|
bool RedoUpdateProfile();
|
||||||
@ -88,5 +88,10 @@ namespace Artemis.UI.Shared.Services
|
|||||||
/// <param name="excludedKeyframe">A keyframe to exclude during keyframe snapping</param>
|
/// <param name="excludedKeyframe">A keyframe to exclude during keyframe snapping</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
TimeSpan SnapToTimeline(TimeSpan time, TimeSpan tolerance, bool snapToSegments, bool snapToCurrentTime, bool snapToKeyframes, BaseLayerPropertyKeyframe excludedKeyframe = null);
|
TimeSpan SnapToTimeline(TimeSpan time, TimeSpan tolerance, bool snapToSegments, bool snapToCurrentTime, bool snapToKeyframes, BaseLayerPropertyKeyframe excludedKeyframe = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If a matching registration is found, creates a new <see cref="PropertyInputViewModel{T}"/> supporting <typeparamref name="T"/>
|
||||||
|
/// </summary>
|
||||||
|
PropertyInputViewModel<T> CreatePropertyInputViewModel<T>(LayerProperty<T> layerProperty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5,6 +5,7 @@ using Artemis.Core;
|
|||||||
using Artemis.Core.Modules;
|
using Artemis.Core.Modules;
|
||||||
using Artemis.Core.Services;
|
using Artemis.Core.Services;
|
||||||
using Ninject;
|
using Ninject;
|
||||||
|
using Ninject.Parameters;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using Stylet;
|
using Stylet;
|
||||||
|
|
||||||
@ -269,6 +270,16 @@ namespace Artemis.UI.Shared.Services
|
|||||||
return time;
|
return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PropertyInputViewModel<T> CreatePropertyInputViewModel<T>(LayerProperty<T> layerProperty)
|
||||||
|
{
|
||||||
|
var registration = RegisteredPropertyEditors.FirstOrDefault(r => r.SupportedType == typeof(T));
|
||||||
|
if (registration == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var parameter = new ConstructorArgument("layerProperty", layerProperty);
|
||||||
|
return (PropertyInputViewModel<T>) Kernel.Get(registration.ViewModelType, parameter);
|
||||||
|
}
|
||||||
|
|
||||||
public ProfileModule GetCurrentModule()
|
public ProfileModule GetCurrentModule()
|
||||||
{
|
{
|
||||||
return SelectedProfile?.Module;
|
return SelectedProfile?.Module;
|
||||||
|
|||||||
@ -1,13 +1,10 @@
|
|||||||
using System.Reflection;
|
using Artemis.Core;
|
||||||
using Artemis.Core;
|
|
||||||
using Artemis.Core.Modules;
|
using Artemis.Core.Modules;
|
||||||
using Artemis.UI.Screens.Modules;
|
using Artemis.UI.Screens.Modules;
|
||||||
using Artemis.UI.Screens.Modules.Tabs;
|
using Artemis.UI.Screens.Modules.Tabs;
|
||||||
using Artemis.UI.Screens.ProfileEditor;
|
using Artemis.UI.Screens.ProfileEditor;
|
||||||
using Artemis.UI.Screens.ProfileEditor.DisplayConditions;
|
using Artemis.UI.Screens.ProfileEditor.DisplayConditions;
|
||||||
using Artemis.UI.Screens.ProfileEditor.DisplayConditions.Abstract;
|
|
||||||
using Artemis.UI.Screens.ProfileEditor.LayerProperties;
|
using Artemis.UI.Screens.ProfileEditor.LayerProperties;
|
||||||
using Artemis.UI.Screens.ProfileEditor.LayerProperties.Abstract;
|
|
||||||
using Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings;
|
using Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings;
|
||||||
using Artemis.UI.Screens.ProfileEditor.LayerProperties.LayerEffects;
|
using Artemis.UI.Screens.ProfileEditor.LayerProperties.LayerEffects;
|
||||||
using Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline;
|
using Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline;
|
||||||
@ -19,7 +16,6 @@ using Artemis.UI.Screens.Settings.Debug;
|
|||||||
using Artemis.UI.Screens.Settings.Tabs.Devices;
|
using Artemis.UI.Screens.Settings.Tabs.Devices;
|
||||||
using Artemis.UI.Screens.Settings.Tabs.Plugins;
|
using Artemis.UI.Screens.Settings.Tabs.Plugins;
|
||||||
using Stylet;
|
using Stylet;
|
||||||
using Module = Artemis.Core.Modules.Module;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Ninject.Factories
|
namespace Artemis.UI.Ninject.Factories
|
||||||
{
|
{
|
||||||
@ -46,15 +42,10 @@ namespace Artemis.UI.Ninject.Factories
|
|||||||
DeviceDebugViewModel Create(ArtemisDevice device);
|
DeviceDebugViewModel Create(ArtemisDevice device);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IFolderVmFactory : IVmFactory
|
public interface IProfileTreeVmFactory : IVmFactory
|
||||||
{
|
{
|
||||||
FolderViewModel Create(ProfileElement folder);
|
FolderViewModel FolderViewModel(ProfileElement folder);
|
||||||
FolderViewModel Create(TreeItemViewModel parent, ProfileElement folder);
|
LayerViewModel LayerViewModel(ProfileElement layer);
|
||||||
}
|
|
||||||
|
|
||||||
public interface ILayerVmFactory : IVmFactory
|
|
||||||
{
|
|
||||||
LayerViewModel Create(TreeItemViewModel parent, ProfileElement folder);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IProfileLayerVmFactory : IVmFactory
|
public interface IProfileLayerVmFactory : IVmFactory
|
||||||
@ -72,10 +63,10 @@ namespace Artemis.UI.Ninject.Factories
|
|||||||
|
|
||||||
public interface IDisplayConditionsVmFactory : IVmFactory
|
public interface IDisplayConditionsVmFactory : IVmFactory
|
||||||
{
|
{
|
||||||
DisplayConditionGroupViewModel DisplayConditionGroupViewModel(DisplayConditionGroup displayConditionGroup, DisplayConditionViewModel parent, bool isListGroup);
|
DisplayConditionGroupViewModel DisplayConditionGroupViewModel(DisplayConditionGroup displayConditionGroup, bool isListGroup);
|
||||||
DisplayConditionListViewModel DisplayConditionListViewModel(DisplayConditionList displayConditionList, DisplayConditionViewModel parent);
|
DisplayConditionListViewModel DisplayConditionListViewModel(DisplayConditionList displayConditionList);
|
||||||
DisplayConditionPredicateViewModel DisplayConditionPredicateViewModel(DisplayConditionPredicate displayConditionPredicate, DisplayConditionViewModel parent);
|
DisplayConditionPredicateViewModel DisplayConditionPredicateViewModel(DisplayConditionPredicate displayConditionPredicate);
|
||||||
DisplayConditionListPredicateViewModel DisplayConditionListPredicateViewModel(DisplayConditionListPredicate displayConditionListPredicate, DisplayConditionViewModel parent);
|
DisplayConditionListPredicateViewModel DisplayConditionListPredicateViewModel(DisplayConditionListPredicate displayConditionListPredicate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IDataBindingsVmFactory : IVmFactory
|
public interface IDataBindingsVmFactory : IVmFactory
|
||||||
@ -87,11 +78,13 @@ namespace Artemis.UI.Ninject.Factories
|
|||||||
|
|
||||||
public interface ILayerPropertyVmFactory : IVmFactory
|
public interface ILayerPropertyVmFactory : IVmFactory
|
||||||
{
|
{
|
||||||
|
LayerPropertyViewModel LayerPropertyViewModel(ILayerProperty layerProperty);
|
||||||
|
LayerPropertyGroupViewModel LayerPropertyGroupViewModel(LayerPropertyGroup layerPropertyGroup);
|
||||||
|
LayerPropertyTreeViewModel<T> LayerPropertyGroupViewModel<T>(LayerProperty<T> layerProperty);
|
||||||
|
LayerPropertyGroupTreeViewModel LayerPropertyGroupTreeViewModel(LayerPropertyGroupViewModel layerPropertyGroupViewModel);
|
||||||
LayerPropertyGroupViewModel LayerPropertyGroupViewModel(LayerPropertyGroup layerPropertyGroup, PropertyGroupDescriptionAttribute propertyGroupDescription);
|
LayerPropertyGroupViewModel LayerPropertyGroupViewModel(LayerPropertyGroup layerPropertyGroup, PropertyGroupDescriptionAttribute propertyGroupDescription);
|
||||||
TreeViewModel TreeViewModel(LayerPropertiesViewModel layerPropertiesViewModel, BindableCollection<LayerPropertyGroupViewModel> layerPropertyGroups);
|
TreeViewModel TreeViewModel(LayerPropertiesViewModel layerPropertiesViewModel, BindableCollection<LayerPropertyGroupViewModel> layerPropertyGroups);
|
||||||
EffectsViewModel EffectsViewModel(LayerPropertiesViewModel layerPropertiesViewModel);
|
EffectsViewModel EffectsViewModel(LayerPropertiesViewModel layerPropertiesViewModel);
|
||||||
TimelineViewModel TimelineViewModel(LayerPropertiesViewModel layerPropertiesViewModel, BindableCollection<LayerPropertyGroupViewModel> layerPropertyGroups);
|
TimelineViewModel TimelineViewModel(LayerPropertiesViewModel layerPropertiesViewModel, BindableCollection<LayerPropertyGroupViewModel> layerPropertyGroups);
|
||||||
TreePropertyGroupViewModel TreePropertyGroupViewModel(LayerPropertyBaseViewModel layerPropertyBaseViewModel);
|
|
||||||
TimelinePropertyGroupViewModel TimelinePropertyGroupViewModel(LayerPropertyBaseViewModel layerPropertyBaseViewModel);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -53,7 +53,7 @@ namespace Artemis.UI.Ninject
|
|||||||
{
|
{
|
||||||
x.FromThisAssembly()
|
x.FromThisAssembly()
|
||||||
.SelectAllClasses()
|
.SelectAllClasses()
|
||||||
.InheritedFrom<ProfileEditorPanelViewModel>()
|
.InheritedFrom<IProfileEditorPanelViewModel>()
|
||||||
.BindAllBaseClasses();
|
.BindAllBaseClasses();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1,44 +1,23 @@
|
|||||||
using System;
|
using Artemis.Core;
|
||||||
using Artemis.Core;
|
|
||||||
using Stylet;
|
using Stylet;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions.Abstract
|
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions.Abstract
|
||||||
{
|
{
|
||||||
public abstract class DisplayConditionViewModel : PropertyChangedBase, IDisposable
|
public abstract class DisplayConditionViewModel : Conductor<DisplayConditionViewModel>.Collection.AllActive
|
||||||
{
|
{
|
||||||
protected DisplayConditionViewModel(DisplayConditionPart model, DisplayConditionViewModel parent)
|
protected DisplayConditionViewModel(DisplayConditionPart model)
|
||||||
{
|
{
|
||||||
Model = model;
|
Model = model;
|
||||||
Parent = parent;
|
|
||||||
Children = new BindableCollection<DisplayConditionViewModel>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public DisplayConditionPart Model { get; }
|
public DisplayConditionPart Model { get; }
|
||||||
public DisplayConditionViewModel Parent { get; set; }
|
|
||||||
public BindableCollection<DisplayConditionViewModel> Children { get; }
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
foreach (var child in Children)
|
|
||||||
child.Dispose();
|
|
||||||
|
|
||||||
Dispose(true);
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void Update();
|
public abstract void Update();
|
||||||
|
|
||||||
public virtual void Delete()
|
public virtual void Delete()
|
||||||
{
|
{
|
||||||
Model.Parent.RemoveChild(Model);
|
Model.Parent.RemoveChild(Model);
|
||||||
Parent.Update();
|
((DisplayConditionViewModel) Parent).Update();
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -124,7 +124,7 @@
|
|||||||
<materialDesign:PackIcon Kind="Add" Width="18" Height="18" />
|
<materialDesign:PackIcon Kind="Add" Width="18" Height="18" />
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<ItemsControl Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" ItemsSource="{Binding Children}">
|
<ItemsControl Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" ItemsSource="{Binding Items}">
|
||||||
<ItemsControl.ItemTemplate>
|
<ItemsControl.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<materialDesign:TransitioningContent>
|
<materialDesign:TransitioningContent>
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows;
|
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.UI.Ninject.Factories;
|
using Artemis.UI.Ninject.Factories;
|
||||||
using Artemis.UI.Screens.ProfileEditor.DisplayConditions.Abstract;
|
using Artemis.UI.Screens.ProfileEditor.DisplayConditions.Abstract;
|
||||||
@ -11,21 +10,24 @@ using Stylet;
|
|||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||||
{
|
{
|
||||||
public class DisplayConditionGroupViewModel : DisplayConditionViewModel, IViewAware
|
public class DisplayConditionGroupViewModel : DisplayConditionViewModel
|
||||||
{
|
{
|
||||||
private readonly IDisplayConditionsVmFactory _displayConditionsVmFactory;
|
private readonly IDisplayConditionsVmFactory _displayConditionsVmFactory;
|
||||||
private readonly IProfileEditorService _profileEditorService;
|
private readonly IProfileEditorService _profileEditorService;
|
||||||
private bool _isInitialized;
|
private bool _isInitialized;
|
||||||
private bool _isRootGroup;
|
private bool _isRootGroup;
|
||||||
|
|
||||||
public DisplayConditionGroupViewModel(DisplayConditionGroup displayConditionGroup, DisplayConditionViewModel parent, bool isListGroup,
|
public DisplayConditionGroupViewModel(DisplayConditionGroup displayConditionGroup,
|
||||||
IProfileEditorService profileEditorService, IDisplayConditionsVmFactory displayConditionsVmFactory) : base(displayConditionGroup, parent)
|
bool isListGroup,
|
||||||
|
IProfileEditorService profileEditorService,
|
||||||
|
IDisplayConditionsVmFactory displayConditionsVmFactory)
|
||||||
|
: base(displayConditionGroup)
|
||||||
{
|
{
|
||||||
IsListGroup = isListGroup;
|
IsListGroup = isListGroup;
|
||||||
_profileEditorService = profileEditorService;
|
_profileEditorService = profileEditorService;
|
||||||
_displayConditionsVmFactory = displayConditionsVmFactory;
|
_displayConditionsVmFactory = displayConditionsVmFactory;
|
||||||
|
|
||||||
Children.CollectionChanged += (sender, args) => NotifyOfPropertyChange(nameof(DisplayBooleanOperator));
|
Items.CollectionChanged += (sender, args) => NotifyOfPropertyChange(nameof(DisplayBooleanOperator));
|
||||||
|
|
||||||
Execute.PostToUIThread(async () =>
|
Execute.PostToUIThread(async () =>
|
||||||
{
|
{
|
||||||
@ -50,16 +52,9 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
|||||||
set => SetAndNotify(ref _isInitialized, value);
|
set => SetAndNotify(ref _isInitialized, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool DisplayBooleanOperator => Children.Count > 1;
|
public bool DisplayBooleanOperator => Items.Count > 1;
|
||||||
public string SelectedBooleanOperator => DisplayConditionGroup.BooleanOperator.Humanize();
|
public string SelectedBooleanOperator => DisplayConditionGroup.BooleanOperator.Humanize();
|
||||||
|
|
||||||
public void AttachView(UIElement view)
|
|
||||||
{
|
|
||||||
View = view;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UIElement View { get; set; }
|
|
||||||
|
|
||||||
public void SelectBooleanOperator(string type)
|
public void SelectBooleanOperator(string type)
|
||||||
{
|
{
|
||||||
var enumValue = Enum.Parse<BooleanOperator>(type);
|
var enumValue = Enum.Parse<BooleanOperator>(type);
|
||||||
@ -105,39 +100,36 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
|||||||
NotifyOfPropertyChange(nameof(SelectedBooleanOperator));
|
NotifyOfPropertyChange(nameof(SelectedBooleanOperator));
|
||||||
|
|
||||||
// Remove VMs of effects no longer applied on the layer
|
// Remove VMs of effects no longer applied on the layer
|
||||||
var toRemove = Children.Where(c => !DisplayConditionGroup.Children.Contains(c.Model)).ToList();
|
var toRemove = Items.Where(c => !DisplayConditionGroup.Children.Contains(c.Model)).ToList();
|
||||||
// Using RemoveRange breaks our lovely animations
|
// Using RemoveRange breaks our lovely animations
|
||||||
foreach (var displayConditionViewModel in toRemove)
|
foreach (var displayConditionViewModel in toRemove)
|
||||||
{
|
CloseItem(displayConditionViewModel);
|
||||||
Children.Remove(displayConditionViewModel);
|
|
||||||
displayConditionViewModel.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var childModel in Model.Children)
|
foreach (var childModel in Model.Children)
|
||||||
{
|
{
|
||||||
if (Children.Any(c => c.Model == childModel))
|
if (Items.Any(c => c.Model == childModel))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
switch (childModel)
|
switch (childModel)
|
||||||
{
|
{
|
||||||
case DisplayConditionGroup displayConditionGroup:
|
case DisplayConditionGroup displayConditionGroup:
|
||||||
Children.Add(_displayConditionsVmFactory.DisplayConditionGroupViewModel(displayConditionGroup, this, IsListGroup));
|
ActivateItem(_displayConditionsVmFactory.DisplayConditionGroupViewModel(displayConditionGroup, IsListGroup));
|
||||||
break;
|
break;
|
||||||
case DisplayConditionList displayConditionListPredicate:
|
case DisplayConditionList displayConditionListPredicate:
|
||||||
Children.Add(_displayConditionsVmFactory.DisplayConditionListViewModel(displayConditionListPredicate, this));
|
ActivateItem(_displayConditionsVmFactory.DisplayConditionListViewModel(displayConditionListPredicate));
|
||||||
break;
|
break;
|
||||||
case DisplayConditionPredicate displayConditionPredicate:
|
case DisplayConditionPredicate displayConditionPredicate:
|
||||||
if (!IsListGroup)
|
if (!IsListGroup)
|
||||||
Children.Add(_displayConditionsVmFactory.DisplayConditionPredicateViewModel(displayConditionPredicate, this));
|
ActivateItem(_displayConditionsVmFactory.DisplayConditionPredicateViewModel(displayConditionPredicate));
|
||||||
break;
|
break;
|
||||||
case DisplayConditionListPredicate displayConditionListPredicate:
|
case DisplayConditionListPredicate displayConditionListPredicate:
|
||||||
if (IsListGroup)
|
if (IsListGroup)
|
||||||
Children.Add(_displayConditionsVmFactory.DisplayConditionListPredicateViewModel(displayConditionListPredicate, this));
|
ActivateItem(_displayConditionsVmFactory.DisplayConditionListPredicateViewModel(displayConditionListPredicate));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var childViewModel in Children)
|
foreach (var childViewModel in Items)
|
||||||
childViewModel.Update();
|
childViewModel.Update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,9 +17,9 @@ using Stylet;
|
|||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||||
{
|
{
|
||||||
public class DisplayConditionListPredicateViewModel : DisplayConditionViewModel, IHandle<MainWindowKeyEvent>, IHandle<MainWindowMouseEvent>
|
public class DisplayConditionListPredicateViewModel : DisplayConditionViewModel, IHandle<MainWindowKeyEvent>, IHandle<MainWindowMouseEvent>, IDisposable
|
||||||
{
|
{
|
||||||
private readonly IDataModelService _dataModelService;
|
private readonly IConditionOperatorService _conditionOperatorService;
|
||||||
private readonly IDataModelUIService _dataModelUIService;
|
private readonly IDataModelUIService _dataModelUIService;
|
||||||
private readonly IEventAggregator _eventAggregator;
|
private readonly IEventAggregator _eventAggregator;
|
||||||
private readonly IProfileEditorService _profileEditorService;
|
private readonly IProfileEditorService _profileEditorService;
|
||||||
@ -39,16 +39,15 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
|||||||
|
|
||||||
public DisplayConditionListPredicateViewModel(
|
public DisplayConditionListPredicateViewModel(
|
||||||
DisplayConditionListPredicate displayConditionListPredicate,
|
DisplayConditionListPredicate displayConditionListPredicate,
|
||||||
DisplayConditionViewModel parent,
|
|
||||||
IProfileEditorService profileEditorService,
|
IProfileEditorService profileEditorService,
|
||||||
IDataModelUIService dataModelUIService,
|
IDataModelUIService dataModelUIService,
|
||||||
IDataModelService dataModelService,
|
IConditionOperatorService conditionOperatorService,
|
||||||
ISettingsService settingsService,
|
ISettingsService settingsService,
|
||||||
IEventAggregator eventAggregator) : base(displayConditionListPredicate, parent)
|
IEventAggregator eventAggregator) : base(displayConditionListPredicate)
|
||||||
{
|
{
|
||||||
_profileEditorService = profileEditorService;
|
_profileEditorService = profileEditorService;
|
||||||
_dataModelUIService = dataModelUIService;
|
_dataModelUIService = dataModelUIService;
|
||||||
_dataModelService = dataModelService;
|
_conditionOperatorService = conditionOperatorService;
|
||||||
_eventAggregator = eventAggregator;
|
_eventAggregator = eventAggregator;
|
||||||
_updateTimer = new Timer(500);
|
_updateTimer = new Timer(500);
|
||||||
_supportedInputTypes = new List<Type>();
|
_supportedInputTypes = new List<Type>();
|
||||||
@ -206,7 +205,7 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
|||||||
|
|
||||||
// Get the supported operators
|
// Get the supported operators
|
||||||
Operators.Clear();
|
Operators.Clear();
|
||||||
Operators.AddRange(_dataModelService.GetConditionOperatorsForType(leftSideType));
|
Operators.AddRange(_conditionOperatorService.GetConditionOperatorsForType(leftSideType));
|
||||||
if (DisplayConditionListPredicate.Operator == null)
|
if (DisplayConditionListPredicate.Operator == null)
|
||||||
DisplayConditionListPredicate.UpdateOperator(Operators.FirstOrDefault(o => o.SupportsType(leftSideType)));
|
DisplayConditionListPredicate.UpdateOperator(Operators.FirstOrDefault(o => o.SupportsType(leftSideType)));
|
||||||
SelectedOperator = DisplayConditionListPredicate.Operator;
|
SelectedOperator = DisplayConditionListPredicate.Operator;
|
||||||
@ -277,12 +276,6 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
|||||||
_eventAggregator.Subscribe(this);
|
_eventAggregator.Subscribe(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
_updateTimer.Stop();
|
|
||||||
_updateTimer.Elapsed -= OnUpdateTimerOnElapsed;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnUpdateTimerOnElapsed(object sender, ElapsedEventArgs e)
|
private void OnUpdateTimerOnElapsed(object sender, ElapsedEventArgs e)
|
||||||
{
|
{
|
||||||
if (LeftSideDataModelOpen)
|
if (LeftSideDataModelOpen)
|
||||||
@ -353,5 +346,11 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
|||||||
SelectedOperator = displayConditionOperator;
|
SelectedOperator = displayConditionOperator;
|
||||||
ApplyOperator();
|
ApplyOperator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_updateTimer.Dispose();
|
||||||
|
_updateTimer.Elapsed -= OnUpdateTimerOnElapsed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -105,7 +105,7 @@
|
|||||||
</Button.ContextMenu>
|
</Button.ContextMenu>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<ItemsControl Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" ItemsSource="{Binding Children}" Margin="0 4 0 0">
|
<ItemsControl Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" ItemsSource="{Binding Items}" Margin="0 4 0 0">
|
||||||
<ItemsControl.ItemTemplate>
|
<ItemsControl.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<materialDesign:TransitioningContent>
|
<materialDesign:TransitioningContent>
|
||||||
|
|||||||
@ -14,7 +14,7 @@ using Humanizer;
|
|||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||||
{
|
{
|
||||||
public class DisplayConditionListViewModel : DisplayConditionViewModel
|
public class DisplayConditionListViewModel : DisplayConditionViewModel, IDisposable
|
||||||
{
|
{
|
||||||
private readonly IDataModelUIService _dataModelUIService;
|
private readonly IDataModelUIService _dataModelUIService;
|
||||||
private readonly IDisplayConditionsVmFactory _displayConditionsVmFactory;
|
private readonly IDisplayConditionsVmFactory _displayConditionsVmFactory;
|
||||||
@ -30,7 +30,7 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
|||||||
IProfileEditorService profileEditorService,
|
IProfileEditorService profileEditorService,
|
||||||
IDataModelUIService dataModelUIService,
|
IDataModelUIService dataModelUIService,
|
||||||
IDisplayConditionsVmFactory displayConditionsVmFactory,
|
IDisplayConditionsVmFactory displayConditionsVmFactory,
|
||||||
ISettingsService settingsService) : base(displayConditionList, parent)
|
ISettingsService settingsService) : base(displayConditionList)
|
||||||
{
|
{
|
||||||
_profileEditorService = profileEditorService;
|
_profileEditorService = profileEditorService;
|
||||||
_dataModelUIService = dataModelUIService;
|
_dataModelUIService = dataModelUIService;
|
||||||
@ -152,36 +152,27 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
|||||||
TargetDataModel.ApplyTypeFilter(true, typeof(IList));
|
TargetDataModel.ApplyTypeFilter(true, typeof(IList));
|
||||||
|
|
||||||
// Remove VMs of effects no longer applied on the layer
|
// Remove VMs of effects no longer applied on the layer
|
||||||
var toRemove = Children.Where(c => !DisplayConditionList.Children.Contains(c.Model)).ToList();
|
var toRemove = Items.Where(c => !DisplayConditionList.Children.Contains(c.Model)).ToList();
|
||||||
// Using RemoveRange breaks our lovely animations
|
// Using RemoveRange breaks our lovely animations
|
||||||
foreach (var displayConditionViewModel in toRemove)
|
foreach (var displayConditionViewModel in toRemove)
|
||||||
{
|
CloseItem(displayConditionViewModel);
|
||||||
Children.Remove(displayConditionViewModel);
|
|
||||||
displayConditionViewModel.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var childModel in Model.Children)
|
foreach (var childModel in Model.Children)
|
||||||
{
|
{
|
||||||
if (Children.Any(c => c.Model == childModel))
|
if (Items.Any(c => c.Model == childModel))
|
||||||
continue;
|
continue;
|
||||||
if (!(childModel is DisplayConditionGroup displayConditionGroup))
|
if (!(childModel is DisplayConditionGroup displayConditionGroup))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var viewModel = _displayConditionsVmFactory.DisplayConditionGroupViewModel(displayConditionGroup, this, true);
|
var viewModel = _displayConditionsVmFactory.DisplayConditionGroupViewModel(displayConditionGroup, true);
|
||||||
viewModel.IsRootGroup = true;
|
viewModel.IsRootGroup = true;
|
||||||
Children.Add(viewModel);
|
ActivateItem(viewModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var childViewModel in Children)
|
foreach (var childViewModel in Items)
|
||||||
childViewModel.Update();
|
childViewModel.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
_updateTimer.Stop();
|
|
||||||
_updateTimer.Elapsed -= OnUpdateTimerOnElapsed;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnUpdateTimerOnElapsed(object sender, ElapsedEventArgs e)
|
private void OnUpdateTimerOnElapsed(object sender, ElapsedEventArgs e)
|
||||||
{
|
{
|
||||||
if (TargetDataModelOpen)
|
if (TargetDataModelOpen)
|
||||||
@ -205,5 +196,11 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
|||||||
SelectedListProperty = dataModelListViewModel;
|
SelectedListProperty = dataModelListViewModel;
|
||||||
ApplyList();
|
ApplyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_updateTimer.Dispose();
|
||||||
|
_updateTimer.Elapsed -= OnUpdateTimerOnElapsed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -16,9 +16,9 @@ using Stylet;
|
|||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||||
{
|
{
|
||||||
public class DisplayConditionPredicateViewModel : DisplayConditionViewModel, IHandle<MainWindowKeyEvent>, IHandle<MainWindowMouseEvent>
|
public class DisplayConditionPredicateViewModel : DisplayConditionViewModel, IHandle<MainWindowKeyEvent>, IHandle<MainWindowMouseEvent>, IDisposable
|
||||||
{
|
{
|
||||||
private readonly IDataModelService _dataModelService;
|
private readonly IConditionOperatorService _conditionOperatorService;
|
||||||
private readonly IDataModelUIService _dataModelUIService;
|
private readonly IDataModelUIService _dataModelUIService;
|
||||||
private readonly IEventAggregator _eventAggregator;
|
private readonly IEventAggregator _eventAggregator;
|
||||||
private readonly IProfileEditorService _profileEditorService;
|
private readonly IProfileEditorService _profileEditorService;
|
||||||
@ -38,16 +38,15 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
|||||||
|
|
||||||
public DisplayConditionPredicateViewModel(
|
public DisplayConditionPredicateViewModel(
|
||||||
DisplayConditionPredicate displayConditionPredicate,
|
DisplayConditionPredicate displayConditionPredicate,
|
||||||
DisplayConditionViewModel parent,
|
|
||||||
IProfileEditorService profileEditorService,
|
IProfileEditorService profileEditorService,
|
||||||
IDataModelUIService dataModelUIService,
|
IDataModelUIService dataModelUIService,
|
||||||
IDataModelService dataModelService,
|
IConditionOperatorService conditionOperatorService,
|
||||||
ISettingsService settingsService,
|
ISettingsService settingsService,
|
||||||
IEventAggregator eventAggregator) : base(displayConditionPredicate, parent)
|
IEventAggregator eventAggregator) : base(displayConditionPredicate)
|
||||||
{
|
{
|
||||||
_profileEditorService = profileEditorService;
|
_profileEditorService = profileEditorService;
|
||||||
_dataModelUIService = dataModelUIService;
|
_dataModelUIService = dataModelUIService;
|
||||||
_dataModelService = dataModelService;
|
_conditionOperatorService = conditionOperatorService;
|
||||||
_eventAggregator = eventAggregator;
|
_eventAggregator = eventAggregator;
|
||||||
_updateTimer = new Timer(500);
|
_updateTimer = new Timer(500);
|
||||||
_supportedInputTypes = new List<Type>();
|
_supportedInputTypes = new List<Type>();
|
||||||
@ -208,7 +207,7 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
|||||||
|
|
||||||
// Get the supported operators
|
// Get the supported operators
|
||||||
Operators.Clear();
|
Operators.Clear();
|
||||||
Operators.AddRange(_dataModelService.GetConditionOperatorsForType(leftSideType));
|
Operators.AddRange(_conditionOperatorService.GetConditionOperatorsForType(leftSideType));
|
||||||
if (DisplayConditionPredicate.Operator == null)
|
if (DisplayConditionPredicate.Operator == null)
|
||||||
DisplayConditionPredicate.UpdateOperator(Operators.FirstOrDefault(o => o.SupportsType(leftSideType)));
|
DisplayConditionPredicate.UpdateOperator(Operators.FirstOrDefault(o => o.SupportsType(leftSideType)));
|
||||||
SelectedOperator = DisplayConditionPredicate.Operator;
|
SelectedOperator = DisplayConditionPredicate.Operator;
|
||||||
@ -278,13 +277,7 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
|||||||
);
|
);
|
||||||
_eventAggregator.Subscribe(this);
|
_eventAggregator.Subscribe(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
_updateTimer.Stop();
|
|
||||||
_updateTimer.Elapsed -= OnUpdateTimerOnElapsed;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnUpdateTimerOnElapsed(object sender, ElapsedEventArgs e)
|
private void OnUpdateTimerOnElapsed(object sender, ElapsedEventArgs e)
|
||||||
{
|
{
|
||||||
if (LeftSideDataModelOpen)
|
if (LeftSideDataModelOpen)
|
||||||
@ -335,5 +328,11 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
|||||||
SelectedOperator = displayConditionOperator;
|
SelectedOperator = displayConditionOperator;
|
||||||
ApplyOperator();
|
ApplyOperator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_updateTimer.Dispose();
|
||||||
|
_updateTimer.Elapsed -= OnUpdateTimerOnElapsed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -43,7 +43,7 @@
|
|||||||
|
|
||||||
<Grid Grid.Row="2" Grid.Column="0">
|
<Grid Grid.Row="2" Grid.Column="0">
|
||||||
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" Background="{StaticResource MaterialDesignCardBackground}">
|
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" Background="{StaticResource MaterialDesignCardBackground}">
|
||||||
<ContentControl s:View.Model="{Binding RootGroup}" />
|
<ContentControl s:View.Model="{Binding ActiveItem}" />
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
|
|||||||
@ -3,17 +3,17 @@ using Artemis.Core;
|
|||||||
using Artemis.UI.Ninject.Factories;
|
using Artemis.UI.Ninject.Factories;
|
||||||
using Artemis.UI.Shared;
|
using Artemis.UI.Shared;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
|
using Stylet;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||||
{
|
{
|
||||||
public class DisplayConditionsViewModel : ProfileEditorPanelViewModel
|
public class DisplayConditionsViewModel : Conductor<DisplayConditionGroupViewModel>, IProfileEditorPanelViewModel
|
||||||
{
|
{
|
||||||
private readonly IDisplayConditionsVmFactory _displayConditionsVmFactory;
|
private readonly IDisplayConditionsVmFactory _displayConditionsVmFactory;
|
||||||
private readonly IProfileEditorService _profileEditorService;
|
private readonly IProfileEditorService _profileEditorService;
|
||||||
private bool _alwaysFinishTimeline;
|
private bool _alwaysFinishTimeline;
|
||||||
private bool _displayContinuously;
|
private bool _displayContinuously;
|
||||||
private RenderProfileElement _renderProfileElement;
|
private RenderProfileElement _renderProfileElement;
|
||||||
private DisplayConditionGroupViewModel _rootGroup;
|
|
||||||
private int _transitionerIndex;
|
private int _transitionerIndex;
|
||||||
|
|
||||||
public DisplayConditionsViewModel(IProfileEditorService profileEditorService, IDisplayConditionsVmFactory displayConditionsVmFactory)
|
public DisplayConditionsViewModel(IProfileEditorService profileEditorService, IDisplayConditionsVmFactory displayConditionsVmFactory)
|
||||||
@ -28,11 +28,6 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
|||||||
set => SetAndNotify(ref _transitionerIndex, value);
|
set => SetAndNotify(ref _transitionerIndex, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DisplayConditionGroupViewModel RootGroup
|
|
||||||
{
|
|
||||||
get => _rootGroup;
|
|
||||||
set => SetAndNotify(ref _rootGroup, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public RenderProfileElement RenderProfileElement
|
public RenderProfileElement RenderProfileElement
|
||||||
{
|
{
|
||||||
@ -70,9 +65,6 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
|||||||
protected override void OnDeactivate()
|
protected override void OnDeactivate()
|
||||||
{
|
{
|
||||||
_profileEditorService.ProfileElementSelected -= ProfileEditorServiceOnProfileElementSelected;
|
_profileEditorService.ProfileElementSelected -= ProfileEditorServiceOnProfileElementSelected;
|
||||||
|
|
||||||
RootGroup?.Dispose();
|
|
||||||
RootGroup = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProfileEditorServiceOnProfileElementSelected(object sender, RenderProfileElementEventArgs e)
|
private void ProfileEditorServiceOnProfileElementSelected(object sender, RenderProfileElementEventArgs e)
|
||||||
@ -87,8 +79,7 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
|||||||
|
|
||||||
if (e.RenderProfileElement == null)
|
if (e.RenderProfileElement == null)
|
||||||
{
|
{
|
||||||
RootGroup?.Dispose();
|
ActiveItem = null;
|
||||||
RootGroup = null;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,14 +87,13 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
|||||||
if (e.RenderProfileElement.DisplayConditionGroup == null)
|
if (e.RenderProfileElement.DisplayConditionGroup == null)
|
||||||
e.RenderProfileElement.DisplayConditionGroup = new DisplayConditionGroup(null);
|
e.RenderProfileElement.DisplayConditionGroup = new DisplayConditionGroup(null);
|
||||||
|
|
||||||
RootGroup?.Dispose();
|
ActiveItem = _displayConditionsVmFactory.DisplayConditionGroupViewModel(e.RenderProfileElement.DisplayConditionGroup, false);
|
||||||
RootGroup = _displayConditionsVmFactory.DisplayConditionGroupViewModel(e.RenderProfileElement.DisplayConditionGroup, null, false);
|
ActiveItem.IsRootGroup = true;
|
||||||
RootGroup.IsRootGroup = true;
|
ActiveItem.Update();
|
||||||
RootGroup.Update();
|
|
||||||
|
|
||||||
// Only show the intro to conditions once, and only if the layer has no conditions
|
// Only show the intro to conditions once, and only if the layer has no conditions
|
||||||
if (TransitionerIndex != 1)
|
if (TransitionerIndex != 1)
|
||||||
TransitionerIndex = RootGroup.Children.Any() ? 1 : 0;
|
TransitionerIndex = ActiveItem.Items.Any() ? 1 : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor
|
namespace Artemis.UI.Screens.ProfileEditor
|
||||||
{
|
{
|
||||||
public class ProfileEditorPanelViewModel : Screen
|
public interface IProfileEditorPanelViewModel : IScreen
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,36 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Artemis.Core;
|
|
||||||
using Stylet;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Abstract
|
|
||||||
{
|
|
||||||
public abstract class LayerPropertyBaseViewModel : PropertyChangedBase, IDisposable
|
|
||||||
{
|
|
||||||
private BindableCollection<LayerPropertyBaseViewModel> _children;
|
|
||||||
private bool _isExpanded;
|
|
||||||
|
|
||||||
protected LayerPropertyBaseViewModel()
|
|
||||||
{
|
|
||||||
Children = new BindableCollection<LayerPropertyBaseViewModel>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract bool IsVisible { get; }
|
|
||||||
|
|
||||||
public virtual bool IsExpanded
|
|
||||||
{
|
|
||||||
get => _isExpanded;
|
|
||||||
set => SetAndNotify(ref _isExpanded, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BindableCollection<LayerPropertyBaseViewModel> Children
|
|
||||||
{
|
|
||||||
get => _children;
|
|
||||||
set => SetAndNotify(ref _children, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void Dispose();
|
|
||||||
|
|
||||||
public abstract List<BaseLayerPropertyKeyframe> GetKeyframes(bool expandedOnly);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -9,32 +9,22 @@ using Stylet;
|
|||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.LayerEffects
|
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.LayerEffects
|
||||||
{
|
{
|
||||||
public class EffectsViewModel : PropertyChangedBase
|
public class EffectsViewModel : Conductor<LayerEffectDescriptor>.Collection.AllActive
|
||||||
{
|
{
|
||||||
private readonly IPluginService _pluginService;
|
private readonly IPluginService _pluginService;
|
||||||
private readonly IProfileEditorService _profileEditorService;
|
private readonly IProfileEditorService _profileEditorService;
|
||||||
private readonly IRenderElementService _renderElementService;
|
|
||||||
private BindableCollection<LayerEffectDescriptor> _layerEffectDescriptors;
|
|
||||||
private LayerEffectDescriptor _selectedLayerEffectDescriptor;
|
private LayerEffectDescriptor _selectedLayerEffectDescriptor;
|
||||||
|
|
||||||
public EffectsViewModel(LayerPropertiesViewModel layerPropertiesViewModel, IPluginService pluginService, IRenderElementService renderElementService, IProfileEditorService profileEditorService)
|
public EffectsViewModel(LayerPropertiesViewModel layerPropertiesViewModel, IPluginService pluginService, IProfileEditorService profileEditorService)
|
||||||
{
|
{
|
||||||
_pluginService = pluginService;
|
_pluginService = pluginService;
|
||||||
_renderElementService = renderElementService;
|
|
||||||
_profileEditorService = profileEditorService;
|
_profileEditorService = profileEditorService;
|
||||||
LayerPropertiesViewModel = layerPropertiesViewModel;
|
LayerPropertiesViewModel = layerPropertiesViewModel;
|
||||||
LayerEffectDescriptors = new BindableCollection<LayerEffectDescriptor>();
|
|
||||||
PropertyChanged += HandleSelectedLayerEffectChanged;
|
PropertyChanged += HandleSelectedLayerEffectChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LayerPropertiesViewModel LayerPropertiesViewModel { get; }
|
public LayerPropertiesViewModel LayerPropertiesViewModel { get; }
|
||||||
public bool HasLayerEffectDescriptors => LayerEffectDescriptors.Any();
|
public bool HasLayerEffectDescriptors => Items.Any();
|
||||||
|
|
||||||
public BindableCollection<LayerEffectDescriptor> LayerEffectDescriptors
|
|
||||||
{
|
|
||||||
get => _layerEffectDescriptors;
|
|
||||||
set => SetAndNotify(ref _layerEffectDescriptors, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayerEffectDescriptor SelectedLayerEffectDescriptor
|
public LayerEffectDescriptor SelectedLayerEffectDescriptor
|
||||||
{
|
{
|
||||||
@ -46,15 +36,15 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.LayerEffects
|
|||||||
{
|
{
|
||||||
var layerBrushProviders = _pluginService.GetPluginsOfType<LayerEffectProvider>();
|
var layerBrushProviders = _pluginService.GetPluginsOfType<LayerEffectProvider>();
|
||||||
var descriptors = layerBrushProviders.SelectMany(l => l.LayerEffectDescriptors).ToList();
|
var descriptors = layerBrushProviders.SelectMany(l => l.LayerEffectDescriptors).ToList();
|
||||||
LayerEffectDescriptors.AddRange(descriptors.Except(LayerEffectDescriptors));
|
Items.AddRange(descriptors.Except(Items));
|
||||||
LayerEffectDescriptors.RemoveRange(LayerEffectDescriptors.Except(descriptors));
|
Items.RemoveRange(Items.Except(descriptors));
|
||||||
|
|
||||||
// Sort by display name
|
// Sort by display name
|
||||||
var index = 0;
|
var index = 0;
|
||||||
foreach (var layerEffectDescriptor in LayerEffectDescriptors.OrderBy(d => d.DisplayName).ToList())
|
foreach (var layerEffectDescriptor in Items.OrderBy(d => d.DisplayName).ToList())
|
||||||
{
|
{
|
||||||
if (LayerEffectDescriptors.IndexOf(layerEffectDescriptor) != index)
|
if (Items.IndexOf(layerEffectDescriptor) != index)
|
||||||
LayerEffectDescriptors.Move(LayerEffectDescriptors.IndexOf(layerEffectDescriptor), index);
|
((BindableCollection<LayerEffectDescriptor>) Items).Move(Items.IndexOf(layerEffectDescriptor), index);
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,7 +68,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.LayerEffects
|
|||||||
Execute.PostToUIThread(async () =>
|
Execute.PostToUIThread(async () =>
|
||||||
{
|
{
|
||||||
await Task.Delay(500);
|
await Task.Delay(500);
|
||||||
_renderElementService.AddLayerEffect(renderElement, SelectedLayerEffectDescriptor);
|
renderElement.AddLayerEffect(SelectedLayerEffectDescriptor);
|
||||||
_profileEditorService.UpdateSelectedProfileElement();
|
_profileEditorService.UpdateSelectedProfileElement();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,11 +16,10 @@ using Artemis.UI.Shared;
|
|||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
using GongSolutions.Wpf.DragDrop;
|
using GongSolutions.Wpf.DragDrop;
|
||||||
using Stylet;
|
using Stylet;
|
||||||
using static Artemis.UI.Screens.ProfileEditor.LayerProperties.LayerPropertyGroupViewModel.ViewModelType;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
|
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
|
||||||
{
|
{
|
||||||
public class LayerPropertiesViewModel : ProfileEditorPanelViewModel, IDropTarget
|
public class LayerPropertiesViewModel : Conductor<IScreen>.Collection.AllActive, IProfileEditorPanelViewModel, IDropTarget
|
||||||
{
|
{
|
||||||
private readonly ILayerPropertyVmFactory _layerPropertyVmFactory;
|
private readonly ILayerPropertyVmFactory _layerPropertyVmFactory;
|
||||||
private readonly IDataBindingsVmFactory _dataBindingsVmFactory;
|
private readonly IDataBindingsVmFactory _dataBindingsVmFactory;
|
||||||
|
|||||||
@ -1,58 +1,31 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.UI.Ninject.Factories;
|
using Artemis.UI.Ninject.Factories;
|
||||||
using Artemis.UI.Screens.ProfileEditor.LayerProperties.Abstract;
|
|
||||||
using Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline;
|
|
||||||
using Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree;
|
using Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree;
|
||||||
using Artemis.UI.Shared.Services;
|
using Stylet;
|
||||||
using Humanizer;
|
|
||||||
using Ninject;
|
|
||||||
using Ninject.Parameters;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
|
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
|
||||||
{
|
{
|
||||||
public class LayerPropertyGroupViewModel : LayerPropertyBaseViewModel
|
public class LayerPropertyGroupViewModel : PropertyChangedBase, IDisposable
|
||||||
{
|
{
|
||||||
private readonly ILayerPropertyVmFactory _layerPropertyVmFactory;
|
private readonly ILayerPropertyVmFactory _layerPropertyVmFactory;
|
||||||
private ViewModelType _groupType;
|
|
||||||
private TimelinePropertyGroupViewModel _timelinePropertyGroupViewModel;
|
|
||||||
private TreePropertyGroupViewModel _treePropertyGroupViewModel;
|
|
||||||
|
|
||||||
public LayerPropertyGroupViewModel(LayerPropertyGroup layerPropertyGroup, PropertyGroupDescriptionAttribute propertyGroupDescription,
|
public LayerPropertyGroupViewModel(LayerPropertyGroup layerPropertyGroup, ILayerPropertyVmFactory layerPropertyVmFactory)
|
||||||
IProfileEditorService profileEditorService, ILayerPropertyVmFactory layerPropertyVmFactory)
|
|
||||||
{
|
{
|
||||||
_layerPropertyVmFactory = layerPropertyVmFactory;
|
_layerPropertyVmFactory = layerPropertyVmFactory;
|
||||||
ProfileEditorService = profileEditorService;
|
|
||||||
|
|
||||||
LayerPropertyGroup = layerPropertyGroup;
|
LayerPropertyGroup = layerPropertyGroup;
|
||||||
PropertyGroupDescription = propertyGroupDescription;
|
LayerPropertyGroupTreeViewModel = layerPropertyVmFactory.LayerPropertyGroupTreeViewModel(this);
|
||||||
|
|
||||||
TreePropertyGroupViewModel = _layerPropertyVmFactory.TreePropertyGroupViewModel(this);
|
|
||||||
TimelinePropertyGroupViewModel = _layerPropertyVmFactory.TimelinePropertyGroupViewModel(this);
|
|
||||||
|
|
||||||
// Generate a fallback name if the description does not contain one
|
|
||||||
if (PropertyGroupDescription.Name == null)
|
|
||||||
{
|
|
||||||
var propertyInfo = LayerPropertyGroup.Parent?.GetType().GetProperties().FirstOrDefault(p => ReferenceEquals(p.GetValue(LayerPropertyGroup.Parent), LayerPropertyGroup));
|
|
||||||
if (propertyInfo != null)
|
|
||||||
PropertyGroupDescription.Name = propertyInfo.Name.Humanize();
|
|
||||||
else
|
|
||||||
PropertyGroupDescription.Name = "Unknown group";
|
|
||||||
}
|
|
||||||
|
|
||||||
LayerPropertyGroup.VisibilityChanged += LayerPropertyGroupOnVisibilityChanged;
|
|
||||||
PopulateChildren();
|
PopulateChildren();
|
||||||
DetermineType();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool IsVisible => !LayerPropertyGroup.IsHidden;
|
|
||||||
public IProfileEditorService ProfileEditorService { get; }
|
|
||||||
public LayerPropertyGroup LayerPropertyGroup { get; }
|
public LayerPropertyGroup LayerPropertyGroup { get; }
|
||||||
public PropertyGroupDescriptionAttribute PropertyGroupDescription { get; }
|
public LayerPropertyGroupTreeViewModel LayerPropertyGroupTreeViewModel { get; }
|
||||||
|
public BindableCollection<PropertyChangedBase> Children { get; set; }
|
||||||
|
|
||||||
public override bool IsExpanded
|
public bool IsVisible => !LayerPropertyGroup.IsHidden;
|
||||||
|
|
||||||
|
public bool IsExpanded
|
||||||
{
|
{
|
||||||
get => LayerPropertyGroup.ProfileElement.IsPropertyGroupExpanded(LayerPropertyGroup);
|
get => LayerPropertyGroup.ProfileElement.IsPropertyGroupExpanded(LayerPropertyGroup);
|
||||||
set
|
set
|
||||||
@ -62,81 +35,10 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ViewModelType GroupType
|
|
||||||
{
|
|
||||||
get => _groupType;
|
|
||||||
set => SetAndNotify(ref _groupType, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TreePropertyGroupViewModel TreePropertyGroupViewModel
|
|
||||||
{
|
|
||||||
get => _treePropertyGroupViewModel;
|
|
||||||
set => SetAndNotify(ref _treePropertyGroupViewModel, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TimelinePropertyGroupViewModel TimelinePropertyGroupViewModel
|
|
||||||
{
|
|
||||||
get => _timelinePropertyGroupViewModel;
|
|
||||||
set => SetAndNotify(ref _timelinePropertyGroupViewModel, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override List<BaseLayerPropertyKeyframe> GetKeyframes(bool expandedOnly)
|
|
||||||
{
|
|
||||||
var result = new List<BaseLayerPropertyKeyframe>();
|
|
||||||
if (expandedOnly && !IsExpanded || LayerPropertyGroup.IsHidden)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
foreach (var layerPropertyBaseViewModel in Children)
|
|
||||||
result.AddRange(layerPropertyBaseViewModel.GetKeyframes(expandedOnly));
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Dispose()
|
|
||||||
{
|
|
||||||
foreach (var layerPropertyBaseViewModel in Children)
|
|
||||||
layerPropertyBaseViewModel.Dispose();
|
|
||||||
|
|
||||||
LayerPropertyGroup.VisibilityChanged -= LayerPropertyGroupOnVisibilityChanged;
|
|
||||||
TimelinePropertyGroupViewModel.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<LayerPropertyBaseViewModel> GetAllChildren()
|
|
||||||
{
|
|
||||||
var result = new List<LayerPropertyBaseViewModel>();
|
|
||||||
foreach (var layerPropertyBaseViewModel in Children)
|
|
||||||
{
|
|
||||||
result.Add(layerPropertyBaseViewModel);
|
|
||||||
if (layerPropertyBaseViewModel is LayerPropertyGroupViewModel layerPropertyGroupViewModel)
|
|
||||||
result.AddRange(layerPropertyGroupViewModel.GetAllChildren());
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateOrder(int order)
|
|
||||||
{
|
|
||||||
LayerPropertyGroup.LayerEffect.Order = order;
|
|
||||||
NotifyOfPropertyChange(nameof(IsExpanded));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DetermineType()
|
|
||||||
{
|
|
||||||
if (LayerPropertyGroup is LayerGeneralProperties)
|
|
||||||
GroupType = ViewModelType.General;
|
|
||||||
else if (LayerPropertyGroup is LayerTransformProperties)
|
|
||||||
GroupType = ViewModelType.Transform;
|
|
||||||
else if (LayerPropertyGroup.Parent == null && LayerPropertyGroup.LayerBrush != null)
|
|
||||||
GroupType = ViewModelType.LayerBrushRoot;
|
|
||||||
else if (LayerPropertyGroup.Parent == null && LayerPropertyGroup.LayerEffect != null)
|
|
||||||
GroupType = ViewModelType.LayerEffectRoot;
|
|
||||||
else
|
|
||||||
GroupType = ViewModelType.None;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void PopulateChildren()
|
private void PopulateChildren()
|
||||||
{
|
{
|
||||||
// Get all properties and property groups and create VMs for them
|
// Get all properties and property groups and create VMs for them
|
||||||
|
// The group has methods for getting this without reflection but then we lose the order of the properties as they are defined on the group
|
||||||
foreach (var propertyInfo in LayerPropertyGroup.GetType().GetProperties())
|
foreach (var propertyInfo in LayerPropertyGroup.GetType().GetProperties())
|
||||||
{
|
{
|
||||||
var propertyAttribute = (PropertyDescriptionAttribute) Attribute.GetCustomAttribute(propertyInfo, typeof(PropertyDescriptionAttribute));
|
var propertyAttribute = (PropertyDescriptionAttribute) Attribute.GetCustomAttribute(propertyInfo, typeof(PropertyDescriptionAttribute));
|
||||||
@ -144,50 +46,28 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
|
|||||||
var value = propertyInfo.GetValue(LayerPropertyGroup);
|
var value = propertyInfo.GetValue(LayerPropertyGroup);
|
||||||
|
|
||||||
// Create VMs for properties on the group
|
// Create VMs for properties on the group
|
||||||
if (propertyAttribute != null && value is BaseLayerProperty baseLayerProperty)
|
if (propertyAttribute != null && value is ILayerProperty layerProperty)
|
||||||
{
|
{
|
||||||
var viewModel = CreateLayerPropertyViewModel(baseLayerProperty, propertyAttribute);
|
var layerPropertyViewModel = _layerPropertyVmFactory.LayerPropertyViewModel(layerProperty);
|
||||||
if (viewModel != null)
|
// After creation ensure a supported input VM was found, if not, discard the VM
|
||||||
Children.Add(viewModel);
|
if (!layerPropertyViewModel.LayerPropertyTreeViewModel.HasPropertyInputViewModel)
|
||||||
|
layerPropertyViewModel.Dispose();
|
||||||
|
else
|
||||||
|
Children.Add(layerPropertyViewModel);
|
||||||
}
|
}
|
||||||
// Create VMs for child groups on this group, resulting in a nested structure
|
// Create VMs for child groups on this group, resulting in a nested structure
|
||||||
else if (groupAttribute != null && value is LayerPropertyGroup layerPropertyGroup)
|
else if (groupAttribute != null && value is LayerPropertyGroup layerPropertyGroup)
|
||||||
Children.Add(_layerPropertyVmFactory.LayerPropertyGroupViewModel(layerPropertyGroup, groupAttribute));
|
Children.Add(_layerPropertyVmFactory.LayerPropertyGroupViewModel(layerPropertyGroup));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private LayerPropertyBaseViewModel CreateLayerPropertyViewModel(BaseLayerProperty baseLayerProperty, PropertyDescriptionAttribute propertyDescription)
|
public void Dispose()
|
||||||
{
|
{
|
||||||
// Go through the pain of instantiating a generic type VM now via reflection to make things a lot simpler down the line
|
foreach (var child in Children)
|
||||||
var genericType = baseLayerProperty.GetType().Name == typeof(LayerProperty<>).Name
|
|
||||||
? baseLayerProperty.GetType().GetGenericArguments()[0]
|
|
||||||
: baseLayerProperty.GetType().BaseType.GetGenericArguments()[0];
|
|
||||||
|
|
||||||
// Only create entries for types supported by a tree input VM
|
|
||||||
if (!genericType.IsEnum && ProfileEditorService.RegisteredPropertyEditors.All(r => r.SupportedType != genericType))
|
|
||||||
return null;
|
|
||||||
var genericViewModel = typeof(LayerPropertyViewModel<>).MakeGenericType(genericType);
|
|
||||||
var parameters = new IParameter[]
|
|
||||||
{
|
{
|
||||||
new ConstructorArgument("layerProperty", baseLayerProperty),
|
if (child is IDisposable disposableChild)
|
||||||
new ConstructorArgument("propertyDescription", propertyDescription)
|
disposableChild.Dispose();
|
||||||
};
|
}
|
||||||
|
|
||||||
return (LayerPropertyBaseViewModel) ProfileEditorService.Kernel.Get(genericViewModel, parameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void LayerPropertyGroupOnVisibilityChanged(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
NotifyOfPropertyChange(nameof(IsVisible));
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum ViewModelType
|
|
||||||
{
|
|
||||||
General,
|
|
||||||
Transform,
|
|
||||||
LayerBrushRoot,
|
|
||||||
LayerEffectRoot,
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,141 +1,37 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.UI.Exceptions;
|
|
||||||
using Artemis.UI.PropertyInput;
|
|
||||||
using Artemis.UI.Screens.ProfileEditor.LayerProperties.Abstract;
|
|
||||||
using Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline;
|
|
||||||
using Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree;
|
using Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree;
|
||||||
using Artemis.UI.Shared;
|
|
||||||
using Artemis.UI.Shared.Services;
|
|
||||||
using Humanizer;
|
|
||||||
using Ninject;
|
using Ninject;
|
||||||
using Ninject.Parameters;
|
using Ninject.Parameters;
|
||||||
|
using Stylet;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
|
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
|
||||||
{
|
{
|
||||||
public class LayerPropertyViewModel<T> : LayerPropertyViewModel
|
public class LayerPropertyViewModel : PropertyChangedBase, IDisposable
|
||||||
{
|
{
|
||||||
private TimelinePropertyViewModel<T> _timelinePropertyViewModel;
|
public LayerPropertyViewModel(ILayerProperty layerProperty, IKernel kernel)
|
||||||
private TreePropertyViewModel<T> _treePropertyViewModel;
|
|
||||||
|
|
||||||
public LayerPropertyViewModel(IProfileEditorService profileEditorService, LayerProperty<T> layerProperty) : base(profileEditorService, layerProperty)
|
|
||||||
{
|
{
|
||||||
LayerProperty = layerProperty;
|
LayerProperty = layerProperty;
|
||||||
|
|
||||||
TreePropertyViewModel = CreateTreePropertyViewModel();
|
var parameter = new ConstructorArgument("layerProperty", LayerProperty);
|
||||||
TimelinePropertyViewModel = new TimelinePropertyViewModel<T>(this, profileEditorService);
|
var treeViewModelType = typeof(LayerPropertyTreeViewModel<>).MakeGenericType(layerProperty.GetType().GetGenericArguments());
|
||||||
|
var timelineViewModelType = typeof(LayerPropertyTimelineViewModel<>).MakeGenericType(layerProperty.GetType().GetGenericArguments());
|
||||||
|
|
||||||
TreePropertyBaseViewModel = TreePropertyViewModel;
|
LayerPropertyTreeViewModel = (ILayerPropertyTreeViewModel) kernel.Get(treeViewModelType, parameter);
|
||||||
TimelinePropertyBaseViewModel = TimelinePropertyViewModel;
|
LayerPropertyTimelineViewModel = (ILayerPropertyTimelineViewModel) kernel.Get(timelineViewModelType, parameter);
|
||||||
|
|
||||||
// Generate a fallback name if the description does not contain one
|
|
||||||
if (LayerProperty.PropertyDescription.Name == null)
|
|
||||||
{
|
|
||||||
var propertyInfo = LayerProperty.Parent?.GetType().GetProperties().FirstOrDefault(p => ReferenceEquals(p.GetValue(LayerProperty.Parent), LayerProperty));
|
|
||||||
if (propertyInfo != null)
|
|
||||||
LayerProperty.PropertyDescription.Name = propertyInfo.Name.Humanize();
|
|
||||||
else
|
|
||||||
LayerProperty.PropertyDescription.Name = $"Unknown {typeof(T).Name} property";
|
|
||||||
}
|
|
||||||
|
|
||||||
LayerProperty.VisibilityChanged += LayerPropertyOnVisibilityChanged;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool IsVisible => !LayerProperty.IsHidden;
|
public ILayerProperty LayerProperty { get; }
|
||||||
|
public ILayerPropertyTreeViewModel LayerPropertyTreeViewModel { get; }
|
||||||
|
public ILayerPropertyTimelineViewModel LayerPropertyTimelineViewModel { get; }
|
||||||
|
|
||||||
public LayerProperty<T> LayerProperty { get; }
|
public bool IsVisible { get; set; }
|
||||||
|
public bool IsExpanded { get; set; }
|
||||||
|
|
||||||
public TreePropertyViewModel<T> TreePropertyViewModel
|
public void Dispose()
|
||||||
{
|
{
|
||||||
get => _treePropertyViewModel;
|
LayerPropertyTreeViewModel?.Dispose();
|
||||||
set => SetAndNotify(ref _treePropertyViewModel, value);
|
LayerPropertyTimelineViewModel?.Dispose();
|
||||||
}
|
|
||||||
|
|
||||||
public TimelinePropertyViewModel<T> TimelinePropertyViewModel
|
|
||||||
{
|
|
||||||
get => _timelinePropertyViewModel;
|
|
||||||
set => SetAndNotify(ref _timelinePropertyViewModel, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override List<BaseLayerPropertyKeyframe> GetKeyframes(bool expandedOnly)
|
|
||||||
{
|
|
||||||
if (LayerProperty.KeyframesEnabled && !LayerProperty.IsHidden)
|
|
||||||
return LayerProperty.BaseKeyframes.ToList();
|
|
||||||
return new List<BaseLayerPropertyKeyframe>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Dispose()
|
|
||||||
{
|
|
||||||
TreePropertyViewModel.Dispose();
|
|
||||||
TimelinePropertyViewModel.Dispose();
|
|
||||||
|
|
||||||
LayerProperty.VisibilityChanged -= LayerPropertyOnVisibilityChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetCurrentValue(T value, bool saveChanges)
|
|
||||||
{
|
|
||||||
LayerProperty.SetCurrentValue(value, ProfileEditorService.CurrentTime);
|
|
||||||
if (saveChanges)
|
|
||||||
ProfileEditorService.UpdateSelectedProfileElement();
|
|
||||||
else
|
|
||||||
ProfileEditorService.UpdateProfilePreview();
|
|
||||||
}
|
|
||||||
|
|
||||||
private TreePropertyViewModel<T> CreateTreePropertyViewModel()
|
|
||||||
{
|
|
||||||
// Make sure there is a supported property editor VM, unless the type is an enum, then we'll use the EnumPropertyInputViewModel
|
|
||||||
Type vmType = null;
|
|
||||||
if (typeof(T).IsEnum)
|
|
||||||
vmType = typeof(EnumPropertyInputViewModel<>).MakeGenericType(typeof(T));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var registration = ProfileEditorService.RegisteredPropertyEditors.FirstOrDefault(r => r.SupportedType == typeof(T));
|
|
||||||
if (registration != null)
|
|
||||||
vmType = registration.ViewModelType;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vmType == null)
|
|
||||||
throw new ArtemisUIException($"Cannot create a tree property view model for type {typeof(T)}, found no matching property editor");
|
|
||||||
|
|
||||||
var parameters = new IParameter[]
|
|
||||||
{
|
|
||||||
new ConstructorArgument("layerProperty", LayerProperty)
|
|
||||||
};
|
|
||||||
return new TreePropertyViewModel<T>(this, (PropertyInputViewModel<T>) ProfileEditorService.Kernel.Get(vmType, parameters), ProfileEditorService);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void LayerPropertyOnVisibilityChanged(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
NotifyOfPropertyChange(nameof(IsVisible));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract class LayerPropertyViewModel : LayerPropertyBaseViewModel
|
|
||||||
{
|
|
||||||
private TimelinePropertyViewModel _timelinePropertyBaseViewModel;
|
|
||||||
private TreePropertyViewModel _treePropertyBaseViewModel;
|
|
||||||
|
|
||||||
protected LayerPropertyViewModel(IProfileEditorService profileEditorService, BaseLayerProperty baseLayerProperty)
|
|
||||||
{
|
|
||||||
ProfileEditorService = profileEditorService;
|
|
||||||
BaseLayerProperty = baseLayerProperty;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IProfileEditorService ProfileEditorService { get; }
|
|
||||||
public BaseLayerProperty BaseLayerProperty { get; }
|
|
||||||
|
|
||||||
public TreePropertyViewModel TreePropertyBaseViewModel
|
|
||||||
{
|
|
||||||
get => _treePropertyBaseViewModel;
|
|
||||||
set => SetAndNotify(ref _treePropertyBaseViewModel, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TimelinePropertyViewModel TimelinePropertyBaseViewModel
|
|
||||||
{
|
|
||||||
get => _timelinePropertyBaseViewModel;
|
|
||||||
set => SetAndNotify(ref _timelinePropertyBaseViewModel, value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
using System;
|
||||||
|
using Artemis.Core;
|
||||||
|
using Stylet;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
|
||||||
|
{
|
||||||
|
public class LayerPropertyTimelineViewModel<T> : Screen, ILayerPropertyTimelineViewModel
|
||||||
|
{
|
||||||
|
public LayerProperty<T> LayerProperty { get; }
|
||||||
|
public LayerPropertyViewModel LayerPropertyViewModel { get; }
|
||||||
|
|
||||||
|
public LayerPropertyTimelineViewModel(LayerProperty<T> layerProperty, LayerPropertyViewModel layerPropertyViewModel)
|
||||||
|
{
|
||||||
|
LayerProperty = layerProperty;
|
||||||
|
LayerPropertyViewModel = layerPropertyViewModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ILayerPropertyTimelineViewModel : IScreen, IDisposable
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using Artemis.Core;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline.Rails
|
||||||
|
{
|
||||||
|
public class TimelineGroupViewModel
|
||||||
|
{
|
||||||
|
public LayerPropertyGroup LayerPropertyGroup { get; }
|
||||||
|
|
||||||
|
public TimelineGroupViewModel(LayerPropertyGroup layerPropertyGroup)
|
||||||
|
{
|
||||||
|
LayerPropertyGroup = layerPropertyGroup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -9,7 +9,7 @@
|
|||||||
xmlns:converters="clr-namespace:Artemis.UI.Converters"
|
xmlns:converters="clr-namespace:Artemis.UI.Converters"
|
||||||
xmlns:dd="urn:gong-wpf-dragdrop"
|
xmlns:dd="urn:gong-wpf-dragdrop"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DataContext="{d:DesignInstance local:TreePropertyGroupViewModel}"
|
d:DataContext="{d:DesignInstance local:LayerPropertyGroupTreeViewModel}"
|
||||||
d:DesignHeight="450" d:DesignWidth="800">
|
d:DesignHeight="450" d:DesignWidth="800">
|
||||||
<UserControl.Resources>
|
<UserControl.Resources>
|
||||||
<converters:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
|
<converters:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
|
||||||
@ -18,8 +18,8 @@
|
|||||||
<!-- Type: None -->
|
<!-- Type: None -->
|
||||||
<TextBlock
|
<TextBlock
|
||||||
dd:DragDrop.DragSourceIgnore="True"
|
dd:DragDrop.DragSourceIgnore="True"
|
||||||
Text="{Binding LayerPropertyGroupViewModel.PropertyGroupDescription.Name}"
|
Text="{Binding LayerPropertyGroup.GroupDescription.Name}"
|
||||||
ToolTip="{Binding LayerPropertyGroupViewModel.PropertyGroupDescription.Description}"
|
ToolTip="{Binding LayerPropertyGroup.GroupDescription.Description}"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
Margin="3 5 0 5">
|
Margin="3 5 0 5">
|
||||||
@ -27,7 +27,7 @@
|
|||||||
<Style TargetType="{x:Type TextBlock}">
|
<Style TargetType="{x:Type TextBlock}">
|
||||||
<Setter Property="Visibility" Value="Collapsed" />
|
<Setter Property="Visibility" Value="Collapsed" />
|
||||||
<Style.Triggers>
|
<Style.Triggers>
|
||||||
<DataTrigger Binding="{Binding LayerPropertyGroupViewModel.GroupType}" Value="None">
|
<DataTrigger Binding="{Binding GroupType}" Value="None">
|
||||||
<Setter Property="Visibility" Value="Visible" />
|
<Setter Property="Visibility" Value="Visible" />
|
||||||
</DataTrigger>
|
</DataTrigger>
|
||||||
</Style.Triggers>
|
</Style.Triggers>
|
||||||
@ -41,14 +41,14 @@
|
|||||||
<Style TargetType="{x:Type StackPanel}">
|
<Style TargetType="{x:Type StackPanel}">
|
||||||
<Setter Property="Visibility" Value="Collapsed" />
|
<Setter Property="Visibility" Value="Collapsed" />
|
||||||
<Style.Triggers>
|
<Style.Triggers>
|
||||||
<DataTrigger Binding="{Binding LayerPropertyGroupViewModel.GroupType}" Value="General">
|
<DataTrigger Binding="{Binding GroupType}" Value="General">
|
||||||
<Setter Property="Visibility" Value="Visible" />
|
<Setter Property="Visibility" Value="Visible" />
|
||||||
</DataTrigger>
|
</DataTrigger>
|
||||||
</Style.Triggers>
|
</Style.Triggers>
|
||||||
</Style>
|
</Style>
|
||||||
</StackPanel.Style>
|
</StackPanel.Style>
|
||||||
<materialDesign:PackIcon Kind="HammerWrench" Margin="0 -1 5 0" />
|
<materialDesign:PackIcon Kind="HammerWrench" Margin="0 -1 5 0" />
|
||||||
<TextBlock ToolTip="{Binding LayerPropertyGroupViewModel.PropertyGroupDescription.Description}">General</TextBlock>
|
<TextBlock ToolTip="{Binding LayerPropertyGroup.GroupDescription.Description}">General</TextBlock>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<!-- Type: Transform -->
|
<!-- Type: Transform -->
|
||||||
@ -57,14 +57,14 @@
|
|||||||
<Style TargetType="{x:Type StackPanel}">
|
<Style TargetType="{x:Type StackPanel}">
|
||||||
<Setter Property="Visibility" Value="Collapsed" />
|
<Setter Property="Visibility" Value="Collapsed" />
|
||||||
<Style.Triggers>
|
<Style.Triggers>
|
||||||
<DataTrigger Binding="{Binding LayerPropertyGroupViewModel.GroupType}" Value="Transform">
|
<DataTrigger Binding="{Binding GroupType}" Value="Transform">
|
||||||
<Setter Property="Visibility" Value="Visible" />
|
<Setter Property="Visibility" Value="Visible" />
|
||||||
</DataTrigger>
|
</DataTrigger>
|
||||||
</Style.Triggers>
|
</Style.Triggers>
|
||||||
</Style>
|
</Style>
|
||||||
</StackPanel.Style>
|
</StackPanel.Style>
|
||||||
<materialDesign:PackIcon Kind="TransitConnectionVariant" Margin="0 -1 5 0" />
|
<materialDesign:PackIcon Kind="TransitConnectionVariant" Margin="0 -1 5 0" />
|
||||||
<TextBlock ToolTip="{Binding LayerPropertyGroupViewModel.PropertyGroupDescription.Description}">Transform</TextBlock>
|
<TextBlock ToolTip="{Binding LayerPropertyGroup.GroupDescription.Description}">Transform</TextBlock>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<!-- Type: LayerBrushRoot -->
|
<!-- Type: LayerBrushRoot -->
|
||||||
@ -79,23 +79,23 @@
|
|||||||
<Style TargetType="{x:Type Grid}">
|
<Style TargetType="{x:Type Grid}">
|
||||||
<Setter Property="Visibility" Value="Collapsed" />
|
<Setter Property="Visibility" Value="Collapsed" />
|
||||||
<Style.Triggers>
|
<Style.Triggers>
|
||||||
<DataTrigger Binding="{Binding LayerPropertyGroupViewModel.GroupType}" Value="LayerBrushRoot">
|
<DataTrigger Binding="{Binding GroupType}" Value="LayerBrushRoot">
|
||||||
<Setter Property="Visibility" Value="Visible" />
|
<Setter Property="Visibility" Value="Visible" />
|
||||||
</DataTrigger>
|
</DataTrigger>
|
||||||
</Style.Triggers>
|
</Style.Triggers>
|
||||||
</Style>
|
</Style>
|
||||||
</Grid.Style>
|
</Grid.Style>
|
||||||
<materialDesign:PackIcon Grid.Column="0"
|
<materialDesign:PackIcon Grid.Column="0"
|
||||||
Kind="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerBrush.Descriptor.Icon}"
|
Kind="{Binding LayerPropertyGroup.LayerBrush.Descriptor.Icon}"
|
||||||
Margin="0 5 5 0" />
|
Margin="0 5 5 0" />
|
||||||
<TextBlock Grid.Column="1"
|
<TextBlock Grid.Column="1"
|
||||||
ToolTip="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerBrush.Descriptor.Description}"
|
ToolTip="{Binding LayerPropertyGroup.LayerBrush.Descriptor.Description}"
|
||||||
Margin="0 5 0 0">
|
Margin="0 5 0 0">
|
||||||
Brush - 
|
Brush - 
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
<TextBlock Grid.Column="2"
|
<TextBlock Grid.Column="2"
|
||||||
Text="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerBrush.Descriptor.DisplayName}"
|
Text="{Binding LayerPropertyGroup.LayerBrush.Descriptor.DisplayName}"
|
||||||
ToolTip="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerBrush.Descriptor.Description}"
|
ToolTip="{Binding LayerPropertyGroup.LayerBrush.Descriptor.Description}"
|
||||||
Margin="0 5 0 0" />
|
Margin="0 5 0 0" />
|
||||||
|
|
||||||
<Button Grid.Column="3"
|
<Button Grid.Column="3"
|
||||||
@ -106,7 +106,7 @@
|
|||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
HorizontalAlignment="Right"
|
HorizontalAlignment="Right"
|
||||||
Command="{s:Action OpenBrushSettings}"
|
Command="{s:Action OpenBrushSettings}"
|
||||||
Visibility="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerBrush.ConfigurationDialog, Converter={StaticResource NullToVisibilityConverter}}">
|
Visibility="{Binding LayerPropertyGroup.LayerBrush.ConfigurationDialog, Converter={StaticResource NullToVisibilityConverter}}">
|
||||||
<materialDesign:PackIcon Kind="Settings" Height="16" Width="16" />
|
<materialDesign:PackIcon Kind="Settings" Height="16" Width="16" />
|
||||||
</Button>
|
</Button>
|
||||||
</Grid>
|
</Grid>
|
||||||
@ -125,7 +125,7 @@
|
|||||||
<Style TargetType="{x:Type Grid}">
|
<Style TargetType="{x:Type Grid}">
|
||||||
<Setter Property="Visibility" Value="Collapsed" />
|
<Setter Property="Visibility" Value="Collapsed" />
|
||||||
<Style.Triggers>
|
<Style.Triggers>
|
||||||
<DataTrigger Binding="{Binding LayerPropertyGroupViewModel.GroupType}" Value="LayerEffectRoot">
|
<DataTrigger Binding="{Binding GroupType}" Value="LayerEffectRoot">
|
||||||
<Setter Property="Visibility" Value="Visible" />
|
<Setter Property="Visibility" Value="Visible" />
|
||||||
</DataTrigger>
|
</DataTrigger>
|
||||||
</Style.Triggers>
|
</Style.Triggers>
|
||||||
@ -134,29 +134,29 @@
|
|||||||
<materialDesign:PackIcon
|
<materialDesign:PackIcon
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
Cursor="SizeNS"
|
Cursor="SizeNS"
|
||||||
Kind="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Descriptor.Icon}"
|
Kind="{Binding LayerPropertyGroup.LayerEffect.Descriptor.Icon}"
|
||||||
Margin="0 5 5 0"
|
Margin="0 5 5 0"
|
||||||
Background="Transparent" />
|
Background="Transparent" />
|
||||||
<TextBlock Grid.Column="1" ToolTip="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Descriptor.Description}" Margin="0 5 0 0">
|
<TextBlock Grid.Column="1" ToolTip="{Binding LayerPropertyGroup.LayerEffect.Descriptor.Description}" Margin="0 5 0 0">
|
||||||
Effect
|
Effect
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
<TextBlock Grid.Column="2"
|
<TextBlock Grid.Column="2"
|
||||||
ToolTip="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Descriptor.Description}"
|
ToolTip="{Binding LayerPropertyGroup.LayerEffect.Descriptor.Description}"
|
||||||
Margin="3 5">
|
Margin="3 5">
|
||||||
-
|
-
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
|
|
||||||
<!-- Show either the descriptors display name or, if set, the effect name -->
|
<!-- Show either the descriptors display name or, if set, the effect name -->
|
||||||
<TextBlock Grid.Column="3"
|
<TextBlock Grid.Column="3"
|
||||||
Text="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Descriptor.DisplayName}"
|
Text="{Binding LayerPropertyGroup.LayerEffect.Descriptor.DisplayName}"
|
||||||
ToolTip="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Descriptor.Description}"
|
ToolTip="{Binding LayerPropertyGroup.LayerEffect.Descriptor.Description}"
|
||||||
Margin="0 5"
|
Margin="0 5"
|
||||||
Visibility="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Name, Converter={StaticResource NullToVisibilityConverter}, ConverterParameter=Inverted}" />
|
Visibility="{Binding LayerPropertyGroup.LayerEffect.Name, Converter={StaticResource NullToVisibilityConverter}, ConverterParameter=Inverted}" />
|
||||||
<TextBlock Grid.Column="4"
|
<TextBlock Grid.Column="4"
|
||||||
Text="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Name}"
|
Text="{Binding LayerPropertyGroup.LayerEffect.Name}"
|
||||||
ToolTip="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Descriptor.Description}"
|
ToolTip="{Binding LayerPropertyGroup.LayerEffect.Descriptor.Description}"
|
||||||
Margin="0 5"
|
Margin="0 5"
|
||||||
Visibility="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Name, Converter={StaticResource NullToVisibilityConverter}}" />
|
Visibility="{Binding LayerPropertyGroup.LayerEffect.Name, Converter={StaticResource NullToVisibilityConverter}}" />
|
||||||
|
|
||||||
<StackPanel Grid.Column="5" Orientation="Horizontal">
|
<StackPanel Grid.Column="5" Orientation="Horizontal">
|
||||||
<ToggleButton
|
<ToggleButton
|
||||||
@ -164,7 +164,7 @@
|
|||||||
ToolTip="Toggle enabled state"
|
ToolTip="Toggle enabled state"
|
||||||
Width="18"
|
Width="18"
|
||||||
Height="18"
|
Height="18"
|
||||||
IsChecked="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Enabled}"
|
IsChecked="{Binding LayerPropertyGroup.LayerEffect.Enabled}"
|
||||||
VerticalAlignment="Center" Padding="-25"
|
VerticalAlignment="Center" Padding="-25"
|
||||||
Margin="5 0"
|
Margin="5 0"
|
||||||
Command="{s:Action EnableToggled}">
|
Command="{s:Action EnableToggled}">
|
||||||
@ -184,7 +184,7 @@
|
|||||||
Height="24"
|
Height="24"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Command="{s:Action OpenEffectSettings}"
|
Command="{s:Action OpenEffectSettings}"
|
||||||
Visibility="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.ConfigurationDialog, Converter={StaticResource NullToVisibilityConverter}}">
|
Visibility="{Binding LayerPropertyGroup.LayerEffect.ConfigurationDialog, Converter={StaticResource NullToVisibilityConverter}}">
|
||||||
<materialDesign:PackIcon Kind="Settings" Height="16" Width="16" />
|
<materialDesign:PackIcon Kind="Settings" Height="16" Width="16" />
|
||||||
</Button>
|
</Button>
|
||||||
<Button Style="{StaticResource MaterialDesignIconButton}"
|
<Button Style="{StaticResource MaterialDesignIconButton}"
|
||||||
@ -1,13 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using Artemis.Core;
|
||||||
using Artemis.Core.LayerBrushes;
|
using Artemis.Core.LayerBrushes;
|
||||||
using Artemis.Core.LayerEffects;
|
using Artemis.Core.LayerEffects;
|
||||||
using Artemis.Core.Services;
|
|
||||||
using Artemis.UI.Exceptions;
|
using Artemis.UI.Exceptions;
|
||||||
using Artemis.UI.Screens.ProfileEditor.Dialogs;
|
using Artemis.UI.Screens.ProfileEditor.Dialogs;
|
||||||
using Artemis.UI.Screens.ProfileEditor.LayerProperties.Abstract;
|
using Artemis.UI.Screens.ProfileEditor.Windows;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
using Ninject;
|
using Ninject;
|
||||||
using Ninject.Parameters;
|
using Ninject.Parameters;
|
||||||
@ -15,34 +14,36 @@ using Stylet;
|
|||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree
|
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree
|
||||||
{
|
{
|
||||||
public class TreePropertyGroupViewModel : PropertyChangedBase
|
public class LayerPropertyGroupTreeViewModel : PropertyChangedBase
|
||||||
{
|
{
|
||||||
private readonly IDialogService _dialogService;
|
private readonly IDialogService _dialogService;
|
||||||
private readonly IKernel _kernel;
|
private readonly IKernel _kernel;
|
||||||
private readonly IProfileEditorService _profileEditorService;
|
private readonly IProfileEditorService _profileEditorService;
|
||||||
private readonly IRenderElementService _renderElementService;
|
|
||||||
private readonly IWindowManager _windowManager;
|
private readonly IWindowManager _windowManager;
|
||||||
|
|
||||||
public TreePropertyGroupViewModel(LayerPropertyBaseViewModel layerPropertyBaseViewModel,
|
public LayerPropertyGroupTreeViewModel(
|
||||||
|
LayerPropertyGroupViewModel layerPropertyGroupViewModel,
|
||||||
IProfileEditorService profileEditorService,
|
IProfileEditorService profileEditorService,
|
||||||
IRenderElementService renderElementService,
|
|
||||||
IDialogService dialogService,
|
IDialogService dialogService,
|
||||||
IWindowManager windowManager,
|
IWindowManager windowManager,
|
||||||
IKernel kernel)
|
IKernel kernel)
|
||||||
{
|
{
|
||||||
_profileEditorService = profileEditorService;
|
_profileEditorService = profileEditorService;
|
||||||
_renderElementService = renderElementService;
|
|
||||||
_dialogService = dialogService;
|
_dialogService = dialogService;
|
||||||
_windowManager = windowManager;
|
_windowManager = windowManager;
|
||||||
_kernel = kernel;
|
_kernel = kernel;
|
||||||
LayerPropertyGroupViewModel = (LayerPropertyGroupViewModel) layerPropertyBaseViewModel;
|
|
||||||
|
LayerPropertyGroupViewModel = layerPropertyGroupViewModel;
|
||||||
|
LayerPropertyGroup = LayerPropertyGroupViewModel.LayerPropertyGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LayerPropertyGroupViewModel LayerPropertyGroupViewModel { get; }
|
public LayerPropertyGroupViewModel LayerPropertyGroupViewModel { get; }
|
||||||
|
public LayerPropertyGroup LayerPropertyGroup { get; }
|
||||||
|
public LayerPropertyGroupType GroupType { get; set; }
|
||||||
|
|
||||||
public void OpenBrushSettings()
|
public void OpenBrushSettings()
|
||||||
{
|
{
|
||||||
var layerBrush = LayerPropertyGroupViewModel.LayerPropertyGroup.LayerBrush;
|
var layerBrush = LayerPropertyGroup.LayerBrush;
|
||||||
var configurationViewModel = layerBrush.ConfigurationDialog;
|
var configurationViewModel = layerBrush.ConfigurationDialog;
|
||||||
if (configurationViewModel == null)
|
if (configurationViewModel == null)
|
||||||
return;
|
return;
|
||||||
@ -69,7 +70,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree
|
|||||||
|
|
||||||
public void OpenEffectSettings()
|
public void OpenEffectSettings()
|
||||||
{
|
{
|
||||||
var layerEffect = LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect;
|
var layerEffect = LayerPropertyGroup.LayerEffect;
|
||||||
var configurationViewModel = layerEffect.ConfigurationDialog;
|
var configurationViewModel = layerEffect.ConfigurationDialog;
|
||||||
if (configurationViewModel == null)
|
if (configurationViewModel == null)
|
||||||
return;
|
return;
|
||||||
@ -100,20 +101,23 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree
|
|||||||
new Dictionary<string, object>
|
new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{"subject", "effect"},
|
{"subject", "effect"},
|
||||||
{"currentName", LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Name}
|
{"currentName", LayerPropertyGroup.LayerEffect.Name}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
if (result is string newName)
|
if (result is string newName)
|
||||||
{
|
{
|
||||||
LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Name = newName;
|
LayerPropertyGroup.LayerEffect.Name = newName;
|
||||||
LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.HasBeenRenamed = true;
|
LayerPropertyGroup.LayerEffect.HasBeenRenamed = true;
|
||||||
_profileEditorService.UpdateSelectedProfile();
|
_profileEditorService.UpdateSelectedProfile();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DeleteEffect()
|
public void DeleteEffect()
|
||||||
{
|
{
|
||||||
_renderElementService.RemoveLayerEffect(LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect);
|
if (LayerPropertyGroup.LayerEffect == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
LayerPropertyGroup.ProfileElement.RemoveLayerEffect(LayerPropertyGroup.LayerEffect);
|
||||||
_profileEditorService.UpdateSelectedProfile();
|
_profileEditorService.UpdateSelectedProfile();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,5 +125,28 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree
|
|||||||
{
|
{
|
||||||
_profileEditorService.UpdateSelectedProfile();
|
_profileEditorService.UpdateSelectedProfile();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void DetermineGroupType()
|
||||||
|
{
|
||||||
|
if (LayerPropertyGroup is LayerGeneralProperties)
|
||||||
|
GroupType = LayerPropertyGroupType.General;
|
||||||
|
else if (LayerPropertyGroup is LayerTransformProperties)
|
||||||
|
GroupType = LayerPropertyGroupType.Transform;
|
||||||
|
else if (LayerPropertyGroup.Parent == null && LayerPropertyGroup.LayerBrush != null)
|
||||||
|
GroupType = LayerPropertyGroupType.LayerBrushRoot;
|
||||||
|
else if (LayerPropertyGroup.Parent == null && LayerPropertyGroup.LayerEffect != null)
|
||||||
|
GroupType = LayerPropertyGroupType.LayerEffectRoot;
|
||||||
|
else
|
||||||
|
GroupType = LayerPropertyGroupType.None;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum LayerPropertyGroupType
|
||||||
|
{
|
||||||
|
General,
|
||||||
|
Transform,
|
||||||
|
LayerBrushRoot,
|
||||||
|
LayerEffectRoot,
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,14 +1,12 @@
|
|||||||
<UserControl x:Class="Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree.TreePropertyView"
|
<UserControl x:Class="Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree.LayerPropertyTreeView"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
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:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||||
xmlns:s="https://github.com/canton7/Stylet"
|
xmlns:s="https://github.com/canton7/Stylet"
|
||||||
xmlns:tree="clr-namespace:Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree"
|
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DesignHeight="450" d:DesignWidth="800"
|
d:DesignHeight="450" d:DesignWidth="800">
|
||||||
d:DataContext="{d:DesignInstance {x:Type tree:TreePropertyViewModel}}">
|
|
||||||
<Grid Height="22" Margin="-20 0 0 0">
|
<Grid Height="22" Margin="-20 0 0 0">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
@ -22,7 +20,7 @@
|
|||||||
Width="18"
|
Width="18"
|
||||||
Height="18"
|
Height="18"
|
||||||
IsChecked="{Binding KeyframesEnabled}"
|
IsChecked="{Binding KeyframesEnabled}"
|
||||||
IsEnabled="{Binding LayerPropertyViewModel.LayerProperty.KeyframesSupported}"
|
IsEnabled="{Binding LayerProperty.KeyframesSupported}"
|
||||||
VerticalAlignment="Center" Padding="-25">
|
VerticalAlignment="Center" Padding="-25">
|
||||||
<materialDesign:PackIcon Kind="Stopwatch" Height="13" Width="13" />
|
<materialDesign:PackIcon Kind="Stopwatch" Height="13" Width="13" />
|
||||||
</ToggleButton>
|
</ToggleButton>
|
||||||
@ -32,8 +30,8 @@
|
|||||||
Padding="0,0,5,0"
|
Padding="0,0,5,0"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
TextTrimming="CharacterEllipsis"
|
TextTrimming="CharacterEllipsis"
|
||||||
Text="{Binding LayerPropertyViewModel.LayerProperty.PropertyDescription.Name}"
|
Text="{Binding LayerProperty.PropertyDescription.Name}"
|
||||||
ToolTip="{Binding LayerPropertyViewModel.LayerProperty.PropertyDescription.Description}"
|
ToolTip="{Binding LayerProperty.PropertyDescription.Description}"
|
||||||
HorizontalAlignment="Left" />
|
HorizontalAlignment="Left" />
|
||||||
|
|
||||||
<ContentControl Grid.Column="2" Margin="20 0" s:View.Model="{Binding PropertyInputViewModel}">
|
<ContentControl Grid.Column="2" Margin="20 0" s:View.Model="{Binding PropertyInputViewModel}">
|
||||||
@ -51,7 +49,7 @@
|
|||||||
Width="20"
|
Width="20"
|
||||||
Height="20"
|
Height="20"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
IsEnabled="{Binding LayerPropertyViewModel.LayerProperty.DataBindingsSupported}"
|
IsEnabled="{Binding LayerProperty.DataBindingsSupported}"
|
||||||
IsChecked="{Binding DataBindingsOpen}">
|
IsChecked="{Binding DataBindingsOpen}">
|
||||||
<materialDesign:PackIcon Kind="VectorLink" Height="13" Width="13" />
|
<materialDesign:PackIcon Kind="VectorLink" Height="13" Width="13" />
|
||||||
</ToggleButton>
|
</ToggleButton>
|
||||||
@ -0,0 +1,93 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using Artemis.Core;
|
||||||
|
using Artemis.UI.Shared;
|
||||||
|
using Artemis.UI.Shared.Services;
|
||||||
|
using Stylet;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree
|
||||||
|
{
|
||||||
|
public class LayerPropertyTreeViewModel<T> : Screen, ILayerPropertyTreeViewModel
|
||||||
|
{
|
||||||
|
private readonly IProfileEditorService _profileEditorService;
|
||||||
|
private PropertyInputViewModel<T> _propertyInputViewModel;
|
||||||
|
|
||||||
|
public LayerPropertyTreeViewModel(LayerProperty<T> layerProperty, LayerPropertyViewModel layerPropertyViewModel, IProfileEditorService profileEditorService)
|
||||||
|
{
|
||||||
|
_profileEditorService = profileEditorService;
|
||||||
|
LayerProperty = layerProperty;
|
||||||
|
LayerPropertyViewModel = layerPropertyViewModel;
|
||||||
|
|
||||||
|
PropertyInputViewModel = _profileEditorService.CreatePropertyInputViewModel(LayerProperty);
|
||||||
|
_profileEditorService.SelectedDataBindingChanged += ProfileEditorServiceOnSelectedDataBindingChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LayerProperty<T> LayerProperty { get; }
|
||||||
|
public LayerPropertyViewModel LayerPropertyViewModel { get; }
|
||||||
|
|
||||||
|
public PropertyInputViewModel<T> PropertyInputViewModel
|
||||||
|
{
|
||||||
|
get => _propertyInputViewModel;
|
||||||
|
set => SetAndNotify(ref _propertyInputViewModel, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasPropertyInputViewModel => PropertyInputViewModel != null;
|
||||||
|
|
||||||
|
public bool KeyframesEnabled
|
||||||
|
{
|
||||||
|
get => LayerProperty.KeyframesEnabled;
|
||||||
|
set => ApplyKeyframesEnabled(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DataBindingsOpen
|
||||||
|
{
|
||||||
|
get => _profileEditorService.SelectedDataBinding == LayerProperty;
|
||||||
|
set => _profileEditorService.ChangeSelectedDataBinding(value ? LayerProperty : null);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region IDisposable
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_propertyInputViewModel?.Dispose();
|
||||||
|
_profileEditorService.SelectedDataBindingChanged -= ProfileEditorServiceOnSelectedDataBindingChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private void ApplyKeyframesEnabled(bool enable)
|
||||||
|
{
|
||||||
|
// If enabling keyframes for the first time, add a keyframe with the current value at the current position
|
||||||
|
if (enable && !LayerProperty.Keyframes.Any())
|
||||||
|
{
|
||||||
|
LayerProperty.AddKeyframe(new LayerPropertyKeyframe<T>(
|
||||||
|
LayerProperty.CurrentValue,
|
||||||
|
_profileEditorService.CurrentTime,
|
||||||
|
Easings.Functions.Linear,
|
||||||
|
LayerProperty
|
||||||
|
));
|
||||||
|
}
|
||||||
|
// If disabling keyframes, set the base value to the current value
|
||||||
|
else if (!enable && LayerProperty.Keyframes.Any())
|
||||||
|
LayerProperty.BaseValue = LayerProperty.CurrentValue;
|
||||||
|
|
||||||
|
LayerProperty.KeyframesEnabled = enable;
|
||||||
|
|
||||||
|
_profileEditorService.UpdateSelectedProfileElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Event handlers
|
||||||
|
|
||||||
|
private void ProfileEditorServiceOnSelectedDataBindingChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
NotifyOfPropertyChange(nameof(DataBindingsOpen));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ILayerPropertyTreeViewModel : IScreen, IDisposable
|
||||||
|
{
|
||||||
|
bool HasPropertyInputViewModel { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,89 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using Artemis.Core;
|
|
||||||
using Artemis.UI.Screens.ProfileEditor.LayerProperties.Abstract;
|
|
||||||
using Artemis.UI.Shared;
|
|
||||||
using Artemis.UI.Shared.Services;
|
|
||||||
using Stylet;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree
|
|
||||||
{
|
|
||||||
public class TreePropertyViewModel<T> : TreePropertyViewModel
|
|
||||||
{
|
|
||||||
private readonly IProfileEditorService _profileEditorService;
|
|
||||||
private PropertyInputViewModel<T> _propertyInputViewModel;
|
|
||||||
|
|
||||||
public TreePropertyViewModel(LayerPropertyBaseViewModel layerPropertyBaseViewModel, PropertyInputViewModel<T> propertyInputViewModel,
|
|
||||||
IProfileEditorService profileEditorService) : base(layerPropertyBaseViewModel)
|
|
||||||
{
|
|
||||||
_profileEditorService = profileEditorService;
|
|
||||||
LayerPropertyViewModel = (LayerPropertyViewModel<T>) layerPropertyBaseViewModel;
|
|
||||||
PropertyInputViewModel = propertyInputViewModel;
|
|
||||||
|
|
||||||
_profileEditorService.SelectedDataBindingChanged += ProfileEditorServiceOnSelectedDataBindingChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayerPropertyViewModel<T> LayerPropertyViewModel { get; }
|
|
||||||
|
|
||||||
public PropertyInputViewModel<T> PropertyInputViewModel
|
|
||||||
{
|
|
||||||
get => _propertyInputViewModel;
|
|
||||||
set => SetAndNotify(ref _propertyInputViewModel, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool KeyframesEnabled
|
|
||||||
{
|
|
||||||
get => LayerPropertyViewModel.LayerProperty.KeyframesEnabled;
|
|
||||||
set => ApplyKeyframesEnabled(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool DataBindingsOpen
|
|
||||||
{
|
|
||||||
get => _profileEditorService.SelectedDataBinding == LayerPropertyViewModel.BaseLayerProperty;
|
|
||||||
set => _profileEditorService.ChangeSelectedDataBinding(value ? LayerPropertyViewModel.BaseLayerProperty : null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Dispose()
|
|
||||||
{
|
|
||||||
PropertyInputViewModel.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ProfileEditorServiceOnSelectedDataBindingChanged(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
NotifyOfPropertyChange(nameof(DataBindingsOpen));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ApplyKeyframesEnabled(bool enable)
|
|
||||||
{
|
|
||||||
// If enabling keyframes for the first time, add a keyframe with the current value at the current position
|
|
||||||
if (enable && !LayerPropertyViewModel.LayerProperty.Keyframes.Any())
|
|
||||||
{
|
|
||||||
LayerPropertyViewModel.LayerProperty.AddKeyframe(new LayerPropertyKeyframe<T>(
|
|
||||||
LayerPropertyViewModel.LayerProperty.CurrentValue,
|
|
||||||
_profileEditorService.CurrentTime,
|
|
||||||
Easings.Functions.Linear,
|
|
||||||
LayerPropertyViewModel.LayerProperty
|
|
||||||
));
|
|
||||||
}
|
|
||||||
// If disabling keyframes, set the base value to the current value
|
|
||||||
else if (!enable && LayerPropertyViewModel.LayerProperty.Keyframes.Any())
|
|
||||||
LayerPropertyViewModel.LayerProperty.BaseValue = LayerPropertyViewModel.LayerProperty.CurrentValue;
|
|
||||||
|
|
||||||
LayerPropertyViewModel.LayerProperty.KeyframesEnabled = enable;
|
|
||||||
|
|
||||||
_profileEditorService.UpdateSelectedProfileElement();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract class TreePropertyViewModel : PropertyChangedBase, IDisposable
|
|
||||||
{
|
|
||||||
protected TreePropertyViewModel(LayerPropertyBaseViewModel layerPropertyBaseViewModel)
|
|
||||||
{
|
|
||||||
LayerPropertyBaseViewModel = layerPropertyBaseViewModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayerPropertyBaseViewModel LayerPropertyBaseViewModel { get; }
|
|
||||||
|
|
||||||
public abstract void Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -7,7 +7,7 @@
|
|||||||
xmlns:converters="clr-namespace:Artemis.UI.Converters"
|
xmlns:converters="clr-namespace:Artemis.UI.Converters"
|
||||||
xmlns:dd="urn:gong-wpf-dragdrop"
|
xmlns:dd="urn:gong-wpf-dragdrop"
|
||||||
xmlns:tree="clr-namespace:Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree"
|
xmlns:tree="clr-namespace:Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree"
|
||||||
xmlns:layerProperties1="clr-namespace:Artemis.UI.Screens.ProfileEditor.LayerProperties"
|
xmlns:local="clr-namespace:Artemis.UI.Screens.ProfileEditor.LayerProperties"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DesignHeight="450" d:DesignWidth="800"
|
d:DesignHeight="450" d:DesignWidth="800"
|
||||||
d:DataContext="{d:DesignInstance {x:Type tree:TreeViewModel}}">
|
d:DataContext="{d:DesignInstance {x:Type tree:TreeViewModel}}">
|
||||||
@ -98,11 +98,11 @@
|
|||||||
</Style>
|
</Style>
|
||||||
</TreeView.ItemContainerStyle>
|
</TreeView.ItemContainerStyle>
|
||||||
<TreeView.Resources>
|
<TreeView.Resources>
|
||||||
<HierarchicalDataTemplate DataType="{x:Type layerProperties1:LayerPropertyGroupViewModel}" ItemsSource="{Binding Children}">
|
<HierarchicalDataTemplate DataType="{x:Type local:LayerPropertyGroupViewModel}" ItemsSource="{Binding Items}">
|
||||||
<ContentControl s:View.Model="{Binding TreePropertyGroupViewModel}" />
|
<ContentControl s:View.Model="{Binding LayerPropertyGroupTreeViewModel}" />
|
||||||
</HierarchicalDataTemplate>
|
</HierarchicalDataTemplate>
|
||||||
<DataTemplate DataType="{x:Type layerProperties1:LayerPropertyViewModel}">
|
<DataTemplate DataType="{x:Type local:LayerPropertyViewModel}">
|
||||||
<ContentControl s:View.Model="{Binding TreePropertyBaseViewModel}" dd:DragDrop.DragSourceIgnore="True" />
|
<ContentControl s:View.Model="{Binding LayerPropertyTreeViewModel}" dd:DragDrop.DragSourceIgnore="True" />
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</TreeView.Resources>
|
</TreeView.Resources>
|
||||||
</TreeView>
|
</TreeView>
|
||||||
|
|||||||
@ -5,11 +5,13 @@ using Stylet;
|
|||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree
|
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree
|
||||||
{
|
{
|
||||||
public class TreeViewModel : PropertyChangedBase
|
public class TreeViewModel : Screen
|
||||||
{
|
{
|
||||||
public TreeViewModel(LayerPropertiesViewModel layerPropertiesViewModel, BindableCollection<LayerPropertyGroupViewModel> layerPropertyGroups)
|
public TreeViewModel(LayerPropertiesViewModel layerPropertiesViewModel, BindableCollection<LayerPropertyGroupViewModel> layerPropertyGroups)
|
||||||
{
|
{
|
||||||
LayerPropertiesViewModel = layerPropertiesViewModel;
|
LayerPropertiesViewModel = layerPropertiesViewModel;
|
||||||
|
|
||||||
|
// Not using the Items collection because the list should persist even after this VM gets closed
|
||||||
LayerPropertyGroups = layerPropertyGroups;
|
LayerPropertyGroups = layerPropertyGroups;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -17,7 +17,7 @@ using Stylet;
|
|||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor
|
namespace Artemis.UI.Screens.ProfileEditor
|
||||||
{
|
{
|
||||||
public class ProfileEditorViewModel : Conductor<ProfileEditorPanelViewModel>.Collection.AllActive
|
public class ProfileEditorViewModel : Conductor<IProfileEditorPanelViewModel>.Collection.AllActive
|
||||||
{
|
{
|
||||||
private readonly IModuleService _moduleService;
|
private readonly IModuleService _moduleService;
|
||||||
private readonly IProfileEditorService _profileEditorService;
|
private readonly IProfileEditorService _profileEditorService;
|
||||||
@ -36,7 +36,7 @@ namespace Artemis.UI.Screens.ProfileEditor
|
|||||||
private PluginSetting<GridLength> _sidePanelsWidth;
|
private PluginSetting<GridLength> _sidePanelsWidth;
|
||||||
|
|
||||||
public ProfileEditorViewModel(ProfileModule module,
|
public ProfileEditorViewModel(ProfileModule module,
|
||||||
ICollection<ProfileEditorPanelViewModel> viewModels,
|
ICollection<IProfileEditorPanelViewModel> viewModels,
|
||||||
IProfileEditorService profileEditorService,
|
IProfileEditorService profileEditorService,
|
||||||
IProfileService profileService,
|
IProfileService profileService,
|
||||||
IDialogService dialogService,
|
IDialogService dialogService,
|
||||||
|
|||||||
@ -27,7 +27,7 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<TreeView Grid.Row="1"
|
<TreeView Grid.Row="1"
|
||||||
ItemsSource="{Binding RootFolder.Children}"
|
ItemsSource="{Binding ActiveItem.Items}"
|
||||||
HorizontalContentAlignment="Stretch"
|
HorizontalContentAlignment="Stretch"
|
||||||
dd:DragDrop.IsDragSource="True"
|
dd:DragDrop.IsDragSource="True"
|
||||||
dd:DragDrop.IsDropTarget="True"
|
dd:DragDrop.IsDropTarget="True"
|
||||||
@ -36,11 +36,11 @@
|
|||||||
<behaviors:TreeViewSelectionBehavior ExpandSelected="True" SelectedItem="{Binding SelectedTreeItem}" />
|
<behaviors:TreeViewSelectionBehavior ExpandSelected="True" SelectedItem="{Binding SelectedTreeItem}" />
|
||||||
</b:Interaction.Behaviors>
|
</b:Interaction.Behaviors>
|
||||||
<TreeView.Resources>
|
<TreeView.Resources>
|
||||||
<HierarchicalDataTemplate DataType="{x:Type treeItem1:FolderViewModel}" ItemsSource="{Binding Children}">
|
<HierarchicalDataTemplate DataType="{x:Type treeItem1:FolderViewModel}" ItemsSource="{Binding Items}">
|
||||||
<ContentControl s:View.Model="{Binding}" />
|
<ContentControl s:View.Model="{Binding}" />
|
||||||
</HierarchicalDataTemplate>
|
</HierarchicalDataTemplate>
|
||||||
<!-- TODO: Ensure this item source is required -->
|
<!-- TODO: Ensure this item source is required -->
|
||||||
<HierarchicalDataTemplate DataType="{x:Type treeItem1:LayerViewModel}" ItemsSource="{Binding Children}">
|
<HierarchicalDataTemplate DataType="{x:Type treeItem1:LayerViewModel}" ItemsSource="{Binding Items}">
|
||||||
<ContentControl s:View.Model="{Binding}" />
|
<ContentControl s:View.Model="{Binding}" />
|
||||||
</HierarchicalDataTemplate>
|
</HierarchicalDataTemplate>
|
||||||
</TreeView.Resources>
|
</TreeView.Resources>
|
||||||
|
|||||||
@ -11,24 +11,17 @@ using Stylet;
|
|||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
|
namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
|
||||||
{
|
{
|
||||||
public class ProfileTreeViewModel : ProfileEditorPanelViewModel, IDropTarget
|
public class ProfileTreeViewModel : Conductor<FolderViewModel>, IProfileEditorPanelViewModel, IDropTarget
|
||||||
{
|
{
|
||||||
private readonly IFolderVmFactory _folderVmFactory;
|
private readonly IProfileTreeVmFactory _profileTreeVmFactory;
|
||||||
private readonly IProfileEditorService _profileEditorService;
|
private readonly IProfileEditorService _profileEditorService;
|
||||||
private FolderViewModel _rootFolder;
|
|
||||||
private TreeItemViewModel _selectedTreeItem;
|
private TreeItemViewModel _selectedTreeItem;
|
||||||
private bool _updatingTree;
|
private bool _updatingTree;
|
||||||
|
|
||||||
public ProfileTreeViewModel(IProfileEditorService profileEditorService, IFolderVmFactory folderVmFactory)
|
public ProfileTreeViewModel(IProfileEditorService profileEditorService, IProfileTreeVmFactory profileTreeVmFactory)
|
||||||
{
|
{
|
||||||
_profileEditorService = profileEditorService;
|
_profileEditorService = profileEditorService;
|
||||||
_folderVmFactory = folderVmFactory;
|
_profileTreeVmFactory = profileTreeVmFactory;
|
||||||
}
|
|
||||||
|
|
||||||
public FolderViewModel RootFolder
|
|
||||||
{
|
|
||||||
get => _rootFolder;
|
|
||||||
set => SetAndNotify(ref _rootFolder, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TreeItemViewModel SelectedTreeItem
|
public TreeItemViewModel SelectedTreeItem
|
||||||
@ -73,7 +66,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
|
|||||||
switch (dragDropType)
|
switch (dragDropType)
|
||||||
{
|
{
|
||||||
case DragDropType.Add:
|
case DragDropType.Add:
|
||||||
source.Parent.RemoveExistingElement(source);
|
((TreeItemViewModel) source.Parent).RemoveExistingElement(source);
|
||||||
target.AddExistingElement(source);
|
target.AddExistingElement(source);
|
||||||
break;
|
break;
|
||||||
case DragDropType.InsertBefore:
|
case DragDropType.InsertBefore:
|
||||||
@ -92,27 +85,25 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
|
|||||||
// ReSharper disable once UnusedMember.Global - Called from view
|
// ReSharper disable once UnusedMember.Global - Called from view
|
||||||
public void AddFolder()
|
public void AddFolder()
|
||||||
{
|
{
|
||||||
RootFolder?.AddFolder();
|
ActiveItem?.AddFolder();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReSharper disable once UnusedMember.Global - Called from view
|
// ReSharper disable once UnusedMember.Global - Called from view
|
||||||
public void AddLayer()
|
public void AddLayer()
|
||||||
{
|
{
|
||||||
RootFolder?.AddLayer();
|
ActiveItem?.AddLayer();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnInitialActivate()
|
protected override void OnInitialActivate()
|
||||||
{
|
{
|
||||||
Subscribe();
|
Subscribe();
|
||||||
CreateRootFolderViewModel();
|
CreateRootFolderViewModel();
|
||||||
|
base.OnInitialActivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnClose()
|
protected override void OnClose()
|
||||||
{
|
{
|
||||||
Unsubscribe();
|
Unsubscribe();
|
||||||
|
|
||||||
RootFolder?.Dispose();
|
|
||||||
RootFolder = null;
|
|
||||||
base.OnClose();
|
base.OnClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,12 +113,11 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
|
|||||||
var firstChild = _profileEditorService.SelectedProfile?.Children?.FirstOrDefault();
|
var firstChild = _profileEditorService.SelectedProfile?.Children?.FirstOrDefault();
|
||||||
if (!(firstChild is Folder folder))
|
if (!(firstChild is Folder folder))
|
||||||
{
|
{
|
||||||
RootFolder = null;
|
ActivateItem(null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
RootFolder?.Dispose();
|
ActivateItem(_profileTreeVmFactory.FolderViewModel(folder));
|
||||||
RootFolder = _folderVmFactory.Create(folder);
|
|
||||||
_updatingTree = false;
|
_updatingTree = false;
|
||||||
|
|
||||||
// Auto-select the first layer
|
// Auto-select the first layer
|
||||||
@ -150,7 +140,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
|
|||||||
{
|
{
|
||||||
if (parent == source)
|
if (parent == source)
|
||||||
return DragDropType.None;
|
return DragDropType.None;
|
||||||
parent = parent.Parent;
|
parent = (TreeItemViewModel) parent.Parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (dropInfo.InsertPosition)
|
switch (dropInfo.InsertPosition)
|
||||||
@ -186,20 +176,20 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
|
|||||||
if (e.RenderProfileElement == SelectedTreeItem?.ProfileElement)
|
if (e.RenderProfileElement == SelectedTreeItem?.ProfileElement)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (RootFolder == null)
|
if (ActiveItem == null)
|
||||||
{
|
{
|
||||||
CreateRootFolderViewModel();
|
CreateRootFolderViewModel();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_updatingTree = true;
|
_updatingTree = true;
|
||||||
RootFolder.UpdateProfileElements();
|
ActiveItem.UpdateProfileElements();
|
||||||
_updatingTree = false;
|
_updatingTree = false;
|
||||||
if (e.RenderProfileElement == null)
|
if (e.RenderProfileElement == null)
|
||||||
SelectedTreeItem = null;
|
SelectedTreeItem = null;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var match = RootFolder.GetAllChildren().FirstOrDefault(vm => vm.ProfileElement == e.RenderProfileElement);
|
var match = ActiveItem.GetAllChildren().FirstOrDefault(vm => vm.ProfileElement == e.RenderProfileElement);
|
||||||
if (match != null)
|
if (match != null)
|
||||||
SelectedTreeItem = match;
|
SelectedTreeItem = match;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.Services;
|
|
||||||
using Artemis.UI.Ninject.Factories;
|
using Artemis.UI.Ninject.Factories;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
|
|
||||||
@ -11,36 +10,11 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
|||||||
public FolderViewModel(ProfileElement folder,
|
public FolderViewModel(ProfileElement folder,
|
||||||
IProfileEditorService profileEditorService,
|
IProfileEditorService profileEditorService,
|
||||||
IDialogService dialogService,
|
IDialogService dialogService,
|
||||||
IRenderElementService renderElementService,
|
IProfileTreeVmFactory profileTreeVmFactory) :
|
||||||
IFolderVmFactory folderVmFactory,
|
base(folder, profileEditorService, dialogService, profileTreeVmFactory)
|
||||||
ILayerVmFactory layerVmFactory) :
|
|
||||||
base(null, folder, profileEditorService, dialogService, renderElementService, folderVmFactory, layerVmFactory)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public FolderViewModel(TreeItemViewModel parent,
|
|
||||||
ProfileElement folder,
|
|
||||||
IProfileEditorService profileEditorService,
|
|
||||||
IDialogService dialogService,
|
|
||||||
IRenderElementService renderElementService,
|
|
||||||
IFolderVmFactory folderVmFactory,
|
|
||||||
ILayerVmFactory layerVmFactory) :
|
|
||||||
base(parent, folder, profileEditorService, dialogService, renderElementService, folderVmFactory, layerVmFactory)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool SupportsChildren => true;
|
public override bool SupportsChildren => true;
|
||||||
|
|
||||||
protected override void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
foreach (var treeItemViewModel in Children)
|
|
||||||
treeItemViewModel.Dispose();
|
|
||||||
Children.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
base.Dispose(disposing);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,5 +1,4 @@
|
|||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.Services;
|
|
||||||
using Artemis.UI.Ninject.Factories;
|
using Artemis.UI.Ninject.Factories;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
|
|
||||||
@ -7,14 +6,11 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
|||||||
{
|
{
|
||||||
public class LayerViewModel : TreeItemViewModel
|
public class LayerViewModel : TreeItemViewModel
|
||||||
{
|
{
|
||||||
public LayerViewModel(TreeItemViewModel parent,
|
public LayerViewModel(ProfileElement layer,
|
||||||
ProfileElement folder,
|
|
||||||
IProfileEditorService profileEditorService,
|
IProfileEditorService profileEditorService,
|
||||||
IDialogService dialogService,
|
IDialogService dialogService,
|
||||||
IRenderElementService renderElementService,
|
IProfileTreeVmFactory profileTreeVmFactory) :
|
||||||
IFolderVmFactory folderVmFactory,
|
base(layer, profileEditorService, dialogService, profileTreeVmFactory)
|
||||||
ILayerVmFactory layerVmFactory) :
|
|
||||||
base(parent, folder, profileEditorService, dialogService, renderElementService, folderVmFactory, layerVmFactory)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,6 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.Services;
|
|
||||||
using Artemis.UI.Exceptions;
|
using Artemis.UI.Exceptions;
|
||||||
using Artemis.UI.Ninject.Factories;
|
using Artemis.UI.Ninject.Factories;
|
||||||
using Artemis.UI.Screens.ProfileEditor.Dialogs;
|
using Artemis.UI.Screens.ProfileEditor.Dialogs;
|
||||||
@ -12,66 +11,45 @@ using Stylet;
|
|||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
||||||
{
|
{
|
||||||
public abstract class TreeItemViewModel : PropertyChangedBase, IDisposable
|
public abstract class TreeItemViewModel : Conductor<TreeItemViewModel>.Collection.AllActive, IDisposable
|
||||||
{
|
{
|
||||||
private readonly IDialogService _dialogService;
|
private readonly IDialogService _dialogService;
|
||||||
private readonly IFolderVmFactory _folderVmFactory;
|
|
||||||
private readonly ILayerVmFactory _layerVmFactory;
|
|
||||||
private readonly IProfileEditorService _profileEditorService;
|
private readonly IProfileEditorService _profileEditorService;
|
||||||
private readonly IRenderElementService _renderElementService;
|
private readonly IProfileTreeVmFactory _profileTreeVmFactory;
|
||||||
private TreeItemViewModel _parent;
|
|
||||||
private ProfileElement _profileElement;
|
private ProfileElement _profileElement;
|
||||||
|
|
||||||
protected TreeItemViewModel(TreeItemViewModel parent,
|
protected TreeItemViewModel(ProfileElement profileElement,
|
||||||
ProfileElement profileElement,
|
|
||||||
IProfileEditorService profileEditorService,
|
IProfileEditorService profileEditorService,
|
||||||
IDialogService dialogService,
|
IDialogService dialogService,
|
||||||
IRenderElementService renderElementService,
|
IProfileTreeVmFactory profileTreeVmFactory)
|
||||||
IFolderVmFactory folderVmFactory,
|
|
||||||
ILayerVmFactory layerVmFactory)
|
|
||||||
{
|
{
|
||||||
_profileEditorService = profileEditorService;
|
_profileEditorService = profileEditorService;
|
||||||
_dialogService = dialogService;
|
_dialogService = dialogService;
|
||||||
_renderElementService = renderElementService;
|
_profileTreeVmFactory = profileTreeVmFactory;
|
||||||
_folderVmFactory = folderVmFactory;
|
|
||||||
_layerVmFactory = layerVmFactory;
|
|
||||||
|
|
||||||
Parent = parent;
|
|
||||||
ProfileElement = profileElement;
|
ProfileElement = profileElement;
|
||||||
|
|
||||||
Children = new BindableCollection<TreeItemViewModel>();
|
|
||||||
|
|
||||||
Subscribe();
|
Subscribe();
|
||||||
UpdateProfileElements();
|
UpdateProfileElements();
|
||||||
}
|
}
|
||||||
|
|
||||||
public TreeItemViewModel Parent
|
|
||||||
{
|
|
||||||
get => _parent;
|
|
||||||
set => SetAndNotify(ref _parent, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProfileElement ProfileElement
|
public ProfileElement ProfileElement
|
||||||
{
|
{
|
||||||
get => _profileElement;
|
get => _profileElement;
|
||||||
set => SetAndNotify(ref _profileElement, value);
|
set => SetAndNotify(ref _profileElement, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BindableCollection<TreeItemViewModel> Children { get; }
|
|
||||||
|
|
||||||
public abstract bool SupportsChildren { get; }
|
public abstract bool SupportsChildren { get; }
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
Unsubscribe();
|
Unsubscribe();
|
||||||
Dispose(true);
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<TreeItemViewModel> GetAllChildren()
|
public List<TreeItemViewModel> GetAllChildren()
|
||||||
{
|
{
|
||||||
var children = new List<TreeItemViewModel>();
|
var children = new List<TreeItemViewModel>();
|
||||||
foreach (var childFolder in Children)
|
foreach (var childFolder in Items)
|
||||||
{
|
{
|
||||||
// Add all children in this element
|
// Add all children in this element
|
||||||
children.Add(childFolder);
|
children.Add(childFolder);
|
||||||
@ -84,34 +62,38 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
|||||||
|
|
||||||
public void SetElementInFront(TreeItemViewModel source)
|
public void SetElementInFront(TreeItemViewModel source)
|
||||||
{
|
{
|
||||||
|
var sourceParent = (TreeItemViewModel) source.Parent;
|
||||||
|
var parent = (TreeItemViewModel) Parent;
|
||||||
if (source.Parent != Parent)
|
if (source.Parent != Parent)
|
||||||
{
|
{
|
||||||
source.Parent.RemoveExistingElement(source);
|
sourceParent.RemoveExistingElement(source);
|
||||||
Parent.AddExistingElement(source);
|
parent.AddExistingElement(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
Parent.Unsubscribe();
|
parent.Unsubscribe();
|
||||||
Parent.ProfileElement.RemoveChild(source.ProfileElement);
|
parent.ProfileElement.RemoveChild(source.ProfileElement);
|
||||||
Parent.ProfileElement.AddChild(source.ProfileElement, ProfileElement.Order);
|
parent.ProfileElement.AddChild(source.ProfileElement, ProfileElement.Order);
|
||||||
Parent.Subscribe();
|
parent.Subscribe();
|
||||||
|
|
||||||
Parent.UpdateProfileElements();
|
parent.UpdateProfileElements();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetElementBehind(TreeItemViewModel source)
|
public void SetElementBehind(TreeItemViewModel source)
|
||||||
{
|
{
|
||||||
|
var sourceParent = (TreeItemViewModel) source.Parent;
|
||||||
|
var parent = (TreeItemViewModel) Parent;
|
||||||
if (source.Parent != Parent)
|
if (source.Parent != Parent)
|
||||||
{
|
{
|
||||||
source.Parent.RemoveExistingElement(source);
|
sourceParent.RemoveExistingElement(source);
|
||||||
Parent.AddExistingElement(source);
|
parent.AddExistingElement(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
Parent.Unsubscribe();
|
parent.Unsubscribe();
|
||||||
Parent.ProfileElement.RemoveChild(source.ProfileElement);
|
parent.ProfileElement.RemoveChild(source.ProfileElement);
|
||||||
Parent.ProfileElement.AddChild(source.ProfileElement, ProfileElement.Order + 1);
|
parent.ProfileElement.AddChild(source.ProfileElement, ProfileElement.Order + 1);
|
||||||
Parent.Subscribe();
|
parent.Subscribe();
|
||||||
|
|
||||||
Parent.UpdateProfileElements();
|
parent.UpdateProfileElements();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveExistingElement(TreeItemViewModel treeItem)
|
public void RemoveExistingElement(TreeItemViewModel treeItem)
|
||||||
@ -138,7 +120,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
|||||||
if (!SupportsChildren)
|
if (!SupportsChildren)
|
||||||
throw new ArtemisUIException("Cannot add a folder to a profile element of type " + ProfileElement.GetType().Name);
|
throw new ArtemisUIException("Cannot add a folder to a profile element of type " + ProfileElement.GetType().Name);
|
||||||
|
|
||||||
ProfileElement.AddChild(new Folder(ProfileElement.Profile, ProfileElement, "New folder"));
|
var _ = new Folder(ProfileElement, "New folder");
|
||||||
_profileEditorService.UpdateSelectedProfile();
|
_profileEditorService.UpdateSelectedProfile();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,7 +129,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
|||||||
if (!SupportsChildren)
|
if (!SupportsChildren)
|
||||||
throw new ArtemisUIException("Cannot add a layer to a profile element of type " + ProfileElement.GetType().Name);
|
throw new ArtemisUIException("Cannot add a layer to a profile element of type " + ProfileElement.GetType().Name);
|
||||||
|
|
||||||
_renderElementService.CreateLayer(ProfileElement.Profile, ProfileElement, "New layer");
|
var _ = new Layer(ProfileElement, "New layer");
|
||||||
_profileEditorService.UpdateSelectedProfile();
|
_profileEditorService.UpdateSelectedProfile();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,7 +162,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Farewell, cruel world
|
// Farewell, cruel world
|
||||||
var parent = Parent;
|
var parent = (TreeItemViewModel) Parent;
|
||||||
ProfileElement.Parent?.RemoveChild(ProfileElement);
|
ProfileElement.Parent?.RemoveChild(ProfileElement);
|
||||||
parent.RemoveExistingElement(this);
|
parent.RemoveExistingElement(this);
|
||||||
|
|
||||||
@ -190,17 +172,17 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
|||||||
public void UpdateProfileElements()
|
public void UpdateProfileElements()
|
||||||
{
|
{
|
||||||
// Remove VMs that are no longer a child
|
// Remove VMs that are no longer a child
|
||||||
var toRemove = Children.Where(c => c.ProfileElement.Parent != ProfileElement).ToList();
|
var toRemove = Items.Where(c => c.ProfileElement.Parent != ProfileElement).ToList();
|
||||||
foreach (var treeItemViewModel in toRemove)
|
foreach (var treeItemViewModel in toRemove)
|
||||||
Children.Remove(treeItemViewModel);
|
DeactivateItem(treeItemViewModel);
|
||||||
|
|
||||||
// Order the children
|
// Order the children
|
||||||
var vmsList = Children.OrderBy(v => v.ProfileElement.Order).ToList();
|
var vmsList = Items.OrderBy(v => v.ProfileElement.Order).ToList();
|
||||||
for (var index = 0; index < vmsList.Count; index++)
|
for (var index = 0; index < vmsList.Count; index++)
|
||||||
{
|
{
|
||||||
var profileElementViewModel = vmsList[index];
|
var profileElementViewModel = vmsList[index];
|
||||||
if (Children.IndexOf(profileElementViewModel) != index)
|
if (Items.IndexOf(profileElementViewModel) != index)
|
||||||
Children.Move(Children.IndexOf(profileElementViewModel), index);
|
((BindableCollection<TreeItemViewModel>) Items).Move(Items.IndexOf(profileElementViewModel), index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure every child element has an up-to-date VM
|
// Ensure every child element has an up-to-date VM
|
||||||
@ -212,13 +194,13 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
|||||||
{
|
{
|
||||||
if (profileElement is Folder folder)
|
if (profileElement is Folder folder)
|
||||||
{
|
{
|
||||||
if (Children.FirstOrDefault(p => p is FolderViewModel vm && vm.ProfileElement == folder) == null)
|
if (Items.FirstOrDefault(p => p is FolderViewModel vm && vm.ProfileElement == folder) == null)
|
||||||
newChildren.Add(_folderVmFactory.Create((FolderViewModel) this, folder));
|
newChildren.Add(_profileTreeVmFactory.FolderViewModel(folder));
|
||||||
}
|
}
|
||||||
else if (profileElement is Layer layer)
|
else if (profileElement is Layer layer)
|
||||||
{
|
{
|
||||||
if (Children.FirstOrDefault(p => p is LayerViewModel vm && vm.ProfileElement == layer) == null)
|
if (Items.FirstOrDefault(p => p is LayerViewModel vm && vm.ProfileElement == layer) == null)
|
||||||
newChildren.Add(_layerVmFactory.Create((FolderViewModel) this, layer));
|
newChildren.Add(_profileTreeVmFactory.LayerViewModel(layer));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,7 +211,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
|||||||
foreach (var treeItemViewModel in newChildren)
|
foreach (var treeItemViewModel in newChildren)
|
||||||
{
|
{
|
||||||
treeItemViewModel.UpdateProfileElements();
|
treeItemViewModel.UpdateProfileElements();
|
||||||
Children.Add(treeItemViewModel);
|
ActivateItem(treeItemViewModel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,13 +220,6 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
|||||||
_profileEditorService.UpdateSelectedProfile();
|
_profileEditorService.UpdateSelectedProfile();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Subscribe()
|
private void Subscribe()
|
||||||
{
|
{
|
||||||
ProfileElement.ChildAdded += ProfileElementOnChildAdded;
|
ProfileElement.ChildAdded += ProfileElementOnChildAdded;
|
||||||
|
|||||||
@ -1,60 +0,0 @@
|
|||||||
<UserControl x:Class="Artemis.UI.Screens.ProfileEditor.Visualization.ProfileDeviceView"
|
|
||||||
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:s="https://github.com/canton7/Stylet"
|
|
||||||
xmlns:converters="clr-namespace:Artemis.UI.Converters"
|
|
||||||
xmlns:visualization1="clr-namespace:Artemis.UI.Screens.ProfileEditor.Visualization"
|
|
||||||
mc:Ignorable="d"
|
|
||||||
d:DesignHeight="450"
|
|
||||||
d:DesignWidth="800"
|
|
||||||
d:DataContext="{d:DesignInstance {x:Type visualization1:ProfileDeviceViewModel}}">
|
|
||||||
<UserControl.Resources>
|
|
||||||
<converters:NullToImageConverter x:Key="NullToImageConverter" />
|
|
||||||
<converters:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
|
|
||||||
</UserControl.Resources>
|
|
||||||
|
|
||||||
<Grid Width="{Binding Device.RgbDevice.ActualSize.Width}" Height="{Binding Device.RgbDevice.ActualSize.Height}">
|
|
||||||
<Grid.RenderTransform>
|
|
||||||
<RotateTransform Angle="{Binding Device.Rotation}" />
|
|
||||||
</Grid.RenderTransform>
|
|
||||||
|
|
||||||
<!-- Device image with fallback -->
|
|
||||||
<Image VerticalAlignment="Stretch"
|
|
||||||
HorizontalAlignment="Stretch"
|
|
||||||
Source="{Binding Device.RgbDevice.DeviceInfo.Image, Converter={StaticResource NullToImageConverter}}" />
|
|
||||||
|
|
||||||
<Rectangle Fill="{DynamicResource MaterialDesignCardBackground}"
|
|
||||||
Stroke="{DynamicResource MaterialDesignTextBoxBorder}"
|
|
||||||
Margin="-5"
|
|
||||||
StrokeThickness="1"
|
|
||||||
Visibility="{Binding Device.RgbDevice.DeviceInfo.Image, ConverterParameter=Inverted, Converter={StaticResource NullToVisibilityConverter}}" />
|
|
||||||
<TextBlock Text="{Binding Device.RgbDevice.DeviceInfo.DeviceName}"
|
|
||||||
Visibility="{Binding Device.RgbDevice.DeviceInfo.Image, ConverterParameter=Inverted, Converter={StaticResource NullToVisibilityConverter}}"
|
|
||||||
HorizontalAlignment="Center"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
TextWrapping="Wrap"
|
|
||||||
TextAlignment="Center" />
|
|
||||||
|
|
||||||
<!-- LEDs -->
|
|
||||||
<ItemsControl ItemsSource="{Binding Leds}">
|
|
||||||
<ItemsControl.ItemsPanel>
|
|
||||||
<ItemsPanelTemplate>
|
|
||||||
<Canvas />
|
|
||||||
</ItemsPanelTemplate>
|
|
||||||
</ItemsControl.ItemsPanel>
|
|
||||||
<ItemsControl.ItemContainerStyle>
|
|
||||||
<Style TargetType="{x:Type ContentPresenter}">
|
|
||||||
<Setter Property="Canvas.Left" Value="{Binding X}" />
|
|
||||||
<Setter Property="Canvas.Top" Value="{Binding Y}" />
|
|
||||||
</Style>
|
|
||||||
</ItemsControl.ItemContainerStyle>
|
|
||||||
<ItemsControl.ItemTemplate>
|
|
||||||
<DataTemplate>
|
|
||||||
<ContentControl Width="{Binding Width}" Height="{Binding Height}" s:View.Model="{Binding}" />
|
|
||||||
</DataTemplate>
|
|
||||||
</ItemsControl.ItemTemplate>
|
|
||||||
</ItemsControl>
|
|
||||||
</Grid>
|
|
||||||
</UserControl>
|
|
||||||
@ -1,96 +0,0 @@
|
|||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows;
|
|
||||||
using Artemis.Core;
|
|
||||||
using Stylet;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
|
||||||
{
|
|
||||||
public class ProfileDeviceViewModel : CanvasViewModel
|
|
||||||
{
|
|
||||||
private bool _addedLeds;
|
|
||||||
private ArtemisDevice _device;
|
|
||||||
private ObservableCollection<ProfileLedViewModel> _leds;
|
|
||||||
|
|
||||||
public ProfileDeviceViewModel(ArtemisDevice device)
|
|
||||||
{
|
|
||||||
Device = device;
|
|
||||||
Leds = new ObservableCollection<ProfileLedViewModel>();
|
|
||||||
|
|
||||||
Task.Run(AddLedsAsync);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ObservableCollection<ProfileLedViewModel> Leds
|
|
||||||
{
|
|
||||||
get => _leds;
|
|
||||||
set => SetAndNotify(ref _leds, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArtemisDevice Device
|
|
||||||
{
|
|
||||||
get => _device;
|
|
||||||
set => SetAndNotify(ref _device, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool AddedLeds
|
|
||||||
{
|
|
||||||
get => _addedLeds;
|
|
||||||
private set => SetAndNotify(ref _addedLeds, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public new double X
|
|
||||||
{
|
|
||||||
get => Device.X;
|
|
||||||
set => Device.X = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public new double Y
|
|
||||||
{
|
|
||||||
get => Device.Y;
|
|
||||||
set => Device.Y = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int ZIndex
|
|
||||||
{
|
|
||||||
get => Device.ZIndex;
|
|
||||||
set => Device.ZIndex = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Rect DeviceRectangle => Device.RgbDevice == null
|
|
||||||
? new Rect()
|
|
||||||
: new Rect(X, Y, Device.RgbDevice.Size.Width, Device.RgbDevice.Size.Height);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Update the color of all LEDs if finished adding
|
|
||||||
/// </summary>
|
|
||||||
public void Update()
|
|
||||||
{
|
|
||||||
if (!AddedLeds)
|
|
||||||
return;
|
|
||||||
|
|
||||||
foreach (var ledViewModel in Leds)
|
|
||||||
ledViewModel.Update();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Adds LEDs in batches of 5 to avoid UI freezes
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
private async Task AddLedsAsync()
|
|
||||||
{
|
|
||||||
var index = 0;
|
|
||||||
foreach (var led in Device.Leds.ToList())
|
|
||||||
{
|
|
||||||
Execute.OnUIThreadSync(() => Leds.Add(new ProfileLedViewModel(led)));
|
|
||||||
if (index % 5 == 0)
|
|
||||||
await Task.Delay(1);
|
|
||||||
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
AddedLeds = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,93 +0,0 @@
|
|||||||
<UserControl x:Class="Artemis.UI.Screens.ProfileEditor.Visualization.ProfileLedView"
|
|
||||||
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:converters="clr-namespace:Artemis.UI.Converters"
|
|
||||||
xmlns:visualization1="clr-namespace:Artemis.UI.Screens.ProfileEditor.Visualization"
|
|
||||||
mc:Ignorable="d"
|
|
||||||
d:DataContext="{d:DesignInstance {x:Type visualization1:ProfileLedViewModel}}"
|
|
||||||
d:DesignHeight="25" d:DesignWidth="25">
|
|
||||||
<UserControl.Resources>
|
|
||||||
<converters:NullToImageConverter x:Key="NullToImageConverter" />
|
|
||||||
<Style TargetType="{x:Type Path}" x:Key="DimStyle">
|
|
||||||
<Style.Triggers>
|
|
||||||
<DataTrigger Binding="{Binding IsDimmed}" Value="True">
|
|
||||||
<DataTrigger.EnterActions>
|
|
||||||
<BeginStoryboard>
|
|
||||||
<Storyboard>
|
|
||||||
<DoubleAnimation Storyboard.TargetProperty="(Shape.Opacity)" To="0.2" Duration="0:0:0.25" />
|
|
||||||
</Storyboard>
|
|
||||||
</BeginStoryboard>
|
|
||||||
</DataTrigger.EnterActions>
|
|
||||||
<DataTrigger.ExitActions>
|
|
||||||
<BeginStoryboard>
|
|
||||||
<Storyboard>
|
|
||||||
<DoubleAnimation Storyboard.TargetProperty="(Shape.Opacity)" To="1" Duration="0:0:0.25" />
|
|
||||||
</Storyboard>
|
|
||||||
</BeginStoryboard>
|
|
||||||
</DataTrigger.ExitActions>
|
|
||||||
</DataTrigger>
|
|
||||||
</Style.Triggers>
|
|
||||||
</Style>
|
|
||||||
</UserControl.Resources>
|
|
||||||
<Canvas Width="{Binding Led.RgbLed.ActualSize.Width, Mode=OneWay}" Height="{Binding Led.RgbLed.ActualSize.Height, Mode=OneWay}">
|
|
||||||
<Canvas.Background>
|
|
||||||
<ImageBrush AlignmentX="Center" AlignmentY="Center" Stretch="Fill"
|
|
||||||
ImageSource="{Binding Led.RgbLed.Image, Converter={StaticResource NullToImageConverter}, Mode=OneWay}" />
|
|
||||||
</Canvas.Background>
|
|
||||||
|
|
||||||
<Path Data="{Binding DisplayGeometry, Mode=OneWay}" ClipToBounds="False" Style="{StaticResource DimStyle}">
|
|
||||||
<Path.Fill>
|
|
||||||
<SolidColorBrush Color="{Binding DisplayColor, Mode=OneWay}" Opacity="0.333" />
|
|
||||||
</Path.Fill>
|
|
||||||
</Path>
|
|
||||||
<Path Data="{Binding StrokeGeometry, Mode=OneWay}" ClipToBounds="False" Style="{StaticResource DimStyle}">
|
|
||||||
<Path.Fill>
|
|
||||||
<SolidColorBrush Color="{Binding DisplayColor, Mode=OneWay}" />
|
|
||||||
</Path.Fill>
|
|
||||||
</Path>
|
|
||||||
|
|
||||||
<!-- Selection -->
|
|
||||||
<Path Data="{Binding DisplayGeometry, Mode=OneWay}" ClipToBounds="False" StrokeThickness="1" StrokeLineJoin="Round">
|
|
||||||
<Path.Style>
|
|
||||||
<Style TargetType="{x:Type Path}">
|
|
||||||
<Style.Triggers>
|
|
||||||
<DataTrigger Binding="{Binding IsSelected}" Value="True">
|
|
||||||
<DataTrigger.EnterActions>
|
|
||||||
<BeginStoryboard x:Name="ToSelected">
|
|
||||||
<Storyboard>
|
|
||||||
<ColorAnimation
|
|
||||||
Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"
|
|
||||||
To="{StaticResource Accent700}" Duration="0:0:0.25" />
|
|
||||||
<ColorAnimation
|
|
||||||
Storyboard.TargetProperty="(Shape.Stroke).(SolidColorBrush.Color)"
|
|
||||||
To="{StaticResource Accent400}" Duration="0:0:0.25" />
|
|
||||||
</Storyboard>
|
|
||||||
</BeginStoryboard>
|
|
||||||
</DataTrigger.EnterActions>
|
|
||||||
<DataTrigger.ExitActions>
|
|
||||||
<BeginStoryboard>
|
|
||||||
<Storyboard>
|
|
||||||
<ColorAnimation
|
|
||||||
Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"
|
|
||||||
To="Transparent" Duration="0:0:0.25" />
|
|
||||||
<ColorAnimation
|
|
||||||
Storyboard.TargetProperty="(Shape.Stroke).(SolidColorBrush.Color)"
|
|
||||||
To="Transparent" Duration="0:0:0.25" />
|
|
||||||
</Storyboard>
|
|
||||||
</BeginStoryboard>
|
|
||||||
</DataTrigger.ExitActions>
|
|
||||||
</DataTrigger>
|
|
||||||
</Style.Triggers>
|
|
||||||
</Style>
|
|
||||||
</Path.Style>
|
|
||||||
<Path.Fill>
|
|
||||||
<SolidColorBrush Opacity="0.25" />
|
|
||||||
</Path.Fill>
|
|
||||||
<Path.Stroke>
|
|
||||||
<SolidColorBrush Opacity="0.5" />
|
|
||||||
</Path.Stroke>
|
|
||||||
</Path>
|
|
||||||
</Canvas>
|
|
||||||
</UserControl>
|
|
||||||
@ -1,148 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Windows;
|
|
||||||
using System.Windows.Media;
|
|
||||||
using Artemis.Core;
|
|
||||||
using Artemis.UI.Extensions;
|
|
||||||
using RGB.NET.Core;
|
|
||||||
using Stylet;
|
|
||||||
using Color = System.Windows.Media.Color;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
|
||||||
{
|
|
||||||
public class ProfileLedViewModel : PropertyChangedBase
|
|
||||||
{
|
|
||||||
private Color _displayColor;
|
|
||||||
private Geometry _displayGeometry;
|
|
||||||
private bool _isDimmed;
|
|
||||||
private bool _isSelected;
|
|
||||||
private Geometry _strokeGeometry;
|
|
||||||
|
|
||||||
public ProfileLedViewModel(ArtemisLed led)
|
|
||||||
{
|
|
||||||
Led = led;
|
|
||||||
|
|
||||||
// Don't want ActualLocation here since rotation is done in XAML
|
|
||||||
X = led.RgbLed.Location.X * led.RgbLed.Device.Scale.Horizontal;
|
|
||||||
Y = led.RgbLed.Location.Y * led.RgbLed.Device.Scale.Vertical;
|
|
||||||
Width = led.RgbLed.ActualSize.Width;
|
|
||||||
Height = led.RgbLed.ActualSize.Height;
|
|
||||||
|
|
||||||
Execute.PostToUIThread(CreateLedGeometry);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArtemisLed Led { get; }
|
|
||||||
|
|
||||||
public double X { get; }
|
|
||||||
public double Y { get; }
|
|
||||||
public double Width { get; }
|
|
||||||
public double Height { get; }
|
|
||||||
|
|
||||||
public bool IsSelected
|
|
||||||
{
|
|
||||||
get => _isSelected;
|
|
||||||
set => SetAndNotify(ref _isSelected, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsDimmed
|
|
||||||
{
|
|
||||||
get => _isDimmed;
|
|
||||||
set => SetAndNotify(ref _isDimmed, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Geometry DisplayGeometry
|
|
||||||
{
|
|
||||||
get => _displayGeometry;
|
|
||||||
private set => SetAndNotify(ref _displayGeometry, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Geometry StrokeGeometry
|
|
||||||
{
|
|
||||||
get => _strokeGeometry;
|
|
||||||
private set => SetAndNotify(ref _strokeGeometry, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Color DisplayColor
|
|
||||||
{
|
|
||||||
get => _displayColor;
|
|
||||||
private set => SetAndNotify(ref _displayColor, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Update()
|
|
||||||
{
|
|
||||||
var newColor = Led.RgbLed.Color.ToMediaColor();
|
|
||||||
Execute.PostToUIThread(() =>
|
|
||||||
{
|
|
||||||
if (!DisplayColor.Equals(newColor))
|
|
||||||
DisplayColor = newColor;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CreateLedGeometry()
|
|
||||||
{
|
|
||||||
switch (Led.RgbLed.Shape)
|
|
||||||
{
|
|
||||||
case Shape.Custom:
|
|
||||||
if (Led.RgbLed.Device.DeviceInfo.DeviceType == RGBDeviceType.Keyboard || Led.RgbLed.Device.DeviceInfo.DeviceType == RGBDeviceType.Keypad)
|
|
||||||
CreateCustomGeometry(2.0);
|
|
||||||
else
|
|
||||||
CreateCustomGeometry(1.0);
|
|
||||||
break;
|
|
||||||
case Shape.Rectangle:
|
|
||||||
if (Led.RgbLed.Device.DeviceInfo.DeviceType == RGBDeviceType.Keyboard || Led.RgbLed.Device.DeviceInfo.DeviceType == RGBDeviceType.Keypad)
|
|
||||||
CreateKeyCapGeometry();
|
|
||||||
else
|
|
||||||
CreateRectangleGeometry();
|
|
||||||
break;
|
|
||||||
case Shape.Circle:
|
|
||||||
CreateCircleGeometry();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new ArgumentOutOfRangeException();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stroke geometry is the display geometry excluding the inner geometry
|
|
||||||
StrokeGeometry = DisplayGeometry.GetWidenedPathGeometry(new Pen(null, 1.0), 0.1, ToleranceType.Absolute);
|
|
||||||
DisplayGeometry.Freeze();
|
|
||||||
StrokeGeometry.Freeze();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CreateRectangleGeometry()
|
|
||||||
{
|
|
||||||
DisplayGeometry = new RectangleGeometry(new Rect(0.5, 0.5, Width - 1, Height - 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CreateCircleGeometry()
|
|
||||||
{
|
|
||||||
DisplayGeometry = new EllipseGeometry(new Rect(0.5, 0.5, Width - 1, Height - 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CreateKeyCapGeometry()
|
|
||||||
{
|
|
||||||
DisplayGeometry = new RectangleGeometry(new Rect(1, 1, Width - 2, Height - 2), 1.6, 1.6);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CreateCustomGeometry(double deflateAmount)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
DisplayGeometry = Geometry.Combine(
|
|
||||||
Geometry.Empty,
|
|
||||||
Geometry.Parse(Led.RgbLed.ShapeData),
|
|
||||||
GeometryCombineMode.Union,
|
|
||||||
new TransformGroup
|
|
||||||
{
|
|
||||||
Children = new TransformCollection
|
|
||||||
{
|
|
||||||
new ScaleTransform(Width - deflateAmount, Height - deflateAmount),
|
|
||||||
new TranslateTransform(deflateAmount / 2, deflateAmount / 2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
CreateRectangleGeometry();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -15,7 +15,7 @@ using Stylet;
|
|||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
||||||
{
|
{
|
||||||
public class ProfileViewModel : ProfileEditorPanelViewModel, IHandle<MainWindowFocusChangedEvent>, IHandle<MainWindowKeyEvent>
|
public class ProfileViewModel : Screen, IProfileEditorPanelViewModel, IHandle<MainWindowFocusChangedEvent>, IHandle<MainWindowKeyEvent>
|
||||||
{
|
{
|
||||||
private readonly IProfileEditorService _profileEditorService;
|
private readonly IProfileEditorService _profileEditorService;
|
||||||
private readonly IProfileLayerVmFactory _profileLayerVmFactory;
|
private readonly IProfileLayerVmFactory _profileLayerVmFactory;
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<controls:MaterialWindow x:Class="Artemis.UI.Screens.ProfileEditor.LayerBrushSettingsWindowView"
|
<controls:MaterialWindow x:Class="Artemis.UI.Screens.ProfileEditor.Windows.LayerBrushSettingsWindowView"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
@ -2,7 +2,7 @@
|
|||||||
using Artemis.Core.LayerBrushes;
|
using Artemis.Core.LayerBrushes;
|
||||||
using Stylet;
|
using Stylet;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor
|
namespace Artemis.UI.Screens.ProfileEditor.Windows
|
||||||
{
|
{
|
||||||
public class LayerBrushSettingsWindowViewModel : Conductor<BrushConfigurationViewModel>
|
public class LayerBrushSettingsWindowViewModel : Conductor<BrushConfigurationViewModel>
|
||||||
{
|
{
|
||||||
@ -1,4 +1,4 @@
|
|||||||
<controls:MaterialWindow x:Class="Artemis.UI.Screens.ProfileEditor.LayerEffectSettingsWindowView"
|
<controls:MaterialWindow x:Class="Artemis.UI.Screens.ProfileEditor.Windows.LayerEffectSettingsWindowView"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
@ -2,7 +2,7 @@
|
|||||||
using Artemis.Core.LayerEffects;
|
using Artemis.Core.LayerEffects;
|
||||||
using Stylet;
|
using Stylet;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor
|
namespace Artemis.UI.Screens.ProfileEditor.Windows
|
||||||
{
|
{
|
||||||
public class LayerEffectSettingsWindowViewModel : Conductor<EffectConfigurationViewModel>
|
public class LayerEffectSettingsWindowViewModel : Conductor<EffectConfigurationViewModel>
|
||||||
{
|
{
|
||||||
Loading…
x
Reference in New Issue
Block a user