1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-12 21:38:38 +00:00

Dynamic properties WIP

This commit is contained in:
SpoinkyNL 2016-04-21 10:52:03 +02:00
parent 8394fbc418
commit 3e47ffeff7
17 changed files with 763 additions and 489 deletions

View File

@ -418,8 +418,9 @@
<Compile Include="Modules\Games\Dota2\Dota2ViewModel.cs" />
<Compile Include="Modules\Games\RocketLeague\RocketLeagueViewModel.cs" />
<Compile Include="Modules\Games\Witcher3\Witcher3ViewModel.cs" />
<Compile Include="ViewModels\LayerEditorViewModel.cs" />
<Compile Include="ViewModels\LayerEditor\LayerConditionViewModel.cs" />
<Compile Include="ViewModels\LayerEditor\LayerDynamicPropertiesViewModel.cs" />
<Compile Include="ViewModels\LayerEditor\LayerEditorViewModel.cs" />
<Compile Include="ViewModels\OverlaysViewModel.cs" />
<Compile Include="Modules\Overlays\VolumeDisplay\VolumeDisplayViewModel.cs" />
<Compile Include="ViewModels\ProfileEditorViewModel.cs" />
@ -459,12 +460,15 @@
<Compile Include="Modules\Games\Witcher3\Witcher3View.xaml.cs">
<DependentUpon>Witcher3View.xaml</DependentUpon>
</Compile>
<Compile Include="Views\LayerEditorView.xaml.cs">
<DependentUpon>LayerEditorView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\LayerEditor\LayerConditionView.xaml.cs">
<DependentUpon>LayerConditionView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\LayerEditor\LayerDynamicPropertiesView.xaml.cs">
<DependentUpon>LayerDynamicPropertiesView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\LayerEditor\LayerEditorView.xaml.cs">
<DependentUpon>LayerEditorView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\OverlaysView.xaml.cs">
<DependentUpon>OverlaysView.xaml</DependentUpon>
</Compile>
@ -623,14 +627,18 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\LayerEditorView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\LayerEditor\LayerConditionView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\LayerEditor\LayerDynamicPropertiesView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\LayerEditor\LayerEditorView.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\OverlaysView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>

View File

@ -1,4 +1,5 @@
using System.Windows;
using System.Collections;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;
@ -44,7 +45,42 @@ namespace Artemis.ItemBehaviours
{
var item = ((BindableSelectedItemBehavior) sender).AssociatedObject
.ItemContainerGenerator.ContainerFromItem(e.NewValue) as TreeViewItem;
item?.SetValue(TreeViewItem.IsSelectedProperty, true);
if (item != null)
item.SetValue(TreeViewItem.IsSelectedProperty, true);
else
ClearTreeViewSelection(((BindableSelectedItemBehavior) sender).AssociatedObject);
}
/// <summary>
/// Clears a TreeView's selected item recursively
/// Tom Wright - http://stackoverflow.com/a/1406116/5015269
/// </summary>
/// <param name="tv"></param>
public static void ClearTreeViewSelection(TreeView tv)
{
if (tv != null)
ClearTreeViewItemsControlSelection(tv.Items, tv.ItemContainerGenerator);
}
/// <summary>
/// Clears a TreeView's selected item recursively
/// Tom Wright - http://stackoverflow.com/a/1406116/5015269
/// </summary>
/// <param name="ic"></param>
/// <param name="icg"></param>
private static void ClearTreeViewItemsControlSelection(ICollection ic, ItemContainerGenerator icg)
{
if ((ic == null) || (icg == null))
return;
for (var i = 0; i < ic.Count; i++)
{
var tvi = icg.ContainerFromIndex(i) as TreeViewItem;
if (tvi == null)
continue;
ClearTreeViewItemsControlSelection(tvi.Items, tvi.ItemContainerGenerator);
tvi.IsSelected = false;
}
}
#endregion

View File

@ -1,68 +1,67 @@
using System.Collections.Generic;
using System.Drawing;
using System.Linq.Dynamic;
using System.Reflection;
using System.ComponentModel;
using Artemis.Models.Interfaces;
using Artemis.Utilities;
using static System.Decimal;
namespace Artemis.Models.Profiles
{
public class LayerDynamicPropertiesModel
{
/// <summary>
/// Property this dynamic property applies on
/// </summary>
public string LayerProperty { get; set; }
public string GameProperty { get; set; }
public string RequiredOperator { get; set; }
public string RequiredValue { get; set; }
public LayerPopertyType LayerPopertyType { get; set; }
/// <summary>
/// Only used when LayerPropertyType is PercentageOf or PercentageOfProperty
/// Property to base the percentage upon
/// </summary>
public string GameProperty { get; set; }
/// <summary>
/// Percentage source, the number that defines 100%
/// </summary>
public string PercentageSource { get; set; }
internal void ApplyProperty<T>(IGameDataModel dataModel, LayerPropertiesModel userProps,
LayerPropertiesModel props)
/// <summary>
/// Type of property
/// </summary>
public LayerPropertyType LayerPropertyType { get; set; }
internal void ApplyProperty<T>(IGameDataModel data, LayerPropertiesModel userProps, LayerPropertiesModel props)
{
var dataList = new List<T> {(T) dataModel};
// Attempt to set the property
var layerProp = props.GetType().GetProperty(LayerProperty);
var layerUserProp = userProps.GetType().GetProperty(LayerProperty);
if (LayerPopertyType == LayerPopertyType.PercentageOf)
SetPercentageOf(props, userProps, dataModel, int.Parse(PercentageSource));
if (LayerPopertyType == LayerPopertyType.PercentageOfProperty)
SetPercentageOfProperty(props, userProps, dataModel);
if (LayerPropertyType == LayerPropertyType.PercentageOf)
Apply(props, userProps, data, int.Parse(PercentageSource));
if (LayerPropertyType == LayerPropertyType.PercentageOfProperty)
ApplyProp(props, userProps, data);
}
private void SetPercentageOf(LayerPropertiesModel props, LayerPropertiesModel userProps,
IGameDataModel dataModel, int percentageSource)
private void Apply(LayerPropertiesModel props, LayerPropertiesModel userProps, IGameDataModel data,
int percentageSource)
{
// Property that will be set
// Property to apply on
var layerProp = props.GetType().GetProperty(LayerProperty);
// Property to use as a 100%
// User's settings
var userProp = userProps.GetType().GetProperty(LayerProperty);
// Value to use as a source
var source = dataModel.GetType().GetProperty(GameProperty)?.GetValue(dataModel, null);
if (layerProp == null || userProp == null || source == null)
// Property to base the percentage upon
var gameProperty = data.GetPropValue<int>(GameProperty);
if (layerProp == null || userProp == null)
return;
var percentage = double.Parse(source.ToString())/percentageSource;
var percentage = ToDouble(gameProperty) / percentageSource;
layerProp.SetValue(props, (int) (percentage*(int) userProp.GetValue(userProps, null)));
}
private void SetPercentageOfProperty(LayerPropertiesModel props, LayerPropertiesModel userProps,
IGameDataModel dataModel)
private void ApplyProp(LayerPropertiesModel props, LayerPropertiesModel userProps, IGameDataModel data)
{
var value = dataModel.GetType().GetProperty(PercentageSource)?.GetValue(dataModel, null);
if (value != null)
SetPercentageOf(props, userProps, dataModel, (int) value);
var value = data.GetPropValue<int>(PercentageSource);
Apply(props, userProps, data, value);
}
}
public enum LayerPopertyType
public enum LayerPropertyType
{
PercentageOf,
PercentageOfProperty,
Color
[Description("None")] None,
[Description("% of")] PercentageOf,
[Description("% of property")] PercentageOfProperty
}
}

