1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +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\Dota2\Dota2ViewModel.cs" />
<Compile Include="Modules\Games\RocketLeague\RocketLeagueViewModel.cs" /> <Compile Include="Modules\Games\RocketLeague\RocketLeagueViewModel.cs" />
<Compile Include="Modules\Games\Witcher3\Witcher3ViewModel.cs" /> <Compile Include="Modules\Games\Witcher3\Witcher3ViewModel.cs" />
<Compile Include="ViewModels\LayerEditorViewModel.cs" />
<Compile Include="ViewModels\LayerEditor\LayerConditionViewModel.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="ViewModels\OverlaysViewModel.cs" />
<Compile Include="Modules\Overlays\VolumeDisplay\VolumeDisplayViewModel.cs" /> <Compile Include="Modules\Overlays\VolumeDisplay\VolumeDisplayViewModel.cs" />
<Compile Include="ViewModels\ProfileEditorViewModel.cs" /> <Compile Include="ViewModels\ProfileEditorViewModel.cs" />
@ -459,12 +460,15 @@
<Compile Include="Modules\Games\Witcher3\Witcher3View.xaml.cs"> <Compile Include="Modules\Games\Witcher3\Witcher3View.xaml.cs">
<DependentUpon>Witcher3View.xaml</DependentUpon> <DependentUpon>Witcher3View.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Views\LayerEditorView.xaml.cs">
<DependentUpon>LayerEditorView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\LayerEditor\LayerConditionView.xaml.cs"> <Compile Include="Views\LayerEditor\LayerConditionView.xaml.cs">
<DependentUpon>LayerConditionView.xaml</DependentUpon> <DependentUpon>LayerConditionView.xaml</DependentUpon>
</Compile> </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"> <Compile Include="Views\OverlaysView.xaml.cs">
<DependentUpon>OverlaysView.xaml</DependentUpon> <DependentUpon>OverlaysView.xaml</DependentUpon>
</Compile> </Compile>
@ -623,14 +627,18 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
<Page Include="Views\LayerEditorView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\LayerEditor\LayerConditionView.xaml"> <Page Include="Views\LayerEditor\LayerConditionView.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </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"> <Page Include="Views\OverlaysView.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <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.Controls;
using System.Windows.Interactivity; using System.Windows.Interactivity;
@ -44,7 +45,42 @@ namespace Artemis.ItemBehaviours
{ {
var item = ((BindableSelectedItemBehavior) sender).AssociatedObject var item = ((BindableSelectedItemBehavior) sender).AssociatedObject
.ItemContainerGenerator.ContainerFromItem(e.NewValue) as TreeViewItem; .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 #endregion

View File

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

View File

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

View File

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

View File

@ -24,5 +24,51 @@ namespace Artemis.Utilities
// TODO: Convert ColorHelpers to ExtensionMethods // TODO: Convert ColorHelpers to ExtensionMethods
#endregion #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;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Text;
using System.Threading; using System.Threading;
using System.Windows.Forms; using System.Windows.Forms;
using Artemis.Settings; using Artemis.Settings;
@ -9,12 +8,18 @@ using Newtonsoft.Json;
namespace Artemis.Utilities.GameState 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 class GameStateWebServer
{ {
public delegate void GameDataReceivedEventHandler( public delegate void GameDataReceivedEventHandler(
object sender, GameDataReceivedEventArgs gameDataReceivedEventArgs); object sender, GameDataReceivedEventArgs gameDataReceivedEventArgs);
private readonly HttpListener _listener = new HttpListener(); private readonly AutoResetEvent _waitForConnection = new AutoResetEvent(false);
private HttpListener _listener;
public GameStateWebServer() public GameStateWebServer()
{ {
@ -31,64 +36,69 @@ namespace Artemis.Utilities.GameState
if (Running) if (Running)
return; return;
Port = General.Default.GamestatePort;
_listener = new HttpListener();
_listener.Prefixes.Add($"http://localhost:{Port}/");
var listenerThread = new Thread(ListenerRun);
try try
{ {
_listener.Prefixes.Clear();
Port = General.Default.GamestatePort;
_listener.Prefixes.Add($"http://localhost:{Port}/");
_listener.Start(); _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; 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() public void Stop()
{ {
_listener.Stop(); _listener.Close();
Running = false;
} }
private string HandleRequest(HttpListenerRequest request) private void HandleRequest(HttpListenerRequest request)
{ {
object json; object json;
using (var reader = new StreamReader(request.InputStream, request.ContentEncoding)) using (var reader = new StreamReader(request.InputStream, request.ContentEncoding))
@ -99,7 +109,6 @@ namespace Artemis.Utilities.GameState
if (json != null) if (json != null)
OnGameDataReceived(new GameDataReceivedEventArgs(json)); OnGameDataReceived(new GameDataReceivedEventArgs(json));
return JsonConvert.SerializeObject(json);
} }
protected virtual void OnGameDataReceived(GameDataReceivedEventArgs e) protected virtual void OnGameDataReceived(GameDataReceivedEventArgs e)

View File

@ -2,12 +2,9 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Linq;
using System.Reflection; using System.Reflection;
using System.Security.Principal; using System.Security.Principal;
using System.Windows; using System.Windows;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using static System.String; using static System.String;
namespace Artemis.Utilities namespace Artemis.Utilities
@ -62,10 +59,7 @@ namespace Artemis.Utilities
if (propertyNames.Length == 1 || value == null) if (propertyNames.Length == 1 || value == null)
return value; 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()); public static List<PropertyCollection> GenerateTypeMap(object o) => GenerateTypeMap(o.GetType().GetProperties());
@ -102,7 +96,9 @@ namespace Artemis.Utilities
if (friendlyName != Empty) if (friendlyName != Empty)
list.Add(parent); 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; return list;
} }

View File

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

View File

@ -15,6 +15,7 @@ using Artemis.KeyboardProviders;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models; using Artemis.Models;
using Artemis.Models.Profiles; using Artemis.Models.Profiles;
using Artemis.ViewModels.LayerEditor;
using Caliburn.Micro; using Caliburn.Micro;
using MahApps.Metro; using MahApps.Metro;
@ -78,6 +79,7 @@ namespace Artemis.ViewModels
if (Equals(value, _selectedLayer)) return; if (Equals(value, _selectedLayer)) return;
_selectedLayer = value; _selectedLayer = value;
NotifyOfPropertyChange(() => SelectedLayer); NotifyOfPropertyChange(() => SelectedLayer);
NotifyOfPropertyChange(() => CanRemoveLayer);
} }
} }
@ -105,6 +107,7 @@ namespace Artemis.ViewModels
NotifyOfPropertyChange(() => SelectedProfile); NotifyOfPropertyChange(() => SelectedProfile);
NotifyOfPropertyChange(() => CanAddLayer); NotifyOfPropertyChange(() => CanAddLayer);
NotifyOfPropertyChange(() => CanRemoveLayer);
} }
} }
@ -169,6 +172,7 @@ namespace Artemis.ViewModels
{ {
if (ActiveKeyboard?.PreviewSettings.Image == null) if (ActiveKeyboard?.PreviewSettings.Image == null)
return null; return null;
ActiveKeyboard.PreviewSettings.Image.Save(memory, ImageFormat.Png); ActiveKeyboard.PreviewSettings.Image.Save(memory, ImageFormat.Png);
memory.Position = 0; memory.Position = 0;
@ -186,6 +190,7 @@ namespace Artemis.ViewModels
public PreviewSettings? PreviewSettings => ActiveKeyboard?.PreviewSettings; public PreviewSettings? PreviewSettings => ActiveKeyboard?.PreviewSettings;
public bool CanAddLayer => _selectedProfile != null; public bool CanAddLayer => _selectedProfile != null;
public bool CanRemoveLayer => _selectedProfile != null && _selectedLayer != null;
private KeyboardProvider ActiveKeyboard => _mainManager.KeyboardManager.ActiveKeyboard; private KeyboardProvider ActiveKeyboard => _mainManager.KeyboardManager.ActiveKeyboard;
@ -197,8 +202,13 @@ namespace Artemis.ViewModels
private void PropertyChangeHandler(object sender, PropertyChangedEventArgs e) private void PropertyChangeHandler(object sender, PropertyChangedEventArgs e)
{ {
if (e.PropertyName != "KeyboardPreview") if (e.PropertyName == "KeyboardPreview")
NotifyOfPropertyChange(() => KeyboardPreview); return;
NotifyOfPropertyChange(() => KeyboardPreview);
if (SelectedProfile != null)
ProfileProvider.AddOrUpdate(SelectedProfile);
} }
private void LoadProfiles() private void LoadProfiles()
@ -247,7 +257,7 @@ namespace Artemis.ViewModels
public void LayerEditor(LayerModel layer) public void LayerEditor(LayerModel layer)
{ {
IWindowManager manager = new WindowManager(); IWindowManager manager = new WindowManager();
_editorVm = new LayerEditorViewModel<T>(ActiveKeyboard, SelectedProfile, layer); _editorVm = new LayerEditorViewModel<T>(ActiveKeyboard, layer);
dynamic settings = new ExpandoObject(); dynamic settings = new ExpandoObject();
settings.Title = "Artemis | Edit " + layer.Name; settings.Title = "Artemis | Edit " + layer.Name;
@ -272,6 +282,16 @@ namespace Artemis.ViewModels
SelectedProfile.Layers.Remove(_selectedLayer); SelectedProfile.Layers.Remove(_selectedLayer);
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() public void LayerUp()
@ -324,8 +344,7 @@ namespace Artemis.ViewModels
var hoverLayer = SelectedProfile.Layers.OrderBy(l => l.Order).Where(l => l.Enabled) var hoverLayer = SelectedProfile.Layers.OrderBy(l => l.Order).Where(l => l.Enabled)
.FirstOrDefault(l => l.UserProps.GetRect(1).Contains(x, y)); .FirstOrDefault(l => l.UserProps.GetRect(1).Contains(x, y));
if (hoverLayer != null) SelectedLayer = hoverLayer;
SelectedLayer = hoverLayer;
} }
public void MouseMoveKeyboardPreview(MouseEventArgs e) 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;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Data; using System.Windows.Data;
using System.Windows.Documents; using System.Windows.Documents;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using System.Windows.Shapes; using System.Windows.Navigation;
using MahApps.Metro.Controls; using System.Windows.Shapes;
using ColorBox;
namespace Artemis.Views.LayerEditor
namespace Artemis.Views {
{ /// <summary>
/// <summary> /// Interaction logic for LayerDynamicPropertiesView.xaml
/// Interaction logic for LayerEditorView.xaml /// </summary>
/// </summary> public partial class LayerDynamicPropertiesView : UserControl
public partial class LayerEditorView : MetroWindow {
{ public LayerDynamicPropertiesView()
public LayerEditorView() {
{ InitializeComponent();
InitializeComponent(); }
} }
} }
}

View File

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