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

Fully implemented layer dragging and resizing

This commit is contained in:
SpoinkyNL 2016-04-15 13:30:34 +02:00
parent e78906bfa3
commit 8aeee846b4
13 changed files with 347 additions and 83 deletions

View File

@ -271,6 +271,7 @@
<Compile Include="Events\ToggleEnabled.cs" /> <Compile Include="Events\ToggleEnabled.cs" />
<Compile Include="Events\ActiveEffectChanged.cs" /> <Compile Include="Events\ActiveEffectChanged.cs" />
<Compile Include="Events\ChangeBitmap.cs" /> <Compile Include="Events\ChangeBitmap.cs" />
<Compile Include="ItemBehaviours\BindableSelectedItemBehavior.cs" />
<Compile Include="KeyboardProviders\Corsair\CorsairRGB.cs" /> <Compile Include="KeyboardProviders\Corsair\CorsairRGB.cs" />
<Compile Include="KeyboardProviders\KeyboardProvider.cs" /> <Compile Include="KeyboardProviders\KeyboardProvider.cs" />
<Compile Include="KeyboardProviders\KeyboardRegion.cs" /> <Compile Include="KeyboardProviders\KeyboardRegion.cs" />
@ -551,6 +552,7 @@
<Resource Include="Resources\Keyboards\k70.png" /> <Resource Include="Resources\Keyboards\k70.png" />
<Resource Include="Resources\Keyboards\k95.png" /> <Resource Include="Resources\Keyboards\k95.png" />
<Resource Include="Resources\Keyboards\strafe.png" /> <Resource Include="Resources\Keyboards\strafe.png" />
<Resource Include="Resources\Keyboards\g910.png" />
<Content Include="Resources\Witcher3\playerWitcher.txt" /> <Content Include="Resources\Witcher3\playerWitcher.txt" />
<Content Include="Resources\Witcher3\artemis.txt" /> <Content Include="Resources\Witcher3\artemis.txt" />
<Resource Include="Resources\Entypo.ttf" /> <Resource Include="Resources\Entypo.ttf" />

View File

@ -0,0 +1,52 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;
namespace Artemis.ItemBehaviours
{
/// <summary>
/// Steve Greatrex - http://stackoverflow.com/a/5118406/5015269
/// </summary>
public class BindableSelectedItemBehavior : Behavior<TreeView>
{
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.SelectedItemChanged += OnTreeViewSelectedItemChanged;
}
protected override void OnDetaching()
{
base.OnDetaching();
if (AssociatedObject != null)
AssociatedObject.SelectedItemChanged -= OnTreeViewSelectedItemChanged;
}
private void OnTreeViewSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
SelectedItem = e.NewValue;
}
#region SelectedItem Property
public object SelectedItem
{
get { return GetValue(SelectedItemProperty); }
set { SetValue(SelectedItemProperty, value); }
}
public static readonly DependencyProperty SelectedItemProperty =
DependencyProperty.Register("SelectedItem", typeof (object), typeof (BindableSelectedItemBehavior),
new UIPropertyMetadata(null, OnSelectedItemChanged));
private static void OnSelectedItemChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
var item = e.NewValue as TreeViewItem;
item?.SetValue(TreeViewItem.IsSelectedProperty, true);
}
#endregion
}
}

View File