View File

@ -49,22 +49,6 @@ namespace Artemis.Models.Profiles
[XmlIgnore]
public ProfileModel ParentProfile { get; internal set; }
#region IChildItem<Parent> Members
LayerModel IChildItem<LayerModel>.Parent
{
get { return ParentLayer; }
set { ParentLayer = value; }
}
ProfileModel IChildItem<ProfileModel>.Parent
{
get { return ParentProfile; }
set { ParentProfile = value; }
}
#endregion
public bool ConditionsMet<T>(IGameDataModel dataModel)
{
return Enabled && LayerConditions.All(cm => cm.ConditionMet<T>(dataModel));
@ -116,7 +100,7 @@ namespace Artemis.Models.Profiles
{
// Fix the sorting just in case
FixOrder();
int newOrder;
if (moveUp)
newOrder = selectedLayer.Order - 1;
@ -137,6 +121,22 @@ namespace Artemis.Models.Profiles
for (var i = 0; i < Children.Count; i++)
Children[i].Order = i;
}
#region IChildItem<Parent> Members
LayerModel IChildItem<LayerModel>.Parent
{
get { return ParentLayer; }
set { ParentLayer = value; }
}
ProfileModel IChildItem<ProfileModel>.Parent
{
get { return ParentProfile; }
set { ParentProfile = value; }
}
#endregion
}
public enum LayerType

View File

@ -68,6 +68,8 @@ namespace Artemis.Modules.Games.CounterStrike
if (!jsonString.Contains("Counter-Strike: Global Offensive"))
return;
Debug.WriteLine("Got data");
// Parse the JSON
GameDataModel = JsonConvert.DeserializeObject<CounterStrikeDataModel>(jsonString);
}

View File

@ -24,5 +24,51 @@ namespace Artemis.Utilities
// TODO: Convert ColorHelpers to ExtensionMethods
#endregion
#region Reflection
/// <summary>
/// Gets a value by path
/// jheddings - http://stackoverflow.com/a/1954663/5015269
/// </summary>
/// <param name="obj"></param>
/// <param name="name">Path, such as "TimeOfDay.Minutes"</param>
/// <returns></returns>
public static object GetPropValue(this object obj, string name)
{
foreach (var part in name.Split('.'))
{
if (obj == null)
return null;
var type = obj.GetType();
var info = type.GetProperty(part);
if (info == null)
return null;
obj = info.GetValue(obj, null);
}
return obj;
}
/// <summary>
/// Gets a value by path
/// jheddings - http://stackoverflow.com/a/1954663/5015269
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <param name="name"></param>
/// <returns></returns>
public static T GetPropValue<T>(this object obj, string name)
{
var retVal = GetPropValue(obj, name);
if (retVal == null)
return default(T);
// throws InvalidCastException if types are incompatible
return (T) retVal;
}
#endregion
}
}

View File

