1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00

Moved from a JSON to a XML save format. Implemented WPF-based layer drawing

This commit is contained in:
SpoinkyNL 2016-04-06 14:48:20 +02:00
parent c44c93803e
commit 36bdfa5aaa
13 changed files with 184 additions and 331 deletions

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Xml.Serialization;
using Artemis.Models; using Artemis.Models;
using Artemis.Models.Profiles; using Artemis.Models.Profiles;
using Newtonsoft.Json; using Newtonsoft.Json;
@ -47,8 +48,11 @@ namespace Artemis.DAL
if (!Directory.Exists(path)) if (!Directory.Exists(path))
Directory.CreateDirectory(path); Directory.CreateDirectory(path);
var serialized = JsonConvert.SerializeObject(prof, Formatting.Indented); var serializer = new XmlSerializer(typeof(ProfileModel));
File.WriteAllText(path + $@"\{prof.Name}.json", serialized); using (var file = new StreamWriter(path + $@"\{prof.Name}.xml"))
{
serializer.Serialize(file, prof);
}
} }
private static List<ProfileModel> ReadProfiles() private static List<ProfileModel> ReadProfiles()
@ -57,15 +61,20 @@ namespace Artemis.DAL
var profiles = new List<ProfileModel>(); var profiles = new List<ProfileModel>();
// Create the directory structure // Create the directory structure
var profileFiles = Directory.GetFiles(ProfileFolder, "*.json", SearchOption.AllDirectories); var profilePaths = Directory.GetFiles(ProfileFolder, "*.xml", SearchOption.AllDirectories);
// Parse the JSON files into objects and add them if they are valid // Parse the JSON files into objects and add them if they are valid
foreach (var file in profileFiles) // TODO: Invalid file handling
var deserializer = new XmlSerializer(typeof (ProfileModel));
foreach (var path in profilePaths)
{ {
var prof = JsonConvert.DeserializeObject<ProfileModel>(File.ReadAllText(file)); using (var file = new StreamReader(path))
{
var prof = (ProfileModel) deserializer.Deserialize(file);
if (prof.GameName?.Length > 1 && prof.KeyboardName?.Length > 1 && prof.Name?.Length > 1) if (prof.GameName?.Length > 1 && prof.KeyboardName?.Length > 1 && prof.Name?.Length > 1)
profiles.Add(prof); profiles.Add(prof);
} }
}
return profiles; return profiles;
} }

View File

@ -19,11 +19,6 @@ namespace Artemis.Models.Profiles
/// </summary> /// </summary>
public string PercentageSource { get; set; } public string PercentageSource { get; set; }
/// <summary>
/// Only used when LayerPropertyType is Color
/// </summary>
public List<Color> LayerColors { get; set; }
internal void ApplyProperty<T>(IGameDataModel dataModel, LayerPropertiesModel userProps, internal void ApplyProperty<T>(IGameDataModel dataModel, LayerPropertiesModel userProps,
LayerPropertiesModel props) LayerPropertiesModel props)
{ {
@ -37,11 +32,6 @@ namespace Artemis.Models.Profiles
SetPercentageOf(props, userProps, dataModel, int.Parse(PercentageSource)); SetPercentageOf(props, userProps, dataModel, int.Parse(PercentageSource));
if (LayerPopertyType == LayerPopertyType.PercentageOfProperty) if (LayerPopertyType == LayerPopertyType.PercentageOfProperty)
SetPercentageOfProperty(props, userProps, dataModel); SetPercentageOfProperty(props, userProps, dataModel);
if (LayerPopertyType == LayerPopertyType.Color)
{
if (dataList.Where($"{GameProperty} {RequiredOperator} {RequiredValue}").Any())
SetColor(layerProp, dataModel);
}
} }
private void SetPercentageOf(LayerPropertiesModel props, LayerPropertiesModel userProps, private void SetPercentageOf(LayerPropertiesModel props, LayerPropertiesModel userProps,
@ -67,14 +57,6 @@ namespace Artemis.Models.Profiles
if (value != null) if (value != null)
SetPercentageOf(props, userProps, dataModel, (int) value); SetPercentageOf(props, userProps, dataModel, (int) value);
} }
private void SetColor(PropertyInfo layerProp, IGameDataModel dataModel)
{
if (layerProp == null)
return;
if (layerProp.PropertyType == typeof (List<Color>))
layerProp.SetValue(dataModel, LayerColors, null);
}
} }
public enum LayerPopertyType public enum LayerPopertyType

View File