@ -3,6 +3,7 @@ using System.Drawing;
using System.Threading; using System.Threading;
using System.Windows; using System.Windows;
using Artemis.KeyboardProviders.Logitech.Utilities; using Artemis.KeyboardProviders.Logitech.Utilities;
using Artemis.Properties;
using Artemis.Utilities; using Artemis.Utilities;
using Artemis.Utilities.LogitechDll; using Artemis.Utilities.LogitechDll;
using Point = System.Drawing.Point; using Point = System.Drawing.Point;
@ -20,6 +21,7 @@ namespace Artemis.KeyboardProviders.Logitech
"If needed, you can select a different keyboard in Artemis under settings."; "If needed, you can select a different keyboard in Artemis under settings.";
Height = 6; Height = 6;
Width = 21; Width = 21;
PreviewSettings = new PreviewSettings(626, 175, new Thickness(0, -15, 0, 0), Resources.g910);
KeyboardRegions = new List<KeyboardRegion> KeyboardRegions = new List<KeyboardRegion>
{ {
new KeyboardRegion("TopRow", new Point(0, 0), new Point(18, 0)), new KeyboardRegion("TopRow", new Point(0, 0), new Point(18, 0)),

View File

@ -11,30 +11,32 @@ namespace Artemis.Models.Profiles
public class LayerModel public class LayerModel
{ {
[XmlIgnore] private readonly LayerDrawer _drawer; [XmlIgnore] private readonly LayerDrawer _drawer;
private bool _mustDraw;
public LayerModel() public LayerModel()
{ {
LayerUserProperties = new LayerPropertiesModel(); UserProps = new LayerPropertiesModel();
LayerCalculatedProperties = new LayerPropertiesModel(); CalcProps = new LayerPropertiesModel();
Children = new List<LayerModel>(); Children = new List<LayerModel>();
LayerConditions = new List<LayerConditionModel>(); LayerConditions = new List<LayerConditionModel>();
LayerProperties = new List<LayerDynamicPropertiesModel>(); LayerProperties = new List<LayerDynamicPropertiesModel>();
_mustDraw = true;
_drawer = new LayerDrawer(this, 4); _drawer = new LayerDrawer(this, 4);
} }
public string Name { get; set; } public string Name { get; set; }
public LayerType LayerType { get; set; } public LayerType LayerType { get; set; }
public bool Enabled { get; set; } public bool Enabled { get; set; }
public LayerPropertiesModel LayerUserProperties { get; set; } public LayerPropertiesModel UserProps { get; set; }
public List<LayerModel> Children { get; set; } public List<LayerModel> Children { get; set; }
public List<LayerConditionModel> LayerConditions { get; set; } public List<LayerConditionModel> LayerConditions { get; set; }
public List<LayerDynamicPropertiesModel> LayerProperties { get; set; } public List<LayerDynamicPropertiesModel> LayerProperties { get; set; }
[XmlIgnore] [XmlIgnore]
public LayerPropertiesModel LayerCalculatedProperties { get; set; } public LayerPropertiesModel CalcProps { get; set; }
[XmlIgnore] [XmlIgnore]
public ImageSource LayerImage => _drawer.GetThumbnail(); public ImageSource LayerImage => _drawer.GetThumbnail();
@ -46,11 +48,12 @@ namespace Artemis.Models.Profiles
public void DrawPreview(DrawingContext c) public void DrawPreview(DrawingContext c)
{ {
GeneralHelpers.CopyProperties(LayerCalculatedProperties, LayerUserProperties); GeneralHelpers.CopyProperties(CalcProps, UserProps);
if (LayerType == LayerType.KeyboardRectangle || LayerType == LayerType.KeyboardEllipse) if (LayerType == LayerType.KeyboardRectangle || LayerType == LayerType.KeyboardEllipse)
_drawer.Draw(c); _drawer.Draw(c, _mustDraw);
else if (LayerType == LayerType.KeyboardGif) else if (LayerType == LayerType.KeyboardGif)
_drawer.DrawGif(c); _drawer.DrawGif(c);
_mustDraw = false;
} }
public void Draw<T>(IGameDataModel dataModel, DrawingContext c) public void Draw<T>(IGameDataModel dataModel, DrawingContext c)
@ -80,9 +83,9 @@ namespace Artemis.Models.Profiles
return; return;
} }
GeneralHelpers.CopyProperties(LayerCalculatedProperties, LayerUserProperties); GeneralHelpers.CopyProperties(CalcProps, UserProps);
foreach (var dynamicProperty in LayerProperties) foreach (var dynamicProperty in LayerProperties)
dynamicProperty.ApplyProperty<T>(dataModel, LayerUserProperties, LayerCalculatedProperties); dynamicProperty.ApplyProperty<T>(dataModel, UserProps, CalcProps);
} }
} }

View File

@ -1,9 +1,11 @@
using System.ComponentModel; using System.ComponentModel;
using System.Windows;
using System.Windows.Media; using System.Windows.Media;
using System.Xml.Serialization; using System.Xml.Serialization;
namespace Artemis.Models.Profiles namespace Artemis.Models.Profiles
{ {
[XmlInclude(typeof (SolidColorBrush))]
[XmlInclude(typeof (LinearGradientBrush))] [XmlInclude(typeof (LinearGradientBrush))]
[XmlInclude(typeof (RadialGradientBrush))] [XmlInclude(typeof (RadialGradientBrush))]
[XmlInclude(typeof (MatrixTransform))] [XmlInclude(typeof (MatrixTransform))]
@ -18,8 +20,14 @@ namespace Artemis.Models.Profiles
public LayerAnimation Animation { get; set; } public LayerAnimation Animation { get; set; }
public double AnimationSpeed { get; set; } public double AnimationSpeed { get; set; }
public Brush Brush { get; set; } public Brush Brush { get; set; }
public Rect GetRect(int scale = 4)
{
return new Rect(X*scale, Y*scale, Width*scale, Height*scale);
}
} }
public enum LayerAnimation public enum LayerAnimation
{ {
[Description("None")] None, [Description("None")] None,

View File

@ -23,7 +23,7 @@ namespace Artemis.Modules.Games.CounterStrike
ProfileEditor = new ProfileEditorViewModel<CounterStrikeDataModel>(MainManager, GameModel); ProfileEditor = new ProfileEditorViewModel<CounterStrikeDataModel>(MainManager, GameModel);
GameModel.Profile = ProfileEditor.SelectedProfileModel; GameModel.Profile = ProfileEditor.SelectedProfile;
} }
public ProfileEditorViewModel<CounterStrikeDataModel> ProfileEditor { get; set; } public ProfileEditorViewModel<CounterStrikeDataModel> ProfileEditor { get; set; }

View File