@ -1,7 +1,6 @@
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using Artemis.Settings;
@ -9,12 +8,18 @@ using Newtonsoft.Json;
namespace Artemis.Utilities.GameState
{
/// <summary>
/// Listens for JSON calls, parses them and raises an event.
/// Includes some code from https://github.com/rakijah/CSGSI
/// </summary>
public class GameStateWebServer
{
public delegate void GameDataReceivedEventHandler(
object sender, GameDataReceivedEventArgs gameDataReceivedEventArgs);
private readonly HttpListener _listener = new HttpListener();
private readonly AutoResetEvent _waitForConnection = new AutoResetEvent(false);
private HttpListener _listener;
public GameStateWebServer()
{
@ -31,64 +36,69 @@ namespace Artemis.Utilities.GameState
if (Running)
return;
Port = General.Default.GamestatePort;
_listener = new HttpListener();
_listener.Prefixes.Add($"http://localhost:{Port}/");
var listenerThread = new Thread(ListenerRun);
try
{
_listener.Prefixes.Clear();
Port = General.Default.GamestatePort;
_listener.Prefixes.Add($"http://localhost:{Port}/");
_listener.Start();
}
catch (Exception)
catch (HttpListenerException)
{
MessageBox.Show("Couldn't start the webserver. CS:GO/Dota2 effects won't work :c \n\nTry changing the port in Settings and restart Artemis.");
MessageBox.Show(
"Couldn't start the webserver. CS:GO/Dota2 effects won't work :c \n\nTry changing the port in Settings and restart Artemis.");
}
ThreadPool.QueueUserWorkItem(o =>
{
try
{
while (_listener.IsListening)
{
ThreadPool.QueueUserWorkItem(c =>
{
var ctx = c as HttpListenerContext;
if (ctx == null)
return;
try
{
HandleRequest(ctx.Request);
var buf = Encoding.UTF8.GetBytes("ok");
ctx.Response.ContentLength64 = buf.Length;
ctx.Response.OutputStream.Write(buf, 0, buf.Length);
}
catch
{
// ignored
}
finally
{
// always close the stream
ctx.Response.OutputStream.Close();
}
}, _listener.GetContext());
}
}
catch
{
// ignored
}
});
Running = true;
listenerThread.Start();
}
private void ListenerRun()
{
while (Running)
{
_listener.BeginGetContext(HandleRequest, _listener);
_waitForConnection.WaitOne();
_waitForConnection.Reset();
}
}
private void HandleRequest(IAsyncResult ar)
{
HttpListenerContext context = null;
try
{
context = _listener.EndGetContext(ar);
}
catch (ObjectDisposedException)
{
// Listener was Closed due to call of Stop();
}
catch (HttpListenerException)
{
// Listener was Closed due to call of Stop();
}
finally
{
_waitForConnection.Set();
}
if (context != null)
{
HandleRequest(context.Request);
context.Response.OutputStream.Close();
}
}
public void Stop()
{
_listener.Stop();
_listener.Close();
Running = false;
}
private string HandleRequest(HttpListenerRequest request)
private void HandleRequest(HttpListenerRequest request)
{
object json;
using (var reader = new StreamReader(request.InputStream, request.ContentEncoding))
@ -99,7 +109,6 @@ namespace Artemis.Utilities.GameState
if (json != null)
OnGameDataReceived(new GameDataReceivedEventArgs(json));
return JsonConvert.SerializeObject(json);
}
protected virtual void OnGameDataReceived(GameDataReceivedEventArgs e)

View File

@ -2,12 +2,9 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Security.Principal;
using System.Windows;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using static System.String;
namespace Artemis.Utilities
@ -62,10 +59,7 @@ namespace Artemis.Utilities
if (propertyNames.Length == 1 || value == null)
return value;
else
{
return GetPropertyValue(value, path.Replace(propertyNames[0] + ".", ""));
}
return GetPropertyValue(value, path.Replace(propertyNames[0] + ".", ""));
}
public static List<PropertyCollection> GenerateTypeMap(object o) => GenerateTypeMap(o.GetType().GetProperties());
@ -102,7 +96,9 @@ namespace Artemis.Utilities
if (friendlyName != Empty)
list.Add(parent);
list.AddRange(GenerateTypeMap(propertyInfo.PropertyType.GetProperties(), path + $"{propertyInfo.Name}."));
if (propertyInfo.PropertyType.Name != "String")
list.AddRange(GenerateTypeMap(propertyInfo.PropertyType.GetProperties(),
path + $"{propertyInfo.Name}."));
}
return list;
}

View File

@ -1,7 +1,6 @@
using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Artemis.Models.Profiles;
namespace Artemis.Utilities
@ -112,46 +111,18 @@ namespace Artemis.Utilities
}
}
public BitmapImage GetThumbnail()
public DrawingImage GetThumbnail()
{
if (_layerModel.UserProps.Brush == null)
return null;
_rectangle = new Rect(0, 0, 18, 18);
var visual = new DrawingVisual();
using (var c = visual.RenderOpen())
c.DrawRectangle(_layerModel.UserProps.Brush, new Pen(new SolidColorBrush(Colors.White), 1),
new Rect(0, 0, 18, 18));
//var bitmap = new Bitmap(18, 18);
//using (var g = Graphics.FromImage(bitmap))
//{
// g.SmoothingMode = SmoothingMode.AntiAlias;
// if (_layerModel.LayerType == LayerType.KeyboardEllipse)
// {
// g.FillEllipse(_layerModel.LayerUserProperties.Brush, _rectangle);
// g.DrawEllipse(new Pen(Color.Black, 1), 0, 0, 17, 17);
// }
// else if (_layerModel.LayerType == LayerType.KeyboardRectangle)
// {
// g.FillRectangle(_layerModel.LayerUserProperties.Brush, _rectangle);
// g.DrawRectangle(new Pen(Color.Black, 1), 0, 0, 17, 17);
// }
// else
// bitmap = Resources.folder;
//}
//using (var memory = new MemoryStream())
//{
// bitmap.Save(memory, ImageFormat.Png);
// memory.Position = 0;
// var bitmapImage = new BitmapImage();
// bitmapImage.BeginInit();
// bitmapImage.StreamSource = memory;
// bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
// bitmapImage.EndInit();
// return bitmapImage;
//}
return null;
var image = new DrawingImage(visual.Drawing);
return image;
}
public void DrawRectangle(DrawingContext c)

View File

@ -0,0 +1,103 @@
using System.ComponentModel;
using System.Linq;
using Artemis.Models.Profiles;
using Artemis.Utilities;
using Caliburn.Micro;
namespace Artemis.ViewModels.LayerEditor
{
public class LayerDynamicPropertiesViewModel : Screen
{
private LayerDynamicPropertiesModel _layerDynamicPropertiesModel;
private string _name;
private GeneralHelpers.PropertyCollection _selectedSource;
private GeneralHelpers.PropertyCollection _selectedTarget;
public LayerDynamicPropertiesViewModel(string property,
BindableCollection<GeneralHelpers.PropertyCollection> dataModelProps, LayerModel layer)
{
// Look for the existing property model
LayerDynamicPropertiesModel = layer.LayerProperties.FirstOrDefault(lp => lp.LayerProperty == property);
if (LayerDynamicPropertiesModel == null)
{
// If it doesn't exist, create a new one
LayerDynamicPropertiesModel = new LayerDynamicPropertiesModel
{
LayerProperty = property,
LayerPropertyType = LayerPropertyType.None
};
// Add it to the layer
layer.LayerProperties.Add(LayerDynamicPropertiesModel);
}
Name = property + ":";
Targets = new BindableCollection<GeneralHelpers.PropertyCollection>();
Targets.AddRange(dataModelProps.Where(p => p.Type == "Int32"));
Sources = new BindableCollection<GeneralHelpers.PropertyCollection>();
Sources.AddRange(dataModelProps.Where(p => p.Type == "Int32"));
PropertyChanged += OnPropertyChanged;
}
public string Name
{
get { return _name; }
set
{
if (value == _name) return;
_name = value;
NotifyOfPropertyChange(() => Name);
}
}
public LayerDynamicPropertiesModel LayerDynamicPropertiesModel
{
get { return _layerDynamicPropertiesModel; }
set
{
if (Equals(value, _layerDynamicPropertiesModel)) return;
_layerDynamicPropertiesModel = value;
NotifyOfPropertyChange(() => LayerDynamicPropertiesModel);
}
}
public BindableCollection<GeneralHelpers.PropertyCollection> Targets { get; set; }
public GeneralHelpers.PropertyCollection SelectedTarget
{
get { return _selectedTarget; }
set
{
if (value.Equals(_selectedTarget)) return;
_selectedTarget = value;
NotifyOfPropertyChange(() => SelectedTarget);
}
}
public BindableCollection<GeneralHelpers.PropertyCollection> Sources { get; set; }
public GeneralHelpers.PropertyCollection SelectedSource
{
get { return _selectedSource; }
set
{
if (value.Equals(_selectedSource)) return;
_selectedSource = value;
NotifyOfPropertyChange(() => SelectedSource);
}
}
/// <summary>
/// Updates the underlying model
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "SelectedTarget")
LayerDynamicPropertiesModel.GameProperty = SelectedTarget.Path;
if (e.PropertyName == "SelectedSource")
LayerDynamicPropertiesModel.PercentageSource = SelectedSource.Path;
}
}
}