@ -1,8 +1,8 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Drawing;
using System.Linq; using System.Linq;
using System.Windows.Media; using System.Windows.Media;
using System.Xml.Serialization;
using Artemis.Models.Interfaces; using Artemis.Models.Interfaces;
using Artemis.Utilities; using Artemis.Utilities;
using Newtonsoft.Json; using Newtonsoft.Json;
@ -11,12 +11,10 @@ namespace Artemis.Models.Profiles
{ {
public class LayerModel public class LayerModel
{ {
[JsonIgnore] private readonly LayerDrawer _drawer; [XmlIgnore] private readonly LayerDrawer _drawer;
public LayerModel(string name, LayerType layerType) public LayerModel()
{ {
Name = name;
LayerType = layerType;
LayerUserProperties = new LayerPropertiesModel(); LayerUserProperties = new LayerPropertiesModel();
LayerCalculatedProperties = new LayerPropertiesModel(); LayerCalculatedProperties = new LayerPropertiesModel();
@ -35,10 +33,10 @@ namespace Artemis.Models.Profiles
public List<LayerConditionModel> LayerConditions { get; set; } public List<LayerConditionModel> LayerConditions { get; set; }
public List<LayerDynamicPropertiesModel> LayerProperties { get; set; } public List<LayerDynamicPropertiesModel> LayerProperties { get; set; }
[JsonIgnore] [XmlIgnore]
public LayerPropertiesModel LayerCalculatedProperties { get; set; } public LayerPropertiesModel LayerCalculatedProperties { get; set; }
[JsonIgnore] [XmlIgnore]
public ImageSource LayerImage => _drawer.GetThumbnail(); public ImageSource LayerImage => _drawer.GetThumbnail();
public bool ConditionsMet<T>(IGameDataModel dataModel) public bool ConditionsMet<T>(IGameDataModel dataModel)
@ -46,15 +44,15 @@ namespace Artemis.Models.Profiles
return LayerConditions.All(cm => cm.ConditionMet<T>(dataModel)); return LayerConditions.All(cm => cm.ConditionMet<T>(dataModel));
} }
public void DrawPreview(Graphics g) public void DrawPreview(DrawingContext c)
{ {
if (LayerType == LayerType.KeyboardRectangle || LayerType == LayerType.KeyboardEllipse) if (LayerType == LayerType.KeyboardRectangle || LayerType == LayerType.KeyboardEllipse)
_drawer.Draw(g); _drawer.Draw(c);
else if (LayerType == LayerType.KeyboardGif) else if (LayerType == LayerType.KeyboardGif)
_drawer.DrawGif(g); _drawer.DrawGif(c);
} }
public void Draw<T>(IGameDataModel dataModel, Graphics g) public void Draw<T>(IGameDataModel dataModel, DrawingContext c)
{ {
if (!ConditionsMet<T>(dataModel)) if (!ConditionsMet<T>(dataModel))
return; return;
@ -62,11 +60,11 @@ namespace Artemis.Models.Profiles
Update<T>(dataModel); Update<T>(dataModel);
if (LayerType == LayerType.Folder) if (LayerType == LayerType.Folder)
DrawChildren<T>(dataModel, g); DrawChildren<T>(dataModel, c);
else if (LayerType == LayerType.KeyboardRectangle || LayerType == LayerType.KeyboardEllipse) else if (LayerType == LayerType.KeyboardRectangle || LayerType == LayerType.KeyboardEllipse)
_drawer.Draw(g); _drawer.Draw(c);
else if (LayerType == LayerType.KeyboardGif) else if (LayerType == LayerType.KeyboardGif)
_drawer.DrawGif(g); _drawer.DrawGif(c);
else if (LayerType == LayerType.Mouse) else if (LayerType == LayerType.Mouse)
_drawer.UpdateMouse(); _drawer.UpdateMouse();
else if (LayerType == LayerType.Headset) else if (LayerType == LayerType.Headset)
@ -80,10 +78,10 @@ namespace Artemis.Models.Profiles
dynamicProperty.ApplyProperty<T>(dataModel, LayerUserProperties, LayerCalculatedProperties); dynamicProperty.ApplyProperty<T>(dataModel, LayerUserProperties, LayerCalculatedProperties);
} }
private void DrawChildren<T>(IGameDataModel dataModel, Graphics g) private void DrawChildren<T>(IGameDataModel dataModel, DrawingContext c)
{ {
foreach (var layerModel in Children) foreach (var layerModel in Children)
layerModel.Draw<T>(dataModel, g); layerModel.Draw<T>(dataModel, c);
} }
} }

View File

@ -1,10 +1,12 @@
using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Windows.Media; using System.Windows.Media;
using System.Drawing.Drawing2D; using System.Xml.Serialization;
namespace Artemis.Models.Profiles namespace Artemis.Models.Profiles
{ {
[XmlInclude(typeof(LinearGradientBrush))]
[XmlInclude(typeof(RadialGradientBrush))]
[XmlInclude(typeof(MatrixTransform))]
public class LayerPropertiesModel public class LayerPropertiesModel
{ {
public int X { get; set; } public int X { get; set; }
@ -16,23 +18,14 @@ namespace Artemis.Models.Profiles
public LayerColorMode ColorMode { get; set; } public LayerColorMode ColorMode { get; set; }
public bool Rotate { get; set; } public bool Rotate { get; set; }
public double RotateSpeed { get; set; } public double RotateSpeed { get; set; }
public List<Color> Colors { get; set; } public Brush Brush { get; set; }
public LayerPropertiesModel()
{
Colors = new List<Color>();
}
} }
public enum LayerColorMode public enum LayerColorMode
{ {
[Description("Left to right")] [Description("Gradient")] Gradient,
Horizontal, [Description("Moving gradient")] MovingGradient,
[Description("Top to bottom")] [Description("Shift")] Shift,
Vertical, [Description("Pulse")] Pulse
[Description("Shift")]
Shift,
[Description("Pulse")]
Pulse,
} }
} }

View File

@ -4,11 +4,9 @@ namespace Artemis.Models.Profiles
{ {
public class ProfileModel public class ProfileModel
{ {
public ProfileModel(string name, string keyboardName, string gameName) public ProfileModel()
{ {
Name = name; Layers = new List<LayerModel>();
KeyboardName = keyboardName;
GameName = gameName;
} }
public string Name { get; set; } public string Name { get; set; }
@ -19,7 +17,8 @@ namespace Artemis.Models.Profiles
protected bool Equals(ProfileModel other) protected bool Equals(ProfileModel other)
{ {
return string.Equals(Name, other.Name) && string.Equals(KeyboardName, other.KeyboardName) && string.Equals(GameName, other.GameName); return string.Equals(Name, other.Name) && string.Equals(KeyboardName, other.KeyboardName) &&
string.Equals(GameName, other.GameName);
} }
public override bool Equals(object obj) public override bool Equals(object obj)

View File

@ -189,7 +189,7 @@
<Popup IsOpen="{Binding ElementName=PART_OpenPopup,Path=IsChecked}" StaysOpen="False" <Popup IsOpen="{Binding ElementName=PART_OpenPopup,Path=IsChecked}" StaysOpen="False"
AllowsTransparency="True" Width="{Binding ActualWidth, ElementName=PART_Root}" AllowsTransparency="True" Width="{Binding ActualWidth, ElementName=PART_Root}"
MinWidth="250" HorizontalOffset="-1" Placement="Center"> MinWidth="250" HorizontalOffset="-1" Placement="Center" PopupAnimation="Fade">
<Border Background="{StaticResource ControlBackgroundBrush}" <Border Background="{StaticResource ControlBackgroundBrush}"
BorderBrush="{StaticResource AccentColorBrush}" BorderThickness="1" BorderBrush="{StaticResource AccentColorBrush}" BorderThickness="1"
Margin="10,0,10,10"> Margin="10,0,10,10">
@ -731,6 +731,4 @@
</Setter.Value> </Setter.Value>
</Setter> </Setter>
</Style> </Style>
</ResourceDictionary> </ResourceDictionary>

View File

@ -1,54 +1,14 @@
using System; using System;
using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging; using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Media.Imaging;
namespace Artemis.Utilities namespace Artemis.Utilities
{ {
internal class ImageUtilities internal class ImageUtilities
{ {
private static Dictionary<string, ImageCodecInfo> encoders;
/// <summary>
/// A lock to prevent concurrency issues loading the encoders.
/// </summary>
private static readonly object encodersLock = new object();
/// <summary>
/// A quick lookup for getting image encoders
/// </summary>
public static Dictionary<string, ImageCodecInfo> Encoders
{
//get accessor that creates the dictionary on demand
get
{
//if the quick lookup isn't initialised, initialise it
if (encoders == null)
{
//protect against concurrency issues
lock (encodersLock)
{
//check again, we might not have been the first person to acquire the lock (see the double checked lock pattern)
if (encoders == null)
{
encoders = new Dictionary<string, ImageCodecInfo>();
//get all the codecs
foreach (var codec in ImageCodecInfo.GetImageEncoders())
{
//add each codec to the quick lookup
encoders.Add(codec.MimeType.ToLower(), codec);
}
}
}
}
//return the lookup
return encoders;
}
}
/// <summary> /// <summary>
/// Resize the image to the specified width and height. /// Resize the image to the specified width and height.
/// </summary> /// </summary>
@ -73,5 +33,29 @@ namespace Artemis.Utilities
//return the resulting bitmap //return the resulting bitmap
return result; return result;
} }
public static Bitmap BitmapSourceToBitmap(BitmapSource srs)
{
var width = srs.PixelWidth;
var height = srs.PixelHeight;
var stride = width * ((srs.Format.BitsPerPixel + 7) / 8);
var ptr = IntPtr.Zero;
try
{
ptr = Marshal.AllocHGlobal(height * stride);
srs.CopyPixels(new Int32Rect(0, 0, width, height), ptr, height * stride, stride);
using (var btm = new Bitmap(width, height, stride, PixelFormat.Format1bppIndexed, ptr))
{
// Clone the bitmap so that we can dispose it and
// release the unmanaged memory at ptr
return new Bitmap(btm);
}
}
finally
{
if (ptr != IntPtr.Zero)
Marshal.FreeHGlobal(ptr);
}
}
} }
} }

View File

@ -1,22 +1,16 @@
using System.Collections.Generic; using System.Windows;
using System.Drawing; using System.Windows.Media;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using Artemis.Models.Profiles; using Artemis.Models.Profiles;
using Artemis.Properties;
namespace Artemis.Utilities namespace Artemis.Utilities
{ {
internal class LayerDrawer internal class LayerDrawer
{ {
private readonly LayerModel _layerModel; private readonly LayerModel _layerModel;
private LinearGradientBrush _brush; private Rect _rectangle;
private Rectangle _rectangle;
private double _rotationProgress; private double _rotationProgress;
private Rectangle _userRectangle; private Rect _userRectangle;
public LayerDrawer(LayerModel layerModel, int scale) public LayerDrawer(LayerModel layerModel, int scale)
{ {
@ -27,22 +21,23 @@ namespace Artemis.Utilities
public int Scale { get; set; } public int Scale { get; set; }
public void Draw(Graphics g) public void Draw(DrawingContext c)
{ {
if (_layerModel.LayerCalculatedProperties.Brush == null)
return;
// Set up variables for this frame // Set up variables for this frame
_rectangle = new Rectangle(_layerModel.LayerCalculatedProperties.X*Scale, _rectangle = new Rect(_layerModel.LayerCalculatedProperties.X*Scale,
_layerModel.LayerCalculatedProperties.Y*Scale, _layerModel.LayerCalculatedProperties.Width*Scale, _layerModel.LayerCalculatedProperties.Y*Scale, _layerModel.LayerCalculatedProperties.Width*Scale,
_layerModel.LayerCalculatedProperties.Height*Scale); _layerModel.LayerCalculatedProperties.Height*Scale);
_userRectangle = new Rectangle(_layerModel.LayerUserProperties.X*Scale, _userRectangle = new Rect(_layerModel.LayerUserProperties.X*Scale,
_layerModel.LayerUserProperties.Y*Scale, _layerModel.LayerUserProperties.Width*Scale, _layerModel.LayerUserProperties.Y*Scale, _layerModel.LayerUserProperties.Width*Scale,
_layerModel.LayerUserProperties.Height*Scale); _layerModel.LayerUserProperties.Height*Scale);
_brush = CreateGradientBrush(
_layerModel.LayerCalculatedProperties.Colors.Select(ColorHelpers.ToDrawingColor).ToList());
if (_layerModel.LayerType == LayerType.KeyboardRectangle) if (_layerModel.LayerType == LayerType.KeyboardRectangle)
DrawRectangle(g); DrawRectangle(c);
else if (_layerModel.LayerType == LayerType.KeyboardEllipse) else if (_layerModel.LayerType == LayerType.KeyboardEllipse)
DrawEllipse(g); DrawEllipse(c);
// Update the rotation progress // Update the rotation progress
_rotationProgress = _rotationProgress + _layerModel.LayerCalculatedProperties.RotateSpeed; _rotationProgress = _rotationProgress + _layerModel.LayerCalculatedProperties.RotateSpeed;
@ -55,133 +50,60 @@ namespace Artemis.Utilities
public BitmapImage GetThumbnail() public BitmapImage GetThumbnail()
{ {
_rectangle = new Rectangle(0, 0, 18, 18); if (_layerModel.LayerUserProperties.Brush == null)
_userRectangle = new Rectangle(0, 0, 18, 18); return null;
_layerModel.LayerCalculatedProperties.Opacity = 255;
var brush =
CreateGradientBrush(_layerModel.LayerUserProperties.Colors.Select(ColorHelpers.ToDrawingColor).ToList());
var bitmap = new Bitmap(18, 18);
using (var g = Graphics.FromImage(bitmap)) _rectangle = new Rect(0, 0, 18, 18);
{ _userRectangle = new Rect(0, 0, 18, 18);
g.SmoothingMode = SmoothingMode.AntiAlias;
if (_layerModel.LayerType == LayerType.KeyboardEllipse) //var bitmap = new Bitmap(18, 18);
{
g.FillEllipse(brush, _rectangle); //using (var g = Graphics.FromImage(bitmap))
g.DrawEllipse(new Pen(Color.Black, 1), 0, 0, 17, 17); //{
} // g.SmoothingMode = SmoothingMode.AntiAlias;
else if (_layerModel.LayerType == LayerType.KeyboardRectangle) // if (_layerModel.LayerType == LayerType.KeyboardEllipse)
{ // {
g.FillRectangle(brush, _rectangle); // g.FillEllipse(_layerModel.LayerUserProperties.Brush, _rectangle);
g.DrawRectangle(new Pen(Color.Black, 1), 0, 0, 17, 17); // g.DrawEllipse(new Pen(Color.Black, 1), 0, 0, 17, 17);
} // }
else // else if (_layerModel.LayerType == LayerType.KeyboardRectangle)
bitmap = Resources.folder; // {
// 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;
} }
using (var memory = new MemoryStream()) public void DrawRectangle(DrawingContext c)
{ {
bitmap.Save(memory, ImageFormat.Png); c.DrawRectangle(_layerModel.LayerCalculatedProperties.Brush, null, _rectangle);
memory.Position = 0;
var bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.StreamSource = memory;
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.EndInit();
return bitmapImage;
}
} }
public void DrawRectangle(Graphics g) public void DrawEllipse(DrawingContext c)
{ {
g.FillRectangle(_brush, _rectangle); c.DrawEllipse(_layerModel.LayerCalculatedProperties.Brush, null,
new Point(_rectangle.Width/2, _rectangle.Height/2), _rectangle.Width, _rectangle.Height);
} }
public void DrawEllipse(Graphics g) public void DrawGif(DrawingContext bmp)
{ {
g.FillEllipse(_brush, _rectangle);
}
public void DrawGif(Graphics g)
{
}
private LinearGradientBrush CreateGradientBrush(List<Color> colors)
{
ColorBlend colorBlend;
var props = _layerModel.LayerCalculatedProperties;
// Create a ColorBlend
if (colors.Count == 0)
{
colorBlend = new ColorBlend
{
Colors = new[] {Color.Transparent, Color.Transparent},
Positions = new[] {0F, 1F}
};
}
else if (colors.Count == 1)
{
colorBlend = new ColorBlend
{
Colors = new[] {colors[0], colors[0]},
Positions = new[] {0F, 1F}
};
}
else
{
colorBlend = props.Rotate
? new ColorBlend {Colors = CreateTilebleColors(colors).ToArray()}
: new ColorBlend {Colors = colors.ToArray()};
}
// If needed, apply opacity to the colors in the blend
if (props.Opacity < 255)
for (var i = 0; i < colorBlend.Colors.Length; i++)
colorBlend.Colors[i] = Color.FromArgb(props.Opacity, colorBlend.Colors[i]);
// Devide the colors over the colorblend
var devider = (float) colorBlend.Colors.Length - 1;
var positions = new List<float>();
for (var i = 0; i < colorBlend.Colors.Length; i++)
positions.Add(i/devider);
// Apply the devided positions
colorBlend.Positions = positions.ToArray();
RectangleF rect;
if (props.Rotate)
rect = _layerModel.LayerCalculatedProperties.ContainedBrush
? new Rectangle((int) _rotationProgress + _rectangle.X, _rectangle.Y, _rectangle.Width*2,
_rectangle.Height*2)
: new Rectangle((int) _rotationProgress + _userRectangle.X, _userRectangle.Y, _userRectangle.Width*2,
_userRectangle.Height*2);
else
rect = _layerModel.LayerCalculatedProperties.ContainedBrush
? new Rectangle(_rectangle.X, _rectangle.Y, _rectangle.Width, _rectangle.Height)
: new Rectangle(_userRectangle.X, _userRectangle.Y, _userRectangle.Width, _userRectangle.Height);
if (_layerModel.LayerCalculatedProperties.ColorMode == LayerColorMode.Horizontal)
return new LinearGradientBrush(rect, Color.Transparent, Color.Transparent, LinearGradientMode.Horizontal)
{
InterpolationColors = colorBlend
};
return new LinearGradientBrush(rect, Color.Transparent, Color.Transparent, LinearGradientMode.Vertical)
{
InterpolationColors = colorBlend
};
}
private List<Color> CreateTilebleColors(List<Color> sourceColors)
{
// Create a list using the original colors
var tilebleColors = new List<Color>(sourceColors);
// Add the original colors again
tilebleColors.AddRange(sourceColors);
// Add the first color, smoothing the transition
tilebleColors.Add(sourceColors.FirstOrDefault());
return tilebleColors;
} }
public void UpdateMouse() public void UpdateMouse()

View File

@ -1,35 +1,33 @@
using System; using System;
using System.Collections.Specialized;
using System.ComponentModel; using System.ComponentModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Windows;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using Artemis.DAL;
using Artemis.Models.Profiles; using Artemis.Models.Profiles;
using Artemis.Utilities; using Artemis.Utilities;
using Artemis.ViewModels.LayerEditor; using Artemis.ViewModels.LayerEditor;
using Caliburn.Micro; using Caliburn.Micro;
using Color = System.Windows.Media.Color;
namespace Artemis.ViewModels namespace Artemis.ViewModels
{ {
public class LayerEditorViewModel<T> : Screen public class LayerEditorViewModel<T> : Screen
{ {
private readonly ProfileModel _profile;
private readonly BackgroundWorker _previewWorker; private readonly BackgroundWorker _previewWorker;
private LayerModel _layer; private LayerModel _layer;
private LayerPropertiesModel _proposedProperties; private LayerPropertiesModel _proposedProperties;
public LayerEditorViewModel(LayerModel layer) public LayerEditorViewModel(ProfileModel profile, LayerModel layer)
{ {
_profile = profile;
Layer = layer; Layer = layer;
DataModelProps = new BindableCollection<GeneralHelpers.PropertyCollection>(); DataModelProps = new BindableCollection<GeneralHelpers.PropertyCollection>();
ProposedColors = new BindableCollection<Color>();
ProposedProperties = new LayerPropertiesModel(); ProposedProperties = new LayerPropertiesModel();
ProposedColors.CollectionChanged += UpdateColors;
DataModelProps.AddRange(GeneralHelpers.GenerateTypeMap<T>()); DataModelProps.AddRange(GeneralHelpers.GenerateTypeMap<T>());
LayerConditionVms = LayerConditionVms =
@ -39,8 +37,8 @@ namespace Artemis.ViewModels
_previewWorker = new BackgroundWorker(); _previewWorker = new BackgroundWorker();
_previewWorker.WorkerSupportsCancellation = true; _previewWorker.WorkerSupportsCancellation = true;
_previewWorker.DoWork += PreviewWorkerOnDoWork; _previewWorker.DoWork += PreviewWorkerOnDoWork;
_previewWorker.RunWorkerAsync(); _previewWorker.RunWorkerAsync();
PreSelect(); PreSelect();
} }
@ -48,8 +46,6 @@ namespace Artemis.ViewModels
public BindableCollection<string> LayerTypes => new BindableCollection<string>(); public BindableCollection<string> LayerTypes => new BindableCollection<string>();
public BindableCollection<Color> ProposedColors { get; set; }
public BindableCollection<LayerConditionViewModel<T>> LayerConditionVms { get; set; } public BindableCollection<LayerConditionViewModel<T>> LayerConditionVms { get; set; }
public LayerModel Layer public LayerModel Layer
@ -80,34 +76,28 @@ namespace Artemis.ViewModels
{ {
// For the preview, put the proposed properties into the calculated properties // For the preview, put the proposed properties into the calculated properties
_layer.LayerCalculatedProperties = ProposedProperties; _layer.LayerCalculatedProperties = ProposedProperties;
var bitmap = new Bitmap(ProposedProperties.Width*4, ProposedProperties.Height*4);
using (var g = Graphics.FromImage(bitmap)) var visual = new DrawingVisual();
using (var drawingContext = visual.RenderOpen())
{ {
_layer.DrawPreview(g); // TODO: Get active keyboard's size * 4
} var keyboardRect = new Rect(new Size(280, 105));
using (var memory = new MemoryStream()) // Setup the DrawingVisual's size
{ drawingContext.PushClip(new RectangleGeometry(keyboardRect));
bitmap.Save(memory, ImageFormat.Png); drawingContext.DrawRectangle(new SolidColorBrush(Color.FromArgb(0, 0, 0, 0)), null, keyboardRect);
memory.Position = 0;
var bitmapImage = new BitmapImage(); // Draw the layer
bitmapImage.BeginInit(); _layer.DrawPreview(drawingContext);
bitmapImage.StreamSource = memory;
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.EndInit();
return bitmapImage; // Remove the clip
drawingContext.Pop();
} }
var image = new DrawingImage(visual.Drawing);
return image;
} }
} }
private void UpdateColors(object sender, NotifyCollectionChangedEventArgs e)
{
ProposedProperties.Colors = ProposedColors.ToList();
}
private void PreviewWorkerOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs) private void PreviewWorkerOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs)
{ {
while (!_previewWorker.CancellationPending) while (!_previewWorker.CancellationPending)
@ -117,11 +107,9 @@ namespace Artemis.ViewModels
} }
} }
private void PreSelect() public void PreSelect()
{ {
GeneralHelpers.CopyProperties(ProposedProperties, Layer.LayerUserProperties); GeneralHelpers.CopyProperties(ProposedProperties, Layer.LayerUserProperties);
ProposedColors.Clear();
ProposedColors.AddRange(ProposedProperties.Colors);
} }
public void AddCondition() public void AddCondition()
@ -131,19 +119,10 @@ namespace Artemis.ViewModels
LayerConditionVms.Add(new LayerConditionViewModel<T>(this, condition, DataModelProps)); LayerConditionVms.Add(new LayerConditionViewModel<T>(this, condition, DataModelProps));
} }
public void AddColor()
{
ProposedColors.Add(ColorHelpers.ToMediaColor(ColorHelpers.GetRandomRainbowColor()));
}
public void DeleteColor(Color c)
{
ProposedColors.Remove(c);
}
public void Apply() public void Apply()
{ {
GeneralHelpers.CopyProperties(Layer.LayerUserProperties, ProposedProperties); GeneralHelpers.CopyProperties(Layer.LayerUserProperties, ProposedProperties);
ProfileProvider.AddOrUpdate(_profile);
} }
public void DeleteCondition(LayerConditionViewModel<T> layerConditionViewModel, public void DeleteCondition(LayerConditionViewModel<T> layerConditionViewModel,

View File

@ -13,9 +13,9 @@ namespace Artemis.ViewModels
{ {
private readonly GameModel _gameModel; private readonly GameModel _gameModel;
private readonly MainManager _mainManager; private readonly MainManager _mainManager;
private LayerEditorViewModel<T> _editorVm;
private BindableCollection<ProfileModel> _profileModels; private BindableCollection<ProfileModel> _profileModels;
private ProfileModel _selectedProfileModel; private ProfileModel _selectedProfileModel;
private LayerEditorViewModel<T> _editorVm;
public ProfileEditorViewModel(MainManager mainManager, GameModel gameModel) public ProfileEditorViewModel(MainManager mainManager, GameModel gameModel)
{ {
@ -48,6 +48,8 @@ namespace Artemis.ViewModels
} }
} }
public LayerModel SelectedLayer { get; set; }
private void LoadProfiles() private void LoadProfiles()
{ {
ProfileModels.Clear(); ProfileModels.Clear();
@ -67,7 +69,12 @@ namespace Artemis.ViewModels
return; return;
} }
var profile = new ProfileModel(name, _mainManager.KeyboardManager.ActiveKeyboard.Name, _gameModel.Name); var profile = new ProfileModel
{
Name = name,
KeyboardName = _mainManager.KeyboardManager.ActiveKeyboard.Name,
GameName = _gameModel.Name
};
if (ProfileProvider.GetAll().Contains(profile)) if (ProfileProvider.GetAll().Contains(profile))
{ {
var overwrite = var overwrite =
@ -87,13 +94,28 @@ 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>(layer); _editorVm = new LayerEditorViewModel<T>(SelectedProfileModel, layer);
dynamic settings = new ExpandoObject(); dynamic settings = new ExpandoObject();
settings.Title = "Artemis | Edit " + layer.Name; settings.Title = "Artemis | Edit " + layer.Name;
manager.ShowDialog(_editorVm, null, settings); manager.ShowDialog(_editorVm, null, settings);
} }
public void SetSelectedLayer(LayerModel layer)
{
SelectedLayer = layer;
}
public void AddLayer()
{
_selectedProfileModel.Layers.Add(new LayerModel
{
Name = "Layer " + (_selectedProfileModel.Layers.Count + 1),
LayerType = LayerType.KeyboardRectangle
});
NotifyOfPropertyChange();
}
private ImageSource GenerateKeyboardImage() private ImageSource GenerateKeyboardImage()
{ {
return null; return null;

View File

@ -169,59 +169,25 @@
</ComboBox> </ComboBox>
<!-- Colors --> <!-- Colors -->
<TextBlock Grid.Row="10" Grid.Column="2" Margin="10,13,10,0" FontSize="13.333" Text="Colors:" <TextBlock Grid.Row="10" Grid.Column="2" Margin="10,13,10,0" FontSize="13.333" Text="Color(s):"
VerticalAlignment="Top" Height="18" /> VerticalAlignment="Top" Height="18" />
<StackPanel Grid.Row="10" Grid.Column="3" Grid.RowSpan="2"> <Border Grid.Row="10" Grid.Column="3" Margin="10" BorderThickness="1" BorderBrush="{StaticResource ControlBorderBrush}" ToolTip="Click to edit">
<ncore:ColorBox Width="100" Height="25"></ncore:ColorBox> <ncore:ColorBox Brush="{Binding Path=ProposedProperties.Brush, Mode=TwoWay}" />
<!--<Border BorderThickness="1" BorderBrush="{StaticResource GrayBrush7}" Margin="10"> </Border>
<ListBox Height="108" ItemsSource="{Binding Path=ProposedColors}"
ScrollViewer.VerticalScrollBarVisibility="Visible" VerticalAlignment="Top">
<ListBox.Template>
<ControlTemplate>
<ScrollViewer>
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</ListBox.Template>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<xctk:ColorPicker SelectedColor="{Binding Path=.}"
VerticalAlignment="Center" Width="100" Height="26"/>
<Button x:Name="Delete" Width="26" Height="26"
Style="{DynamicResource SquareButtonStyle}"
VerticalAlignment="Top" HorizontalAlignment="Right" Margin="5,5,0,5"
cal:Message.Attach="DeleteColor($datacontext)">
<Button.Content>
<Rectangle Fill="Black" Width="12" Height="12">
<Rectangle.OpacityMask>
<VisualBrush Visual="{StaticResource appbar_delete}" Stretch="Fill" />
</Rectangle.OpacityMask>
</Rectangle>
</Button.Content>
</Button>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Border>-->
<Button x:Name="AddColor" Content="Add color"
VerticalAlignment="Center"
Style="{DynamicResource SquareButtonStyle}" Width="95" HorizontalAlignment="Right" Height="30"
Margin="10,0,10,10" ScrollViewer.VerticalScrollBarVisibility="Auto" />
</StackPanel>
<!-- Preview --> <!-- Preview -->
<TextBlock Grid.Row="11" Grid.Column="0" Margin="10,13,10,0" FontSize="13.333" Text="Preview:" <TextBlock Grid.Row="11" Grid.Column="0" Margin="10,13,10,0" FontSize="13.333" Text="Preview:"
VerticalAlignment="Top" Height="18" /> VerticalAlignment="Top" Height="18" />
<Border Grid.Row="11" Grid.Column="1" Grid.ColumnSpan="2" Margin="10" BorderThickness="1" <Border Grid.Row="11" Grid.Column="1" Grid.ColumnSpan="2" Margin="10" BorderThickness="1"
BorderBrush="{StaticResource GrayBrush7}" Width="280" Height="105"> BorderBrush="{StaticResource ControlBorderBrush}" Width="280" Height="105">
<Image Source="{Binding LayerImage}" Stretch="Uniform" /> <Image Source="{Binding LayerImage}" />
</Border> </Border>
<Button Grid.Row="12" Grid.Column="0" x:Name="Apply" Content="Apply" VerticalAlignment="Bottom" <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" Style="{DynamicResource SquareButtonStyle}" Width="95" HorizontalAlignment="Left" Margin="10,0,0,20"
Height="30" /> 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> </Grid>
</controls:MetroWindow> </controls:MetroWindow>

View File

@ -12,6 +12,7 @@ using System.Windows.Media;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using System.Windows.Shapes; using System.Windows.Shapes;
using MahApps.Metro.Controls; using MahApps.Metro.Controls;
using ColorBox;
namespace Artemis.Views namespace Artemis.Views
{ {

View File

@ -59,7 +59,7 @@
</TreeView.Resources> </TreeView.Resources>
<TreeView.ItemTemplate> <TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}"> <HierarchicalDataTemplate ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal" Tag="{Binding DataContext, ElementName=ProfileTree}"> <StackPanel Orientation="Horizontal" Tag="{Binding DataContext, ElementName=ProfileTree}" cal:Message.Attach="SetSelectedLayer($datacontext)">
<StackPanel.ContextMenu> <StackPanel.ContextMenu>
<ContextMenu cal:Action.TargetWithoutContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}"> <ContextMenu cal:Action.TargetWithoutContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Rename" /> <MenuItem Header="Rename" />