@ -145,6 +145,16 @@ namespace Artemis.Properties {
} }
} }
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap g910 {
get {
object obj = ResourceManager.GetObject("g910", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary> /// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap. /// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary> /// </summary>

View File

@ -157,4 +157,7 @@
<data name="strafe" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="strafe" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\resources\keyboards\strafe.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\resources\keyboards\strafe.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
<data name="g910" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Keyboards\g910.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root> </root>

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 KiB

View File

@ -23,22 +23,25 @@ namespace Artemis.Utilities
public int Scale { get; set; } public int Scale { get; set; }
public void Draw(DrawingContext c) public void Draw(DrawingContext c, bool update = true)
{ {
if (_layerModel.LayerCalculatedProperties.Brush == null) if (_layerModel.CalcProps.Brush == null || !_layerModel.Enabled)
return; return;
if (!update)
_layerModel.CalcProps.Animation = LayerAnimation.None;
UpdateAnimation(); UpdateAnimation();
// Set up variables for this frame // Set up variables for this frame
_rectangle = new Rect(_layerModel.LayerCalculatedProperties.X*Scale, _rectangle = new Rect(_layerModel.CalcProps.X*Scale,
_layerModel.LayerCalculatedProperties.Y*Scale, _layerModel.LayerCalculatedProperties.Width*Scale, _layerModel.CalcProps.Y*Scale, _layerModel.CalcProps.Width*Scale,
_layerModel.LayerCalculatedProperties.Height*Scale); _layerModel.CalcProps.Height*Scale);
if (_layerModel.LayerType == LayerType.KeyboardRectangle) if (_layerModel.LayerType == LayerType.KeyboardRectangle)
_layerModel.LayerCalculatedProperties.Brush.Dispatcher.Invoke(() => DrawRectangle(c)); _layerModel.CalcProps.Brush.Dispatcher.Invoke(() => DrawRectangle(c));
else if (_layerModel.LayerType == LayerType.KeyboardEllipse) else if (_layerModel.LayerType == LayerType.KeyboardEllipse)
_layerModel.LayerCalculatedProperties.Brush.Dispatcher.Invoke(() => DrawEllipse(c)); _layerModel.CalcProps.Brush.Dispatcher.Invoke(() => DrawEllipse(c));
} }
private void UpdateAnimation() private void UpdateAnimation()
@ -47,73 +50,73 @@ namespace Artemis.Utilities
return; return;
// Slide right animation // Slide right animation
if (_layerModel.LayerCalculatedProperties.Animation == LayerAnimation.SlideRight) if (_layerModel.CalcProps.Animation == LayerAnimation.SlideRight)
{ {
_firstRect = new Rect(new Point(_rectangle.X + _animationProgress, _rectangle.Y), _firstRect = new Rect(new Point(_rectangle.X + _animationProgress, _rectangle.Y),
new Size(_rectangle.Width, _rectangle.Height)); new Size(_rectangle.Width, _rectangle.Height));
_secondRect = new Rect(new Point(_firstRect.X - _rectangle.Width, _rectangle.Y), _secondRect = new Rect(new Point(_firstRect.X - _rectangle.Width, _rectangle.Y),
new Size(_rectangle.Width + 1, _rectangle.Height)); new Size(_rectangle.Width + 1, _rectangle.Height));
if (_animationProgress > _layerModel.LayerCalculatedProperties.Width*4) if (_animationProgress > _layerModel.CalcProps.Width*4)
_animationProgress = 0; _animationProgress = 0;
} }
// Slide left animation // Slide left animation
if (_layerModel.LayerCalculatedProperties.Animation == LayerAnimation.SlideLeft) if (_layerModel.CalcProps.Animation == LayerAnimation.SlideLeft)
{ {
_firstRect = new Rect(new Point(_rectangle.X - _animationProgress, _rectangle.Y), _firstRect = new Rect(new Point(_rectangle.X - _animationProgress, _rectangle.Y),
new Size(_rectangle.Width + 1, _rectangle.Height)); new Size(_rectangle.Width + 1, _rectangle.Height));
_secondRect = new Rect(new Point(_firstRect.X + _rectangle.Width, _rectangle.Y), _secondRect = new Rect(new Point(_firstRect.X + _rectangle.Width, _rectangle.Y),
new Size(_rectangle.Width, _rectangle.Height)); new Size(_rectangle.Width, _rectangle.Height));
if (_animationProgress > _layerModel.LayerCalculatedProperties.Width*4) if (_animationProgress > _layerModel.CalcProps.Width*4)
_animationProgress = 0; _animationProgress = 0;
} }
// Slide down animation // Slide down animation
if (_layerModel.LayerCalculatedProperties.Animation == LayerAnimation.SlideDown) if (_layerModel.CalcProps.Animation == LayerAnimation.SlideDown)
{ {
_firstRect = new Rect(new Point(_rectangle.X, _rectangle.Y + _animationProgress), _firstRect = new Rect(new Point(_rectangle.X, _rectangle.Y + _animationProgress),
new Size(_rectangle.Width, _rectangle.Height)); new Size(_rectangle.Width, _rectangle.Height));
_secondRect = new Rect(new Point(_firstRect.X, _firstRect.Y - _rectangle.Height), _secondRect = new Rect(new Point(_firstRect.X, _firstRect.Y - _rectangle.Height),
new Size(_rectangle.Width, _rectangle.Height)); new Size(_rectangle.Width, _rectangle.Height));
if (_animationProgress > _layerModel.LayerCalculatedProperties.Height*4) if (_animationProgress > _layerModel.CalcProps.Height*4)
_animationProgress = 0; _animationProgress = 0;
} }
// Slide up animation // Slide up animation
if (_layerModel.LayerCalculatedProperties.Animation == LayerAnimation.SlideUp) if (_layerModel.CalcProps.Animation == LayerAnimation.SlideUp)
{ {
_firstRect = new Rect(new Point(_rectangle.X, _rectangle.Y - _animationProgress), _firstRect = new Rect(new Point(_rectangle.X, _rectangle.Y - _animationProgress),
new Size(_rectangle.Width, _rectangle.Height)); new Size(_rectangle.Width, _rectangle.Height));
_secondRect = new Rect(new Point(_firstRect.X, _firstRect.Y + _rectangle.Height), _secondRect = new Rect(new Point(_firstRect.X, _firstRect.Y + _rectangle.Height),
new Size(_rectangle.Width, _rectangle.Height)); new Size(_rectangle.Width, _rectangle.Height));
if (_animationProgress > _layerModel.LayerCalculatedProperties.Height*4) if (_animationProgress > _layerModel.CalcProps.Height*4)
_animationProgress = 0; _animationProgress = 0;
} }
// Pulse animation // Pulse animation
if (_layerModel.LayerCalculatedProperties.Animation == LayerAnimation.Pulse) if (_layerModel.CalcProps.Animation == LayerAnimation.Pulse)
{ {
var opac = (Math.Sin(_animationProgress*Math.PI) + 1)*(_layerModel.LayerUserProperties.Opacity/2); var opac = (Math.Sin(_animationProgress*Math.PI) + 1)*(_layerModel.UserProps.Opacity/2);
_layerModel.LayerCalculatedProperties.Opacity = opac; _layerModel.CalcProps.Opacity = opac;
if (_animationProgress > 2) if (_animationProgress > 2)
_animationProgress = 0; _animationProgress = 0;
_animationProgress = _animationProgress + _layerModel.LayerCalculatedProperties.AnimationSpeed/2; _animationProgress = _animationProgress + _layerModel.CalcProps.AnimationSpeed/2;
} }
else else
{ {
// Update the animation progress // Update the animation progress
_animationProgress = _animationProgress + _layerModel.LayerCalculatedProperties.AnimationSpeed; _animationProgress = _animationProgress + _layerModel.CalcProps.AnimationSpeed;
} }
} }
public BitmapImage GetThumbnail() public BitmapImage GetThumbnail()
{ {
if (_layerModel.LayerUserProperties.Brush == null) if (_layerModel.UserProps.Brush == null)
return null; return null;
_rectangle = new Rect(0, 0, 18, 18); _rectangle = new Rect(0, 0, 18, 18);
@ -155,14 +158,13 @@ namespace Artemis.Utilities
public void DrawRectangle(DrawingContext c) public void DrawRectangle(DrawingContext c)
{ {
//_layerModel.LayerCalculatedProperties.Brush.Opacity = _layerModel.LayerCalculatedProperties.Opacity; var brush = _layerModel.CalcProps.Brush.CloneCurrentValue();
var brush = _layerModel.LayerCalculatedProperties.Brush.CloneCurrentValue(); brush.Opacity = _layerModel.CalcProps.Opacity;
brush.Opacity = _layerModel.LayerCalculatedProperties.Opacity;
if (_layerModel.LayerCalculatedProperties.Animation == LayerAnimation.SlideDown || if (_layerModel.CalcProps.Animation == LayerAnimation.SlideDown ||
_layerModel.LayerCalculatedProperties.Animation == LayerAnimation.SlideLeft || _layerModel.CalcProps.Animation == LayerAnimation.SlideLeft ||
_layerModel.LayerCalculatedProperties.Animation == LayerAnimation.SlideRight || _layerModel.CalcProps.Animation == LayerAnimation.SlideRight ||
_layerModel.LayerCalculatedProperties.Animation == LayerAnimation.SlideUp) _layerModel.CalcProps.Animation == LayerAnimation.SlideUp)
{ {
c.PushClip(new RectangleGeometry(_rectangle)); c.PushClip(new RectangleGeometry(_rectangle));
c.DrawRectangle(brush, null, _firstRect); c.DrawRectangle(brush, null, _firstRect);
@ -177,7 +179,7 @@ namespace Artemis.Utilities
public void DrawEllipse(DrawingContext c) public void DrawEllipse(DrawingContext c)
{ {
c.DrawEllipse(_layerModel.LayerCalculatedProperties.Brush, null, c.DrawEllipse(_layerModel.CalcProps.Brush, null,
new Point(_rectangle.Width/2, _rectangle.Height/2), _rectangle.Width, _rectangle.Height); new Point(_rectangle.Width/2, _rectangle.Height/2), _rectangle.Width, _rectangle.Height);
} }

View File

@ -110,7 +110,7 @@ namespace Artemis.ViewModels
public void PreSelect() public void PreSelect()
{ {
GeneralHelpers.CopyProperties(ProposedProperties, Layer.LayerUserProperties); GeneralHelpers.CopyProperties(ProposedProperties, Layer.UserProps);
} }
private void AnimationUiHandler(object sender, PropertyChangedEventArgs e) private void AnimationUiHandler(object sender, PropertyChangedEventArgs e)
@ -128,7 +128,7 @@ namespace Artemis.ViewModels
public void Apply() public void Apply()
{ {
GeneralHelpers.CopyProperties(Layer.LayerUserProperties, ProposedProperties); GeneralHelpers.CopyProperties(Layer.UserProps, ProposedProperties);
ProfileProvider.AddOrUpdate(_profile); ProfileProvider.AddOrUpdate(_profile);
} }

View File

@ -1,4 +1,5 @@
using System; using System;
using System.ComponentModel;
using System.Drawing.Imaging; using System.Drawing.Imaging;
using System.Dynamic; using System.Dynamic;
using System.IO; using System.IO;
@ -15,6 +16,7 @@ using Artemis.Managers;
using Artemis.Models; using Artemis.Models;
using Artemis.Models.Profiles; using Artemis.Models.Profiles;
using Caliburn.Micro; using Caliburn.Micro;
using MahApps.Metro;
namespace Artemis.ViewModels namespace Artemis.ViewModels
{ {
@ -22,9 +24,16 @@ namespace Artemis.ViewModels
{ {
private readonly GameModel _gameModel; private readonly GameModel _gameModel;
private readonly MainManager _mainManager; private readonly MainManager _mainManager;
private DateTime _downTime;
private LayerModel _draggingLayer;
private Point? _draggingLayerOffset;
private LayerEditorViewModel<T> _editorVm; private LayerEditorViewModel<T> _editorVm;
private Cursor _keyboardPreviewCursor;
private BindableCollection<LayerModel> _layers;
private BindableCollection<ProfileModel> _profileModels; private BindableCollection<ProfileModel> _profileModels;
private ProfileModel _selectedProfileModel; private bool _resizeSourceRect;
private LayerModel _selectedLayer;
private ProfileModel _selectedProfile;
public ProfileEditorViewModel(MainManager mainManager, GameModel gameModel) public ProfileEditorViewModel(MainManager mainManager, GameModel gameModel)
{ {
@ -32,7 +41,10 @@ namespace Artemis.ViewModels
_gameModel = gameModel; _gameModel = gameModel;
ProfileModels = new BindableCollection<ProfileModel>(); ProfileModels = new BindableCollection<ProfileModel>();
Layers = new BindableCollection<LayerModel>();
_mainManager.Events.Subscribe(this); _mainManager.Events.Subscribe(this);
PropertyChanged += PreviewRefresher;
LoadProfiles(); LoadProfiles();
} }
@ -47,27 +59,52 @@ namespace Artemis.ViewModels
} }
} }
public ProfileModel SelectedProfileModel public BindableCollection<LayerModel> Layers
{ {
get { return _selectedProfileModel; } get { return _layers; }
set set
{ {
if (Equals(value, _selectedProfileModel)) return; if (Equals(value, _layers)) return;
_selectedProfileModel = value; _layers = value;
NotifyOfPropertyChange(() => SelectedProfileModel); NotifyOfPropertyChange(() => Layers);
} }
} }
public LayerModel SelectedLayer { get; set; } public LayerModel SelectedLayer
{
get { return _selectedLayer; }
set
{
if (Equals(value, _selectedLayer)) return;
_selectedLayer = value;
NotifyOfPropertyChange(() => SelectedLayer);
}
}
public ProfileModel SelectedProfile
{
get { return _selectedProfile; }
set
{
if (Equals(value, _selectedProfile)) return;
_selectedProfile = value;
Layers.Clear();
Layers.AddRange(_selectedProfile?.Layers);
NotifyOfPropertyChange(() => SelectedProfile);
NotifyOfPropertyChange(() => CanAddLayer);
}
}
public ImageSource KeyboardPreview public ImageSource KeyboardPreview
{ {
get get
{ {
if (_selectedProfileModel == null) if (_selectedProfile == null)
return null; return null;
var keyboardRect = _mainManager.KeyboardManager.ActiveKeyboard.KeyboardRectangle(4); var keyboardRect = ActiveKeyboard.KeyboardRectangle(4);
var visual = new DrawingVisual(); var visual = new DrawingVisual();
using (var drawingContext = visual.RenderOpen()) using (var drawingContext = visual.RenderOpen())
{ {
@ -75,12 +112,30 @@ namespace Artemis.ViewModels
drawingContext.PushClip(new RectangleGeometry(keyboardRect)); drawingContext.PushClip(new RectangleGeometry(keyboardRect));
drawingContext.DrawRectangle(new SolidColorBrush(Color.FromArgb(0, 0, 0, 0)), null, keyboardRect); drawingContext.DrawRectangle(new SolidColorBrush(Color.FromArgb(0, 0, 0, 0)), null, keyboardRect);
// Get the selection color
var penColor = (Color)ThemeManager.DetectAppStyle(Application.Current).Item2.Resources["AccentColor"];
var pen = new Pen(new SolidColorBrush(penColor), 0.4);
// Draw the layer // Draw the layer
foreach (var layerModel in _selectedProfileModel.Layers) foreach (var layerModel in _selectedProfile.Layers)
{ {
// if (layerModel.Selected)
drawingContext.DrawRectangle(null, new Pen(new SolidColorBrush(Colors.White), 0.5),new Rect(layerModel.LayerUserProperties.X*4,layerModel.LayerUserProperties.Y*4, layerModel.LayerUserProperties.Width*4,layerModel.LayerUserProperties.Height*4));
layerModel.DrawPreview(drawingContext); layerModel.DrawPreview(drawingContext);
if (layerModel != SelectedLayer || !layerModel.Enabled)
continue;
var layerRect = layerModel.UserProps.GetRect();
// Draw an outline around the selected layer
drawingContext.DrawRectangle(null, pen, layerRect);
// Draw a resize indicator in the bottom-right
drawingContext.DrawLine(pen,
new Point(layerRect.BottomRight.X - 1, layerRect.BottomRight.Y - 0.5),
new Point(layerRect.BottomRight.X - 1.2, layerRect.BottomRight.Y - 0.7));
drawingContext.DrawLine(pen,
new Point(layerRect.BottomRight.X - 0.5, layerRect.BottomRight.Y - 1),
new Point(layerRect.BottomRight.X - 0.7, layerRect.BottomRight.Y - 1.2));
drawingContext.DrawLine(pen,
new Point(layerRect.BottomRight.X - 0.5, layerRect.BottomRight.Y - 0.5),
new Point(layerRect.BottomRight.X - 0.7, layerRect.BottomRight.Y - 0.7));
} }
// Remove the clip // Remove the clip
@ -98,10 +153,9 @@ namespace Artemis.ViewModels
{ {
using (var memory = new MemoryStream()) using (var memory = new MemoryStream())
{ {
if (_mainManager.KeyboardManager.ActiveKeyboard?.PreviewSettings == null) if (ActiveKeyboard?.PreviewSettings == null || ActiveKeyboard?.PreviewSettings.Image == null)
return null; return null;
ActiveKeyboard.PreviewSettings.Image.Save(memory, ImageFormat.Png);
_mainManager.KeyboardManager.ActiveKeyboard.PreviewSettings.Image.Save(memory, ImageFormat.Png);
memory.Position = 0; memory.Position = 0;
var bitmapImage = new BitmapImage(); var bitmapImage = new BitmapImage();
@ -115,22 +169,40 @@ namespace Artemis.ViewModels
} }
} }
public PreviewSettings? PreviewSettings public PreviewSettings? PreviewSettings => ActiveKeyboard?.PreviewSettings;
public bool CanAddLayer => _selectedProfile != null;
public Cursor KeyboardPreviewCursor
{ {
get { return _mainManager.KeyboardManager.ActiveKeyboard?.PreviewSettings; } get { return _keyboardPreviewCursor; }
set
{
if (Equals(value, _keyboardPreviewCursor)) return;
_keyboardPreviewCursor = value;
NotifyOfPropertyChange(() => KeyboardPreviewCursor);
}
} }
private KeyboardProvider ActiveKeyboard => _mainManager.KeyboardManager.ActiveKeyboard;
public void Handle(ActiveKeyboardChanged message) public void Handle(ActiveKeyboardChanged message)
{ {
NotifyOfPropertyChange(() => KeyboardImage); NotifyOfPropertyChange(() => KeyboardImage);
NotifyOfPropertyChange(() => PreviewSettings); NotifyOfPropertyChange(() => PreviewSettings);
} }
private void PreviewRefresher(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "SelectedLayer" || e.PropertyName == "ProfileTree")
NotifyOfPropertyChange(() => KeyboardPreview);
}
private void LoadProfiles() private void LoadProfiles()
{ {
ProfileModels.Clear(); ProfileModels.Clear();
ProfileModels.AddRange(ProfileProvider.GetAll(_gameModel)); ProfileModels.AddRange(ProfileProvider.GetAll(_gameModel));
SelectedProfileModel = ProfileModels.FirstOrDefault(); SelectedProfile = ProfileModels.FirstOrDefault();
} }
public async void AddProfile() public async void AddProfile()
@ -148,7 +220,7 @@ namespace Artemis.ViewModels
var profile = new ProfileModel var profile = new ProfileModel
{ {
Name = name, Name = name,
KeyboardName = _mainManager.KeyboardManager.ActiveKeyboard.Name, KeyboardName = ActiveKeyboard.Name,
GameName = _gameModel.Name GameName = _gameModel.Name
}; };
if (ProfileProvider.GetAll().Contains(profile)) if (ProfileProvider.GetAll().Contains(profile))
@ -164,13 +236,18 @@ namespace Artemis.ViewModels
ProfileProvider.AddOrUpdate(profile); ProfileProvider.AddOrUpdate(profile);
LoadProfiles(); LoadProfiles();
SelectedProfileModel = profile; SelectedProfile = profile;
}
public void ToggleEnabled(LayerModel layer)
{
NotifyOfPropertyChange(() => KeyboardPreview);
} }
public void LayerEditor(LayerModel layer) public void LayerEditor(LayerModel layer)
{ {
IWindowManager manager = new WindowManager(); IWindowManager manager = new WindowManager();
_editorVm = new LayerEditorViewModel<T>(_mainManager.KeyboardManager.ActiveKeyboard, SelectedProfileModel, _editorVm = new LayerEditorViewModel<T>(ActiveKeyboard, SelectedProfile,
layer); layer);
dynamic settings = new ExpandoObject(); dynamic settings = new ExpandoObject();
@ -186,27 +263,125 @@ namespace Artemis.ViewModels
public void AddLayer() public void AddLayer()
{ {
_selectedProfileModel.Layers.Add(new LayerModel if (_selectedProfile == null)
return;
var layer = new LayerModel
{ {
Name = "Layer " + (_selectedProfileModel.Layers.Count + 1), Name = "Layer " + (_selectedProfile.Layers.Count + 1),
LayerType = LayerType.KeyboardRectangle LayerType = LayerType.KeyboardRectangle,
}); UserProps = new LayerPropertiesModel
NotifyOfPropertyChange(() => SelectedProfileModel); {
Brush = new SolidColorBrush(Colors.Red),
Animation = LayerAnimation.None,
Height = 1,
Width = 1,
X = 0,
Y = 0,
Opacity = 1
}
};
SelectedProfile.Layers.Add(layer);
Layers.Add(layer);
}
public void MouseDownKeyboardPreview(MouseButtonEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
_downTime = DateTime.Now;
}
public void MouseUpKeyboardPreview(MouseButtonEventArgs e)
{
var timeSinceDown = DateTime.Now - _downTime;
if (timeSinceDown.TotalMilliseconds < 500)
{
var pos = e.GetPosition((Image) e.OriginalSource);
var x = pos.X/((double) ActiveKeyboard.PreviewSettings.Width/ActiveKeyboard.Width);
var y = pos.Y/((double) ActiveKeyboard.PreviewSettings.Height/ActiveKeyboard.Height);
var hoverLayer = SelectedProfile.Layers.Where(l => l.Enabled)
.FirstOrDefault(l => l.UserProps.GetRect(1).Contains(x, y));
if (hoverLayer != null)
SelectedLayer = hoverLayer;
}
} }
public void MouseMoveKeyboardPreview(MouseEventArgs e) public void MouseMoveKeyboardPreview(MouseEventArgs e)
{ {
var pos = e.GetPosition((Image) e.OriginalSource); var pos = e.GetPosition((Image) e.OriginalSource);
var realX = var x = pos.X/((double) ActiveKeyboard.PreviewSettings.Width/ActiveKeyboard.Width);
(int) var y = pos.Y/((double) ActiveKeyboard.PreviewSettings.Height/ActiveKeyboard.Height);
Math.Round(pos.X/ var hoverLayer = SelectedProfile.Layers.Where(l => l.Enabled)
(_mainManager.KeyboardManager.ActiveKeyboard.PreviewSettings.Width/ .FirstOrDefault(l => l.UserProps.GetRect(1).Contains(x, y));
_mainManager.KeyboardManager.ActiveKeyboard.Width));
var realY = HandleDragging(e, x, y, hoverLayer);
(int)
Math.Round(pos.Y/ if (hoverLayer == null)
(_mainManager.KeyboardManager.ActiveKeyboard.PreviewSettings.Height/ {
_mainManager.KeyboardManager.ActiveKeyboard.Height)); KeyboardPreviewCursor = Cursors.Arrow;
return;
}
// Turn the mouse pointer into a hand if hovering over an active layer
if (hoverLayer == SelectedLayer)
{
var layerRect = hoverLayer.UserProps.GetRect(1);
if (Math.Sqrt(Math.Pow(x - layerRect.BottomRight.X, 2) + Math.Pow(y - layerRect.BottomRight.Y, 2)) < 0.6)
KeyboardPreviewCursor = Cursors.SizeNWSE;
else
KeyboardPreviewCursor = Cursors.SizeAll;
}
else
KeyboardPreviewCursor = Cursors.Hand;
}
private void HandleDragging(MouseEventArgs e, double x, double y, LayerModel hoverLayer)
{
// Reset the dragging state on mouse release
if (e.LeftButton == MouseButtonState.Released ||
(_draggingLayer != null && _selectedLayer != _draggingLayer))
{
_draggingLayerOffset = null;
_draggingLayer = null;
return;
}
if (SelectedLayer == null)
return;
// Setup the dragging state on mouse press
if (_draggingLayerOffset == null && hoverLayer != null && e.LeftButton == MouseButtonState.Pressed)
{
var layerRect = hoverLayer.UserProps.GetRect(1);
_draggingLayerOffset = new Point(x - SelectedLayer.UserProps.X, y - SelectedLayer.UserProps.Y);
_draggingLayer = hoverLayer;
if (Math.Sqrt(Math.Pow(x - layerRect.BottomRight.X, 2) + Math.Pow(y - layerRect.BottomRight.Y, 2)) < 0.6)
_resizeSourceRect = true;
else
_resizeSourceRect = false;
}
if (_draggingLayerOffset == null || _draggingLayer == null || (_draggingLayer != SelectedLayer))
return;
// If no setup or reset was done, handle the actual dragging action
if (_resizeSourceRect)
{
_draggingLayer.UserProps.Width = (int) Math.Round(x - _draggingLayer.UserProps.X);
_draggingLayer.UserProps.Height = (int) Math.Round(y - _draggingLayer.UserProps.Y);
if (_draggingLayer.UserProps.Width < 1)
_draggingLayer.UserProps.Width = 1;
if (_draggingLayer.UserProps.Height < 1)
_draggingLayer.UserProps.Height = 1;
}
else
{
_draggingLayer.UserProps.X = (int) Math.Round(x - _draggingLayerOffset.Value.X);
_draggingLayer.UserProps.Y = (int) Math.Round(y - _draggingLayerOffset.Value.Y);
}
NotifyOfPropertyChange(() => KeyboardPreview);
} }
} }
} }

View File

@ -6,6 +6,8 @@
xmlns:local="clr-namespace:Artemis.Views" xmlns:local="clr-namespace:Artemis.Views"
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:cal="http://www.caliburnproject.org"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:itemBehaviours="clr-namespace:Artemis.ItemBehaviours"
mc:Ignorable="d" mc:Ignorable="d"
d:DesignHeight="482.812" d:DesignWidth="1029.95"> d:DesignHeight="482.812" d:DesignWidth="1029.95">
<Grid Width="Auto" Height="Auto"> <Grid Width="Auto" Height="Auto">
@ -34,12 +36,14 @@
<Grid> <Grid>
<Image Grid.Column="0" Grid.Row="0" Source="{Binding Path=KeyboardImage}" Margin="50" /> <Image Grid.Column="0" Grid.Row="0" Source="{Binding Path=KeyboardImage}" Margin="50" />
<Image Grid.Column="0" Grid.Row="0" Source="{Binding Path=KeyboardPreview}" Opacity="0.666" <Image Grid.Column="0" Grid.Row="0" Source="{Binding Path=KeyboardPreview}" Opacity="0.8"
Width="{Binding Path=PreviewSettings.Width}" Width="{Binding Path=PreviewSettings.Width}"
Height="{Binding Path=PreviewSettings.Height}" Height="{Binding Path=PreviewSettings.Height}"
Margin="{Binding Path=PreviewSettings.Margin}" Margin="{Binding Path=PreviewSettings.Margin}"
Stretch="Fill" Stretch="Fill" Cursor="{Binding Path=KeyboardPreviewCursor}"
cal:Message.Attach="[Event MouseMove] = [Action MouseMoveKeyboardPreview($eventArgs)]"/> cal:Message.Attach="[Event MouseMove] = [Action MouseMoveKeyboardPreview($eventArgs)];
[Event MouseDown] = [Action MouseDownKeyboardPreview($eventArgs)];
[Event MouseUp] = [Action MouseUpKeyboardPreview($eventArgs)]" />
</Grid> </Grid>
</Border> </Border>
@ -62,15 +66,17 @@
Margin="10,0,0,0" /> Margin="10,0,0,0" />
<Border Grid.Column="1" Grid.Row="1" Background="#FF232323" BorderBrush="{DynamicResource HighlightBrush}" <Border Grid.Column="1" Grid.Row="1" Background="#FF232323" BorderBrush="{DynamicResource HighlightBrush}"
BorderThickness="3" Margin="10,0,0,0" Height="400" Width="250"> BorderThickness="3" Margin="10,0,0,0" Height="400" Width="250">
<TreeView x:Name="ProfileTree" ItemsSource="{Binding Path=SelectedProfileModel.Layers}"> <TreeView x:Name="ProfileTree" ItemsSource="{Binding Path=Layers}">
<i:Interaction.Behaviors>
<itemBehaviours:BindableSelectedItemBehavior SelectedItem="{Binding SelectedLayer, Mode=TwoWay}" />
</i:Interaction.Behaviors>
<TreeView.Resources> <TreeView.Resources>
<ResourceDictionary <ResourceDictionary
Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseDark.xaml" /> Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseDark.xaml" />
</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 <ContextMenu
cal:Action.TargetWithoutContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}"> cal:Action.TargetWithoutContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
@ -79,7 +85,8 @@
<MenuItem Header="Properties" cal:Message.Attach="LayerEditor($datacontext)" /> <MenuItem Header="Properties" cal:Message.Attach="LayerEditor($datacontext)" />
</ContextMenu> </ContextMenu>
</StackPanel.ContextMenu> </StackPanel.ContextMenu>
<CheckBox VerticalAlignment="Center" ToolTip="Layer enabled" IsChecked="{Binding Enabled}" /> <CheckBox VerticalAlignment="Center" ToolTip="Layer enabled" IsChecked="{Binding Enabled}"
cal:Message.Attach="ToggleEnabled($datacontext)" />
<Image Height="18" Width="18" Source="{Binding LayerImage}" /> <Image Height="18" Width="18" Source="{Binding LayerImage}" />
<TextBlock Margin="5,0,0,0" Text="{Binding Name}" VerticalAlignment="Center" /> <TextBlock Margin="5,0,0,0" Text="{Binding Name}" VerticalAlignment="Center" />
</StackPanel> </StackPanel>