View File

@ -1,149 +1,150 @@
using System;
using System.ComponentModel;
using System.Linq;
using System.Threading;
using System.Windows.Media;
using Artemis.DAL;
using Artemis.KeyboardProviders;
using Artemis.Models.Profiles;
using Artemis.Utilities;
using Artemis.ViewModels.LayerEditor;
using Caliburn.Micro;
namespace Artemis.ViewModels
{
public class LayerEditorViewModel<T> : Screen
{
private readonly KeyboardProvider _activeKeyboard;
private readonly BackgroundWorker _previewWorker;
private readonly ProfileModel _profile;
private readonly bool _wasEnabled;
private LayerModel _layer;
private LayerPropertiesModel _proposedProperties;
public LayerEditorViewModel(KeyboardProvider activeKeyboard, ProfileModel profile, LayerModel layer)
{
_activeKeyboard = activeKeyboard;
_profile = profile;
_wasEnabled = layer.Enabled;
Layer = layer;
Layer.Enabled = false;
DataModelProps = new BindableCollection<GeneralHelpers.PropertyCollection>();
ProposedProperties = new LayerPropertiesModel();
DataModelProps.AddRange(GeneralHelpers.GenerateTypeMap<T>());
LayerConditionVms =
new BindableCollection<LayerConditionViewModel<T>>(
layer.LayerConditions.Select(c => new LayerConditionViewModel<T>(this, c, DataModelProps)));
_previewWorker = new BackgroundWorker {WorkerSupportsCancellation = true};
_previewWorker.DoWork += PreviewWorkerOnDoWork;
_previewWorker.RunWorkerAsync();
PropertyChanged += AnimationUiHandler;
PreSelect();
}
public BindableCollection<GeneralHelpers.PropertyCollection> DataModelProps { get; set; }
public BindableCollection<string> LayerTypes => new BindableCollection<string>();
public BindableCollection<LayerConditionViewModel<T>> LayerConditionVms { get; set; }
public LayerModel Layer
{
get { return _layer; }
set
{
if (Equals(value, _layer)) return;
_layer = value;
NotifyOfPropertyChange(() => Layer);
}
}
public LayerPropertiesModel ProposedProperties
{
get { return _proposedProperties; }
set
{
if (Equals(value, _proposedProperties)) return;
_proposedProperties = value;
NotifyOfPropertyChange(() => ProposedProperties);
}
}
public ImageSource LayerImage
{
get
{
var keyboardRect = _activeKeyboard.KeyboardRectangle(4);
var visual = new DrawingVisual();
using (var drawingContext = visual.RenderOpen())
{
// Setup the DrawingVisual's size
drawingContext.PushClip(new RectangleGeometry(keyboardRect));
drawingContext.DrawRectangle(new SolidColorBrush(Color.FromArgb(0, 0, 0, 0)), null, keyboardRect);
// Draw the layer
_layer.DrawPreview(drawingContext);
// Remove the clip
drawingContext.Pop();
}
var image = new DrawingImage(visual.Drawing);
return image;
}
}
private void PreviewWorkerOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs)
{
while (!_previewWorker.CancellationPending)
{
NotifyOfPropertyChange(() => LayerImage);
Thread.Sleep(1000/25);
}
}
public void PreSelect()
{
GeneralHelpers.CopyProperties(ProposedProperties, Layer.UserProps);
}
private void AnimationUiHandler(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName != "_proposedProperties")
return;
}
public void AddCondition()
{
var condition = new LayerConditionModel();
Layer.LayerConditions.Add(condition);
LayerConditionVms.Add(new LayerConditionViewModel<T>(this, condition, DataModelProps));
}
public void Apply()
{
GeneralHelpers.CopyProperties(Layer.UserProps, ProposedProperties);
ProfileProvider.AddOrUpdate(_profile);
}
public void DeleteCondition(LayerConditionViewModel<T> layerConditionViewModel,
LayerConditionModel layerConditionModel)
{
LayerConditionVms.Remove(layerConditionViewModel);
Layer.LayerConditions.Remove(layerConditionModel);
}
public override void CanClose(Action<bool> callback)
{
_previewWorker.CancelAsync();
_layer.Enabled = _wasEnabled;
base.CanClose(callback);
}
}
using System;
using System.ComponentModel;
using System.Linq;
using System.Threading;
using System.Windows.Media;
using Artemis.KeyboardProviders;
using Artemis.Models.Profiles;
using Artemis.Utilities;
using Caliburn.Micro;
namespace Artemis.ViewModels.LayerEditor
{
public class LayerEditorViewModel<T> : Screen
{
private readonly KeyboardProvider _activeKeyboard;
private readonly BackgroundWorker _previewWorker;
private readonly bool _wasEnabled;
private LayerModel _layer;
private LayerPropertiesModel _proposedProperties;
public LayerEditorViewModel(KeyboardProvider activeKeyboard, LayerModel layer)
{
_activeKeyboard = activeKeyboard;
_wasEnabled = layer.Enabled;
Layer = layer;
Layer.Enabled = false;
DataModelProps = new BindableCollection<GeneralHelpers.PropertyCollection>();
ProposedProperties = new LayerPropertiesModel();
DataModelProps.AddRange(GeneralHelpers.GenerateTypeMap<T>());
LayerConditionVms = new BindableCollection<LayerConditionViewModel<T>>(
layer.LayerConditions.Select(c => new LayerConditionViewModel<T>(this, c, DataModelProps)));
HeightProperties = new LayerDynamicPropertiesViewModel("Height", DataModelProps, layer);
WidthProperties = new LayerDynamicPropertiesViewModel("Width", DataModelProps, layer);
OpacityProperties = new LayerDynamicPropertiesViewModel("Opacity", DataModelProps, layer);
_previewWorker = new BackgroundWorker {WorkerSupportsCancellation = true};
_previewWorker.DoWork += PreviewWorkerOnDoWork;
_previewWorker.RunWorkerAsync();
PropertyChanged += AnimationUiHandler;
PreSelect();
}
public LayerDynamicPropertiesViewModel OpacityProperties { get; set; }
public LayerDynamicPropertiesViewModel WidthProperties { get; set; }
public LayerDynamicPropertiesViewModel HeightProperties { get; set; }
public BindableCollection<GeneralHelpers.PropertyCollection> DataModelProps { get; set; }
public BindableCollection<string> LayerTypes => new BindableCollection<string>();
public BindableCollection<LayerConditionViewModel<T>> LayerConditionVms { get; set; }
public LayerModel Layer
{
get { return _layer; }
set
{
if (Equals(value, _layer)) return;
_layer = value;
NotifyOfPropertyChange(() => Layer);
}
}
public LayerPropertiesModel ProposedProperties
{
get { return _proposedProperties; }
set
{
if (Equals(value, _proposedProperties)) return;
_proposedProperties = value;
NotifyOfPropertyChange(() => ProposedProperties);
}
}
public ImageSource LayerImage
{
get
{
var keyboardRect = _activeKeyboard.KeyboardRectangle(4);
var visual = new DrawingVisual();
using (var drawingContext = visual.RenderOpen())
{
// Setup the DrawingVisual's size
drawingContext.PushClip(new RectangleGeometry(keyboardRect));
drawingContext.DrawRectangle(new SolidColorBrush(Color.FromArgb(0, 0, 0, 0)), null, keyboardRect);
// Draw the layer
_layer.DrawPreview(drawingContext);
// Remove the clip
drawingContext.Pop();
}
var image = new DrawingImage(visual.Drawing);
return image;
}
}
private void PreviewWorkerOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs)
{
while (!_previewWorker.CancellationPending)
{
NotifyOfPropertyChange(() => LayerImage);
Thread.Sleep(1000/25);
}
}
public void PreSelect()
{
GeneralHelpers.CopyProperties(ProposedProperties, Layer.UserProps);
}
private void AnimationUiHandler(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName != "_proposedProperties")
return;
}
public void AddCondition()
{
var condition = new LayerConditionModel();
Layer.LayerConditions.Add(condition);
LayerConditionVms.Add(new LayerConditionViewModel<T>(this, condition, DataModelProps));
}
public void Apply()
{
GeneralHelpers.CopyProperties(Layer.UserProps, ProposedProperties);
}
public void DeleteCondition(LayerConditionViewModel<T> layerConditionViewModel,
LayerConditionModel layerConditionModel)
{
LayerConditionVms.Remove(layerConditionViewModel);
Layer.LayerConditions.Remove(layerConditionModel);
}
public override void CanClose(Action<bool> callback)
{
_previewWorker.CancelAsync();
_layer.Enabled = _wasEnabled;
base.CanClose(callback);
}
}
}

View File

@ -15,6 +15,7 @@ using Artemis.KeyboardProviders;
using Artemis.Managers;
using Artemis.Models;
using Artemis.Models.Profiles;
using Artemis.ViewModels.LayerEditor;
using Caliburn.Micro;
using MahApps.Metro;
@ -78,6 +79,7 @@ namespace Artemis.ViewModels
if (Equals(value, _selectedLayer)) return;
_selectedLayer = value;
NotifyOfPropertyChange(() => SelectedLayer);
NotifyOfPropertyChange(() => CanRemoveLayer);
}
}
@ -105,6 +107,7 @@ namespace Artemis.ViewModels
NotifyOfPropertyChange(() => SelectedProfile);
NotifyOfPropertyChange(() => CanAddLayer);
NotifyOfPropertyChange(() => CanRemoveLayer);
}
}
@ -169,6 +172,7 @@ namespace Artemis.ViewModels
{
if (ActiveKeyboard?.PreviewSettings.Image == null)
return null;
ActiveKeyboard.PreviewSettings.Image.Save(memory, ImageFormat.Png);
memory.Position = 0;
@ -186,6 +190,7 @@ namespace Artemis.ViewModels
public PreviewSettings? PreviewSettings => ActiveKeyboard?.PreviewSettings;
public bool CanAddLayer => _selectedProfile != null;
public bool CanRemoveLayer => _selectedProfile != null && _selectedLayer != null;
private KeyboardProvider ActiveKeyboard => _mainManager.KeyboardManager.ActiveKeyboard;
@ -197,8 +202,13 @@ namespace Artemis.ViewModels
private void PropertyChangeHandler(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName != "KeyboardPreview")
NotifyOfPropertyChange(() => KeyboardPreview);
if (e.PropertyName == "KeyboardPreview")
return;
NotifyOfPropertyChange(() => KeyboardPreview);
if (SelectedProfile != null)
ProfileProvider.AddOrUpdate(SelectedProfile);
}
private void LoadProfiles()
@ -247,7 +257,7 @@ namespace Artemis.ViewModels
public void LayerEditor(LayerModel layer)
{
IWindowManager manager = new WindowManager();
_editorVm = new LayerEditorViewModel<T>(ActiveKeyboard, SelectedProfile, layer);
_editorVm = new LayerEditorViewModel<T>(ActiveKeyboard, layer);
dynamic settings = new ExpandoObject();
settings.Title = "Artemis | Edit " + layer.Name;
@ -272,6 +282,16 @@ namespace Artemis.ViewModels
SelectedProfile.Layers.Remove(_selectedLayer);
Layers.Remove(_selectedLayer);
SelectedProfile.FixOrder();
}
public void RemoveLayer(LayerModel layer)
{
SelectedProfile.Layers.Remove(layer);
Layers.Remove(layer);
SelectedProfile.FixOrder();
}
public void LayerUp()
@ -324,8 +344,7 @@ namespace Artemis.ViewModels
var hoverLayer = SelectedProfile.Layers.OrderBy(l => l.Order).Where(l => l.Enabled)
.FirstOrDefault(l => l.UserProps.GetRect(1).Contains(x, y));
if (hoverLayer != null)
SelectedLayer = hoverLayer;
SelectedLayer = hoverLayer;
}
public void MouseMoveKeyboardPreview(MouseEventArgs e)

View File

@ -0,0 +1,80 @@
<UserControl x:Class="Artemis.Views.LayerEditor.LayerDynamicPropertiesView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Artemis.Views.LayerEditor"
xmlns:utilities="clr-namespace:Artemis.Utilities"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:profileEnumerations="clr-namespace:Artemis.Models.Profiles"
mc:Ignorable="d"
d:DesignHeight="40" d:DesignWidth="500">
<UserControl.Resources>
<utilities:EnumDescriptionConverter x:Key="HEnumDescriptionConverter" />
<ObjectDataProvider MethodName="GetValues"
ObjectType="{x:Type sys:Enum}"
x:Key="DynamicPropertyValues">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="profileEnumerations:LayerPropertyType" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</UserControl.Resources>
<Grid>
<!-- Height -->
<Grid.ColumnDefinitions>
<ColumnDefinition Width="65*" />
<ColumnDefinition Width="86*" />
<ColumnDefinition Width="65*" />
<ColumnDefinition Width="86*" />
</Grid.ColumnDefinitions>
<TextBlock x:Name="Name" Grid.Column="0" Margin="10" FontSize="13.333" VerticalAlignment="Center" Height="18" />
<!-- Target property -->
<ComboBox x:Name="Targets" Grid.Column="1" Margin="10,0" MaxDropDownHeight="125" VerticalAlignment="Center"
Height="22">
<ComboBox.ItemTemplate>
<DataTemplate>
<Grid MinWidth="435">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Path=Display}" HorizontalAlignment="Left" />
<TextBlock Grid.Column="1" FontWeight="Bold" Text="{Binding Path=DisplayType}"
HorizontalAlignment="Right" />
</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<!-- Dynamic type -->
<ComboBox SelectedItem="{Binding Path=LayerDynamicPropertiesModel.LayerPropertyType}" Grid.Column="2"
ItemsSource="{Binding Source={StaticResource DynamicPropertyValues}}"
Margin="10,0" VerticalAlignment="Center" Height="22">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter={StaticResource HEnumDescriptionConverter}}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<!-- PercentageOf property -->
<ComboBox x:Name="Sources" Grid.Column="3" Margin="10,0" MaxDropDownHeight="125"
VerticalAlignment="Center" Height="22">
<ComboBox.ItemTemplate>
<DataTemplate>
<Grid MinWidth="522">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Path=Display}" HorizontalAlignment="Left" />
<TextBlock Grid.Column="1" FontWeight="Bold" Text="{Binding Path=DisplayType}"
HorizontalAlignment="Right" />
</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</Grid>
</UserControl>

View File

@ -1,29 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using MahApps.Metro.Controls;
using ColorBox;
namespace Artemis.Views
{
/// <summary>
/// Interaction logic for LayerEditorView.xaml
/// </summary>
public partial class LayerEditorView : MetroWindow
{
public LayerEditorView()
{
InitializeComponent();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Artemis.Views.LayerEditor
{
/// <summary>
/// Interaction logic for LayerDynamicPropertiesView.xaml
/// </summary>
public partial class LayerDynamicPropertiesView : UserControl
{
public LayerDynamicPropertiesView()
{
InitializeComponent();
}
}
}

View File

@ -1,151 +1,141 @@
<controls:MetroWindow x:Class="Artemis.Views.LayerEditorView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
xmlns:cal="http://www.caliburnproject.org"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
xmlns:utilities="clr-namespace:Artemis.Utilities"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
Title="Artemis | Edit Layer" Height="750" Width="630"
xmlns:profileEnumerations="clr-namespace:Artemis.Models.Profiles"
xmlns:ncore="http://schemas.ncore.com/wpf/xaml/colorbox"
GlowBrush="{DynamicResource AccentColorBrush}" Icon="../logo.ico" ResizeMode="NoResize">
<controls:MetroWindow.Resources>
<utilities:EnumDescriptionConverter x:Key="HEnumDescriptionConverter" />
<ObjectDataProvider MethodName="GetValues"
ObjectType="{x:Type sys:Enum}"
x:Key="AnimationEnumValues">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="profileEnumerations:LayerAnimation" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</controls:MetroWindow.Resources>
<Grid Margin="10,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="65*" />
<ColumnDefinition Width="86*" />
<ColumnDefinition Width="65*" />
<ColumnDefinition Width="86*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition />
</Grid.RowDefinitions>
<!-- Header -->
<Label Grid.Row="0" Grid.ColumnSpan="4" FontSize="20" Content="Basics" />
<!-- Layer name -->
<TextBlock Grid.Row="1" Grid.Column="0" Margin="10,12" FontSize="13.333" Text="Name:"
VerticalAlignment="Center" Height="18" />
<TextBox Grid.Row="1" Grid.Column="1" x:Name="Name" Margin="10" Text="{Binding Path=Layer.Name}" />
<!-- Layer type -->
<!-- Condition editor -->
<Label Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="4" FontSize="20" Content="Display if.." />
<Border Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="4" BorderThickness="1"
BorderBrush="{StaticResource GrayBrush7}" Margin="10,0" SnapsToDevicePixels="True">
<ListBox Height="138" x:Name="LayerConditionVms" ScrollViewer.VerticalScrollBarVisibility="Visible">
<ListBox.Template>
<ControlTemplate>
<ScrollViewer>
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</ListBox.Template>
</ListBox>
</Border>
<Button Grid.Row="4" Grid.Column="3" x:Name="AddCondition" Content="Add condition" VerticalAlignment="Center"
Style="{DynamicResource SquareButtonStyle}" Width="95" HorizontalAlignment="Right" Height="30"
Margin="0,10,10,10" ScrollViewer.VerticalScrollBarVisibility="Auto" />
<!-- Advanced -->
<Label Grid.Row="4" Grid.Column="0" FontSize="20" HorizontalAlignment="Left"
Content="Advanced" Width="97" VerticalAlignment="Bottom" />
<!-- Height -->
<TextBlock Grid.Row="5" Grid.Column="0" Margin="10" FontSize="13.333" Text="Height:" VerticalAlignment="Center"
Height="18" />
<TextBox Grid.Row="5" Grid.Column="1" Margin="10" Text="{Binding Path=ProposedProperties.Height}" />
<!-- Width -->
<TextBlock Grid.Row="5" Grid.Column="2" Margin="10" FontSize="13.333" Text="Width:" VerticalAlignment="Center"
Height="18" />
<TextBox Grid.Row="5" Grid.Column="3" Margin="10" Text="{Binding Path=ProposedProperties.Width}" />
<!-- Colors -->
<TextBlock Grid.Row="6" Grid.Column="0" Margin="10,13,10,0" FontSize="13.333" Text="Color(s):"
VerticalAlignment="Top" Height="18" />
<Border Grid.Row="6" Grid.Column="1" Margin="10" BorderBrush="{StaticResource ControlBorderBrush}"
BorderThickness="1" SnapsToDevicePixels="True" ToolTip="Click to edit">
<ncore:ColorBox Brush="{Binding Path=ProposedProperties.Brush, Mode=TwoWay}" Height="24" />
</Border>
<!-- ContainedBrush -->
<TextBlock Grid.Row="6" Grid.Column="2" Margin="10" FontSize="13.333" Text="Contained colors:"
VerticalAlignment="Center" Height="18" />
<controls:ToggleSwitch IsChecked="{Binding Path=ProposedProperties.ContainedBrush, Mode=TwoWay}" Grid.Row="6"
Grid.Column="3" OnLabel="Yes" OffLabel="No" Margin="10,1,5,1" VerticalAlignment="Center"
Height="36" />
<!-- Animation -->
<TextBlock Grid.Row="7" Grid.Column="0" Margin="10" FontSize="13.333" Text="Animation:"
VerticalAlignment="Center"
Height="18" />
<ComboBox Grid.Row="7" Grid.Column="1" ItemsSource="{Binding Source={StaticResource AnimationEnumValues}}"
Margin="10,10,10,0" SelectedItem="{Binding Path=ProposedProperties.Animation}"
VerticalAlignment="Top" Height="22">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter={StaticResource HEnumDescriptionConverter}}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<!-- Animation Speed -->
<TextBlock Grid.Row="7" Grid.Column="2" Margin="10" FontSize="13.333" Text="Animation speed:"
VerticalAlignment="Center" Height="18" />
<Slider x:Name="RotationSpeed" Grid.Row="7" Grid.Column="3" VerticalAlignment="Center"
TickPlacement="None" TickFrequency="0.05"
Value="{Binding Path=ProposedProperties.AnimationSpeed, Mode=TwoWay}" Minimum="0.05" Maximum="3"
SmallChange="1" IsSnapToTickEnabled="True" Margin="10,12,10,2" Height="24" />
<!-- Opacity -->
<TextBlock Grid.Row="8" Grid.Column="0" Margin="10" FontSize="13.333" Text="Opacity:"
VerticalAlignment="Center" Height="18" />
<Slider x:Name="Sensitivity" Grid.Row="8" Grid.Column="1" VerticalAlignment="Center"
TickPlacement="BottomRight" TickFrequency="0.05"
Value="{Binding Path=ProposedProperties.Opacity, Mode=TwoWay}" Minimum="0.0" Maximum="1.0"
SmallChange="0.05" Margin="10,7" Height="24" />
<!-- Preview -->
<TextBlock Grid.Row="9" Grid.Column="0" Margin="10,13,10,0" FontSize="13.333" Text="Preview:"
VerticalAlignment="Top" Height="18" />
<Border Grid.Row="9" Grid.Column="1" Grid.ColumnSpan="2" Margin="10" BorderThickness="1"
BorderBrush="{StaticResource ControlBorderBrush}" SnapsToDevicePixels="True">
<Image Source="{Binding LayerImage}" />
</Border>
<Button Grid.Row="10" Grid.Column="0" x:Name="Apply" Content="Apply" VerticalAlignment="Bottom"
Style="{DynamicResource SquareButtonStyle}" Width="95" HorizontalAlignment="Left" Margin="10,0,0,20"
Height="30" />
<Button Grid.Row="10" Grid.Column="1" x:Name="PreSelect" Content="Reset" VerticalAlignment="Bottom"
Style="{DynamicResource SquareButtonStyle}" Width="95" HorizontalAlignment="Left" Margin="10,0,0,20"
Height="30" />
</Grid>
<controls:MetroWindow x:Class="Artemis.Views.LayerEditor.LayerEditorView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
xmlns:utilities="clr-namespace:Artemis.Utilities"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
Title="Artemis | Edit Layer" Height="750" Width="630"
xmlns:profileEnumerations="clr-namespace:Artemis.Models.Profiles"
xmlns:ncore="http://schemas.ncore.com/wpf/xaml/colorbox"
GlowBrush="{DynamicResource AccentColorBrush}" Icon="../../Resources/bow.png" ResizeMode="NoResize">
<controls:MetroWindow.Resources>
<utilities:EnumDescriptionConverter x:Key="HEnumDescriptionConverter" />
<ObjectDataProvider MethodName="GetValues"
ObjectType="{x:Type sys:Enum}"
x:Key="AnimationEnumValues">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="profileEnumerations:LayerAnimation" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<ObjectDataProvider MethodName="GetValues"
ObjectType="{x:Type sys:Enum}"
x:Key="DynamicPropertyValues">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="profileEnumerations:LayerPropertyType" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</controls:MetroWindow.Resources>
<Grid Margin="10,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="65*" />
<ColumnDefinition Width="86*" />
<ColumnDefinition Width="65*" />
<ColumnDefinition Width="86*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition />
</Grid.RowDefinitions>
<!-- Header -->
<Label Grid.Row="0" Grid.ColumnSpan="4" FontSize="20" Content="Basics" />
<!-- Layer name -->
<TextBlock Grid.Row="1" Grid.Column="0" Margin="10,12" FontSize="13.333" Text="Name:"
VerticalAlignment="Center" Height="18" />
<TextBox Grid.Row="1" Grid.Column="1" x:Name="Name" Margin="10" Text="{Binding Path=Layer.Name}" />
<!-- Layer type -->
<!-- Condition editor -->
<Label Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="4" FontSize="20" Content="Display if.." />
<Border Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="4" BorderThickness="1"
BorderBrush="{StaticResource GrayBrush7}" Margin="10,0" SnapsToDevicePixels="True">
<ListBox Height="138" x:Name="LayerConditionVms" ScrollViewer.VerticalScrollBarVisibility="Visible">
<ListBox.Template>
<ControlTemplate>
<ScrollViewer>
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</ListBox.Template>
</ListBox>
</Border>
<Button Grid.Row="4" Grid.Column="3" x:Name="AddCondition" Content="Add condition" VerticalAlignment="Center"
Style="{DynamicResource SquareButtonStyle}" Width="95" HorizontalAlignment="Right" Height="30"
Margin="0,10,10,10" ScrollViewer.VerticalScrollBarVisibility="Auto" />
<!-- Advanced -->
<Label Grid.Row="4" Grid.Column="0" FontSize="20" HorizontalAlignment="Left"
Content="Advanced" Width="97" VerticalAlignment="Bottom" />
<!-- Colors -->
<TextBlock Grid.Row="5" Grid.Column="0" Margin="10,13,10,0" FontSize="13.333" Text="Color(s):"
VerticalAlignment="Top" Height="18" />
<Border Grid.Row="5" Grid.Column="1" Margin="10" BorderBrush="{StaticResource ControlBorderBrush}"
BorderThickness="1" SnapsToDevicePixels="True" ToolTip="Click to edit">
<ncore:ColorBox Brush="{Binding Path=ProposedProperties.Brush, Mode=TwoWay}" Height="24" />
</Border>
<!-- ContainedBrush -->
<TextBlock Grid.Row="5" Grid.Column="2" Margin="10" FontSize="13.333" Text="Contained colors:"
VerticalAlignment="Center" Height="18" />
<controls:ToggleSwitch IsChecked="{Binding Path=ProposedProperties.ContainedBrush, Mode=TwoWay}" Grid.Row="5"
Grid.Column="3" OnLabel="Yes" OffLabel="No" Margin="10,1,5,1" VerticalAlignment="Center"
Height="36" />
<!-- Animation -->
<TextBlock Grid.Row="6" Grid.Column="0" Margin="10" FontSize="13.333" Text="Animation:"
VerticalAlignment="Center"
Height="18" />
<ComboBox Grid.Row="6" Grid.Column="1" ItemsSource="{Binding Source={StaticResource AnimationEnumValues}}"
Margin="10,10,10,0" SelectedItem="{Binding Path=ProposedProperties.Animation}"
VerticalAlignment="Top" Height="22">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter={StaticResource HEnumDescriptionConverter}}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<!-- Animation Speed -->
<TextBlock Grid.Row="6" Grid.Column="2" Margin="10" FontSize="13.333" Text="Animation speed:"
VerticalAlignment="Center" Height="18" />
<Slider x:Name="RotationSpeed" Grid.Row="6" Grid.Column="3" VerticalAlignment="Center"
TickPlacement="None" TickFrequency="0.05"
Value="{Binding Path=ProposedProperties.AnimationSpeed, Mode=TwoWay}" Minimum="0.05" Maximum="3"
SmallChange="1" IsSnapToTickEnabled="True" Margin="10,12,10,2" Height="24" />
<!-- Dynamic -->
<Label Grid.Row="7" Grid.Column="0" FontSize="20" HorizontalAlignment="Left"
Content="Dynamic" Width="97" VerticalAlignment="Bottom" />
<!-- Dynamic property views -->
<ContentControl Grid.Row="8" Grid.Column="0" Grid.ColumnSpan="4" x:Name="HeightProperties" />
<ContentControl Grid.Row="9" Grid.Column="0" Grid.ColumnSpan="4" x:Name="WidthProperties" />
<ContentControl Grid.Row="10" Grid.Column="0" Grid.ColumnSpan="4" x:Name="OpacityProperties" />
<Button Grid.Row="12" Grid.Column="0" x:Name="Apply" Content="Apply" VerticalAlignment="Bottom"
Style="{DynamicResource SquareButtonStyle}" Width="95" HorizontalAlignment="Left" Margin="10,0,0,20"
Height="30" />
<Button Grid.Row="12" Grid.Column="1" x:Name="PreSelect" Content="Reset" VerticalAlignment="Bottom"
Style="{DynamicResource SquareButtonStyle}" Width="95" HorizontalAlignment="Left" Margin="10,0,0,20"
Height="30" />
</Grid>
</controls:MetroWindow>

View File

@ -0,0 +1,15 @@
using MahApps.Metro.Controls;
namespace Artemis.Views.LayerEditor
{
/// <summary>
/// Interaction logic for LayerEditorView.xaml
/// </summary>
public partial class LayerEditorView : MetroWindow
{
public LayerEditorView()
{
InitializeComponent();
}
}
}

View File

@ -78,7 +78,7 @@
<ContextMenu
cal:Action.TargetWithoutContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Rename" />
<MenuItem Header="Delete" />
<MenuItem Header="Delete" cal:Message.Attach="RemoveLayer($datacontext)"/>
<MenuItem Header="Properties" cal:Message.Attach="LayerEditor($datacontext)" />
</ContextMenu>
</StackPanel.ContextMenu>