mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Implemented clipping modes, hopefully fixed UI freezes on tab switch
This commit is contained in:
parent
6e451c06cd
commit
4667ea21f9
@ -1,9 +1,11 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Threading;
|
||||
using System.Timers;
|
||||
using Artemis.Events;
|
||||
using Caliburn.Micro;
|
||||
using Ninject.Extensions.Logging;
|
||||
using Timer = System.Timers.Timer;
|
||||
|
||||
namespace Artemis.Managers
|
||||
{
|
||||
@ -108,49 +110,51 @@ namespace Artemis.Managers
|
||||
return;
|
||||
}
|
||||
|
||||
lock (_keyboardManager.ActiveKeyboard)
|
||||
if (!Monitor.TryEnter(_keyboardManager.ActiveKeyboard))
|
||||
return;
|
||||
|
||||
// Skip frame if effect is still initializing
|
||||
if (renderEffect.Initialized == false)
|
||||
return;
|
||||
|
||||
// ApplyProperties the current effect
|
||||
if (renderEffect.Initialized)
|
||||
renderEffect.Update();
|
||||
|
||||
// Get ActiveEffect's bitmap
|
||||
var bitmap = renderEffect.Initialized
|
||||
? renderEffect.GenerateBitmap()
|
||||
: null;
|
||||
|
||||
// Draw enabled overlays on top
|
||||
foreach (var overlayModel in _effectManager.EnabledOverlays)
|
||||
{
|
||||
// Skip frame if effect is still initializing
|
||||
if (renderEffect.Initialized == false)
|
||||
return;
|
||||
|
||||
// ApplyProperties the current effect
|
||||
if (renderEffect.Initialized)
|
||||
renderEffect.Update();
|
||||
|
||||
// Get ActiveEffect's bitmap
|
||||
var bitmap = renderEffect.Initialized
|
||||
? renderEffect.GenerateBitmap()
|
||||
: null;
|
||||
|
||||
// Draw enabled overlays on top
|
||||
foreach (var overlayModel in _effectManager.EnabledOverlays)
|
||||
{
|
||||
overlayModel.Update();
|
||||
bitmap = bitmap != null
|
||||
? overlayModel.GenerateBitmap(bitmap)
|
||||
: overlayModel.GenerateBitmap();
|
||||
}
|
||||
|
||||
if (bitmap == null)
|
||||
return;
|
||||
|
||||
// Fill the bitmap's background with black to avoid trailing colors on some keyboards
|
||||
var fixedBmp = new Bitmap(bitmap.Width, bitmap.Height);
|
||||
using (var g = Graphics.FromImage(fixedBmp))
|
||||
{
|
||||
g.Clear(Color.Black);
|
||||
g.DrawImage(bitmap, 0, 0);
|
||||
}
|
||||
|
||||
bitmap = fixedBmp;
|
||||
|
||||
// If it exists, send bitmap to the device
|
||||
_keyboardManager.ActiveKeyboard?.DrawBitmap(bitmap);
|
||||
|
||||
// debugging TODO: Disable when window isn't shown (in Debug VM, or get rid of it, w/e)
|
||||
_events.PublishOnUIThread(new ChangeBitmap(bitmap));
|
||||
overlayModel.Update();
|
||||
bitmap = bitmap != null
|
||||
? overlayModel.GenerateBitmap(bitmap)
|
||||
: overlayModel.GenerateBitmap();
|
||||
}
|
||||
|
||||
if (bitmap == null)
|
||||
return;
|
||||
|
||||
// Fill the bitmap's background with black to avoid trailing colors on some keyboards
|
||||
var fixedBmp = new Bitmap(bitmap.Width, bitmap.Height);
|
||||
using (var g = Graphics.FromImage(fixedBmp))
|
||||
{
|
||||
g.Clear(Color.Black);
|
||||
g.DrawImage(bitmap, 0, 0);
|
||||
}
|
||||
|
||||
bitmap = fixedBmp;
|
||||
|
||||
// If it exists, send bitmap to the device
|
||||
_keyboardManager.ActiveKeyboard?.DrawBitmap(bitmap);
|
||||
|
||||
// debugging TODO: Disable when window isn't shown (in Debug VM, or get rid of it, w/e)
|
||||
_events.PublishOnUIThread(new ChangeBitmap(bitmap));
|
||||
|
||||
Monitor.Exit(_keyboardManager.ActiveKeyboard);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -41,7 +41,7 @@ namespace Artemis.Models.Profiles
|
||||
return Enabled && Properties.Conditions.All(cm => cm.ConditionMet<T>(dataModel));
|
||||
}
|
||||
|
||||
public void Draw<T>(IGameDataModel dataModel, DrawingContext c, bool preview = false)
|
||||
public void Draw<T>(IGameDataModel dataModel, DrawingContext c, bool preview, bool updateAnimations)
|
||||
{
|
||||
// Don't draw when the layer is disabled
|
||||
if (!Enabled)
|
||||
@ -59,22 +59,21 @@ namespace Artemis.Models.Profiles
|
||||
appliedProperties = GeneralHelpers.Clone(Properties);
|
||||
|
||||
// Update animations on layer types that support them
|
||||
if (LayerType == LayerType.Keyboard || LayerType == LayerType.KeyboardGif)
|
||||
if ((LayerType == LayerType.Keyboard || LayerType == LayerType.KeyboardGif) && updateAnimations)
|
||||
{
|
||||
AnimationUpdater.UpdateAnimation((KeyboardPropertiesModel) Properties);
|
||||
((KeyboardPropertiesModel) appliedProperties).AnimationProgress =
|
||||
((KeyboardPropertiesModel) Properties).AnimationProgress;
|
||||
AnimationUpdater.UpdateAnimation((KeyboardPropertiesModel) Properties,
|
||||
(KeyboardPropertiesModel) appliedProperties);
|
||||
}
|
||||
|
||||
// Folders are drawn recursively
|
||||
if (LayerType == LayerType.Folder)
|
||||
{
|
||||
foreach (var layerModel in Children.OrderByDescending(l => l.Order))
|
||||
layerModel.Draw<T>(dataModel, c);
|
||||
layerModel.Draw<T>(dataModel, c, preview, updateAnimations);
|
||||
}
|
||||
// All other types are handles by the Drawer helper
|
||||
else if (LayerType == LayerType.Keyboard)
|
||||
Drawer.Draw(c, (KeyboardPropertiesModel) appliedProperties);
|
||||
Drawer.Draw(c, (KeyboardPropertiesModel) Properties, (KeyboardPropertiesModel) appliedProperties);
|
||||
else if (LayerType == LayerType.KeyboardGif)
|
||||
GifImage = Drawer.DrawGif(c, (KeyboardPropertiesModel) appliedProperties, GifImage);
|
||||
else if (LayerType == LayerType.Mouse)
|
||||
@ -131,6 +130,15 @@ namespace Artemis.Models.Profiles
|
||||
Children[i].Order = i;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether the layer meets the requirements to be drawn
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool MustDraw()
|
||||
{
|
||||
return Enabled && (LayerType == LayerType.Keyboard || LayerType == LayerType.KeyboardGif);
|
||||
}
|
||||
|
||||
#region IChildItem<Parent> Members
|
||||
|
||||
LayerModel IChildItem<LayerModel>.Parent
|
||||
|
||||
@ -110,7 +110,7 @@ namespace Artemis.Models.Profiles
|
||||
Layers[i].Order = i;
|
||||
}
|
||||
|
||||
public Bitmap GenerateBitmap<T>(Rect keyboardRect, IGameDataModel gameDataModel, bool preview = false)
|
||||
public Bitmap GenerateBitmap<T>(Rect keyboardRect, IGameDataModel gameDataModel, bool preview, bool updateAnimations)
|
||||
{
|
||||
Bitmap bitmap = null;
|
||||
DrawingVisual.Dispatcher.Invoke(delegate
|
||||
@ -124,7 +124,7 @@ namespace Artemis.Models.Profiles
|
||||
|
||||
// Draw the layers
|
||||
foreach (var layerModel in Layers.OrderByDescending(l => l.Order))
|
||||
layerModel.Draw<T>(gameDataModel, c, preview);
|
||||
layerModel.Draw<T>(gameDataModel, c, preview, updateAnimations);
|
||||
|
||||
// Remove the clip
|
||||
c.Pop();
|
||||
|
||||
@ -24,8 +24,6 @@ namespace Artemis.Models.Profiles.Properties
|
||||
public double AnimationSpeed { get; set; }
|
||||
public string GifFile { get; set; }
|
||||
public List<DynamicPropertiesModel> DynamicProperties { get; set; }
|
||||
|
||||
[XmlIgnore]
|
||||
public double AnimationProgress { get; set; }
|
||||
|
||||
public Rect GetRect(int scale = 4)
|
||||
|
||||
@ -41,7 +41,7 @@ namespace Artemis.Modules.Effects.ProfilePreview
|
||||
return bitmap;
|
||||
|
||||
var keyboardRect = MainManager.KeyboardManager.ActiveKeyboard.KeyboardRectangle(4);
|
||||
var image = SelectedProfile.GenerateBitmap<ProfilePreviewDataModel>(keyboardRect, _previewDataModel, true);
|
||||
var image = SelectedProfile.GenerateBitmap<ProfilePreviewDataModel>(keyboardRect, _previewDataModel, true, true);
|
||||
|
||||
// Draw on top of everything else
|
||||
using (var g = Graphics.FromImage(bitmap))
|
||||
|
||||
@ -48,7 +48,7 @@ namespace Artemis.Modules.Games.CounterStrike
|
||||
return null;
|
||||
|
||||
var keyboardRect = MainManager.KeyboardManager.ActiveKeyboard.KeyboardRectangle(Scale);
|
||||
return Profile.GenerateBitmap<CounterStrikeDataModel>(keyboardRect, GameDataModel);
|
||||
return Profile.GenerateBitmap<CounterStrikeDataModel>(keyboardRect, GameDataModel, false, true);
|
||||
}
|
||||
|
||||
public void HandleGameData(object sender, GameDataReceivedEventArgs e)
|
||||
|
||||
@ -62,7 +62,7 @@ namespace Artemis.Modules.Games.Dota2
|
||||
return null;
|
||||
|
||||
var keyboardRect = MainManager.KeyboardManager.ActiveKeyboard.KeyboardRectangle(Scale);
|
||||
return Profile.GenerateBitmap<Dota2DataModel>(keyboardRect, GameDataModel);
|
||||
return Profile.GenerateBitmap<Dota2DataModel>(keyboardRect, GameDataModel, false, true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -73,7 +73,7 @@ namespace Artemis.Modules.Games.RocketLeague
|
||||
return null;
|
||||
|
||||
var keyboardRect = MainManager.KeyboardManager.ActiveKeyboard.KeyboardRectangle(Scale);
|
||||
return Profile.GenerateBitmap<RocketLeagueDataModel>(keyboardRect, GameDataModel);
|
||||
return Profile.GenerateBitmap<RocketLeagueDataModel>(keyboardRect, GameDataModel, false, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -110,7 +110,7 @@ namespace Artemis.Modules.Games.Witcher3
|
||||
return null;
|
||||
|
||||
var keyboardRect = MainManager.KeyboardManager.ActiveKeyboard.KeyboardRectangle(Scale);
|
||||
return Profile.GenerateBitmap<TheWitcherDataModel>(keyboardRect, GameDataModel);
|
||||
return Profile.GenerateBitmap<TheWitcherDataModel>(keyboardRect, GameDataModel, false, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,42 +1,46 @@
|
||||
using System;
|
||||
using Artemis.Models.Profiles.Properties;
|
||||
using Artemis.Models.Profiles.Properties;
|
||||
|
||||
namespace Artemis.Utilities.Layers
|
||||
{
|
||||
public static class AnimationUpdater
|
||||
{
|
||||
public static void UpdateAnimation(KeyboardPropertiesModel properties)
|
||||
public static void UpdateAnimation(KeyboardPropertiesModel properties, KeyboardPropertiesModel appliedProperties)
|
||||
{
|
||||
const int scale = 4;
|
||||
var progress = properties.AnimationProgress;
|
||||
var animateProperties = properties.Contain ? appliedProperties : properties;
|
||||
var progress = appliedProperties.AnimationProgress;
|
||||
|
||||
// Horizontal sliding
|
||||
if (properties.Animation == LayerAnimation.SlideRight || properties.Animation == LayerAnimation.SlideLeft)
|
||||
if (animateProperties.Animation == LayerAnimation.SlideRight ||
|
||||
animateProperties.Animation == LayerAnimation.SlideLeft)
|
||||
{
|
||||
if (progress > properties.Width*scale)
|
||||
if (progress > animateProperties.Width*scale)
|
||||
progress = 0;
|
||||
}
|
||||
|
||||
// Vertical sliding
|
||||
if (properties.Animation == LayerAnimation.SlideDown || properties.Animation == LayerAnimation.SlideUp)
|
||||
if (animateProperties.Animation == LayerAnimation.SlideDown ||
|
||||
animateProperties.Animation == LayerAnimation.SlideUp)
|
||||
{
|
||||
if (progress > properties.Height*scale)
|
||||
if (progress > animateProperties.Height*scale)
|
||||
progress = 0;
|
||||
}
|
||||
|
||||
// Pulse animation
|
||||
if (properties.Animation == LayerAnimation.Pulse)
|
||||
if (animateProperties.Animation == LayerAnimation.Pulse)
|
||||
{
|
||||
if (progress > 2)
|
||||
progress = 0;
|
||||
|
||||
progress = progress + properties.AnimationSpeed/2;
|
||||
progress = progress + animateProperties.AnimationSpeed/2;
|
||||
}
|
||||
else
|
||||
{
|
||||
progress = progress + properties.AnimationSpeed * 2;
|
||||
progress = progress + animateProperties.AnimationSpeed*2;
|
||||
}
|
||||
|
||||
appliedProperties.AnimationProgress = progress;
|
||||
// Store the animation progress in the actual model for the next frame
|
||||
properties.AnimationProgress = progress;
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,54 +14,60 @@ namespace Artemis.Utilities.Layers
|
||||
{
|
||||
public static class Drawer
|
||||
{
|
||||
public static void Draw(DrawingContext c, KeyboardPropertiesModel props)
|
||||
public static void Draw(DrawingContext c, KeyboardPropertiesModel props, KeyboardPropertiesModel applied)
|
||||
{
|
||||
if (props.Brush == null)
|
||||
if (applied.Brush == null)
|
||||
return;
|
||||
|
||||
const int scale = 4;
|
||||
|
||||
// Set up variables for this frame
|
||||
var rect = new Rect(props.X*scale, props.Y*scale, props.Width*scale, props.Height*scale);
|
||||
var rect = props.Contain
|
||||
? new Rect(applied.X*scale, applied.Y*scale, applied.Width*scale, applied.Height*scale)
|
||||
: new Rect(props.X*scale, props.Y*scale, props.Width*scale, props.Height*scale);
|
||||
|
||||
var s1 = new Rect();
|
||||
var s2 = new Rect();
|
||||
|
||||
if (props.Animation == LayerAnimation.SlideRight)
|
||||
if (applied.Animation == LayerAnimation.SlideRight)
|
||||
{
|
||||
s1 = new Rect(new Point(rect.X + props.AnimationProgress, rect.Y), new Size(rect.Width, rect.Height));
|
||||
s1 = new Rect(new Point(rect.X + applied.AnimationProgress, rect.Y), new Size(rect.Width, rect.Height));
|
||||
s2 = new Rect(new Point(s1.X - rect.Width, rect.Y), new Size(rect.Width + 1, rect.Height));
|
||||
}
|
||||
if (props.Animation == LayerAnimation.SlideLeft)
|
||||
if (applied.Animation == LayerAnimation.SlideLeft)
|
||||
{
|
||||
s1 = new Rect(new Point(rect.X - props.AnimationProgress, rect.Y), new Size(rect.Width + 1, rect.Height));
|
||||
s1 = new Rect(new Point(rect.X - applied.AnimationProgress, rect.Y),
|
||||
new Size(rect.Width + 1, rect.Height));
|
||||
s2 = new Rect(new Point(s1.X + rect.Width, rect.Y), new Size(rect.Width, rect.Height));
|
||||
}
|
||||
if (props.Animation == LayerAnimation.SlideDown)
|
||||
if (applied.Animation == LayerAnimation.SlideDown)
|
||||
{
|
||||
s1 = new Rect(new Point(rect.X, rect.Y + props.AnimationProgress), new Size(rect.Width, rect.Height));
|
||||
s1 = new Rect(new Point(rect.X, rect.Y + applied.AnimationProgress), new Size(rect.Width, rect.Height));
|
||||
s2 = new Rect(new Point(s1.X, s1.Y - rect.Height), new Size(rect.Width, rect.Height));
|
||||
}
|
||||
if (props.Animation == LayerAnimation.SlideUp)
|
||||
if (applied.Animation == LayerAnimation.SlideUp)
|
||||
{
|
||||
s1 = new Rect(new Point(rect.X, rect.Y - props.AnimationProgress), new Size(rect.Width, rect.Height));
|
||||
s1 = new Rect(new Point(rect.X, rect.Y - applied.AnimationProgress), new Size(rect.Width, rect.Height));
|
||||
s2 = new Rect(new Point(s1.X, s1.Y + rect.Height), new Size(rect.Width, rect.Height));
|
||||
}
|
||||
|
||||
props.Brush.Dispatcher.Invoke(() => DrawRectangle(c, props, rect, s1, s2));
|
||||
var clip = new Rect(applied.X*scale, applied.Y*scale, applied.Width*scale, applied.Height*scale);
|
||||
|
||||
applied.Brush.Dispatcher.Invoke(() => DrawRectangle(c, applied, clip, rect, s1, s2));
|
||||
}
|
||||
|
||||
private static void DrawRectangle(DrawingContext c, KeyboardPropertiesModel properties, Rect rectangle,
|
||||
private static void DrawRectangle(DrawingContext c, KeyboardPropertiesModel properties, Rect clip,
|
||||
Rect rectangle,
|
||||
Rect slide1, Rect slide2)
|
||||
{
|
||||
// Apply the pulse animation
|
||||
var brush = properties.Brush.CloneCurrentValue();
|
||||
brush.Opacity = properties.Opacity;
|
||||
if (properties.Animation == LayerAnimation.Pulse)
|
||||
brush.Opacity = (Math.Sin(properties.AnimationProgress * Math.PI) + 1) * (properties.Opacity / 2);
|
||||
brush.Opacity = (Math.Sin(properties.AnimationProgress*Math.PI) + 1)*(properties.Opacity/2);
|
||||
else
|
||||
brush.Opacity = properties.Opacity;
|
||||
|
||||
// TODO: Implement clipping modes
|
||||
c.PushClip(new RectangleGeometry(clip));
|
||||
// Most animation types can be drawn regularly
|
||||
if (properties.Animation == LayerAnimation.None ||
|
||||
properties.Animation == LayerAnimation.Grow ||
|
||||
@ -72,11 +78,11 @@ namespace Artemis.Utilities.Layers
|
||||
// Sliding animations however, require offsetting two rects
|
||||
else
|
||||
{
|
||||
c.PushClip(new RectangleGeometry(rectangle));
|
||||
c.PushClip(new RectangleGeometry(clip));
|
||||
c.DrawRectangle(brush, null, slide1);
|
||||
c.DrawRectangle(brush, null, slide2);
|
||||
c.Pop();
|
||||
}
|
||||
c.Pop();
|
||||
}
|
||||
|
||||
public static GifImage DrawGif(DrawingContext c, KeyboardPropertiesModel properties, GifImage gifImage,
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using Artemis.Models.Interfaces;
|
||||
using Artemis.Models.Profiles;
|
||||
using Artemis.Models.Profiles.Properties;
|
||||
@ -10,14 +8,12 @@ using Artemis.Services;
|
||||
using Artemis.Utilities;
|
||||
using Caliburn.Micro;
|
||||
using Ninject;
|
||||
using Screen = Caliburn.Micro.Screen;
|
||||
|
||||
namespace Artemis.ViewModels.LayerEditor
|
||||
{
|
||||
public sealed class LayerEditorViewModel : Screen
|
||||
{
|
||||
private readonly IGameDataModel _gameDataModel;
|
||||
private readonly bool _wasEnabled;
|
||||
private LayerModel _layer;
|
||||
private LayerPropertiesViewModel _layerPropertiesViewModel;
|
||||
private LayerType _layerType;
|
||||
@ -27,10 +23,8 @@ namespace Artemis.ViewModels.LayerEditor
|
||||
public LayerEditorViewModel(IGameDataModel gameDataModel, LayerModel layer)
|
||||
{
|
||||
_gameDataModel = gameDataModel;
|
||||
_wasEnabled = layer.Enabled;
|
||||
|
||||
Layer = layer;
|
||||
Layer.Enabled = false;
|
||||
|
||||
if (Layer.Properties == null)
|
||||
Layer.SetupProperties();
|
||||
@ -39,7 +33,7 @@ namespace Artemis.ViewModels.LayerEditor
|
||||
DataModelProps.AddRange(GeneralHelpers.GenerateTypeMap(gameDataModel));
|
||||
LayerConditionVms = new BindableCollection<LayerConditionViewModel>(layer.Properties.Conditions
|
||||
.Select(c => new LayerConditionViewModel(this, c, DataModelProps)));
|
||||
|
||||
|
||||
PropertyChanged += PropertiesViewModelHandler;
|
||||
PreSelect();
|
||||
}
|
||||
@ -172,11 +166,5 @@ namespace Artemis.ViewModels.LayerEditor
|
||||
LayerConditionVms.Remove(layerConditionViewModel);
|
||||
Layer.Properties.Conditions.Remove(layerConditionModel);
|
||||
}
|
||||
|
||||
public override void CanClose(Action<bool> callback)
|
||||
{
|
||||
_layer.Enabled = _wasEnabled;
|
||||
base.CanClose(callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -7,6 +7,7 @@ using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
using Artemis.DAL;
|
||||
using Artemis.Events;
|
||||
using Artemis.KeyboardProviders;
|
||||
@ -31,6 +32,7 @@ namespace Artemis.ViewModels
|
||||
private LayerModel _draggingLayer;
|
||||
private Point? _draggingLayerOffset;
|
||||
private LayerEditorViewModel _editorVm;
|
||||
private ImageSource _keyboardPreview;
|
||||
private Cursor _keyboardPreviewCursor;
|
||||
private BindableCollection<LayerModel> _layers;
|
||||
private BindableCollection<ProfileModel> _profiles;
|
||||
@ -45,10 +47,13 @@ namespace Artemis.ViewModels
|
||||
|
||||
Profiles = new BindableCollection<ProfileModel>();
|
||||
Layers = new BindableCollection<LayerModel>();
|
||||
ActiveKeyboard = _mainManager.KeyboardManager.ActiveKeyboard;
|
||||
|
||||
events.Subscribe(this);
|
||||
|
||||
PreviewTimer = new Timer(40);
|
||||
PreviewTimer.Elapsed += (sender, args) => NotifyOfPropertyChange(() => KeyboardPreview);
|
||||
PreviewTimer.Elapsed += InvokeUpdateKeyboardPreview;
|
||||
|
||||
|
||||
PropertyChanged += PropertyChangeHandler;
|
||||
LoadProfiles();
|
||||
@ -124,59 +129,12 @@ namespace Artemis.ViewModels
|
||||
|
||||
public ImageSource KeyboardPreview
|
||||
{
|
||||
get
|
||||
get { return _keyboardPreview; }
|
||||
set
|
||||
{
|
||||
if (_selectedProfile == null || ActiveKeyboard == null)
|
||||
return null;
|
||||
|
||||
var keyboardRect = ActiveKeyboard.KeyboardRectangle(4);
|
||||
var visual = new DrawingVisual();
|
||||
using (var drawingContext = visual.RenderOpen())
|
||||
{
|
||||
// Setup the DrawingVisual's size
|
||||
drawingContext.PushClip(new RectangleGeometry(keyboardRect));
|
||||
drawingContext.DrawRectangle(new SolidColorBrush(Color.FromArgb(0, 0, 0, 0)), null, keyboardRect);
|
||||
|
||||
// Draw the layers
|
||||
foreach (var layerModel in _selectedProfile.Layers
|
||||
.OrderByDescending(l => l.Order)
|
||||
.Where(l => l.LayerType == LayerType.Keyboard ||
|
||||
l.LayerType == LayerType.KeyboardGif))
|
||||
{
|
||||
layerModel.Draw<object>(null, drawingContext, true);
|
||||
}
|
||||
|
||||
// Get the selection color
|
||||
var color = (Color) ThemeManager.DetectAppStyle(Application.Current).Item2.Resources["AccentColor"];
|
||||
var pen = new Pen(new SolidColorBrush(color), 0.4);
|
||||
|
||||
// Draw the selection outline and resize indicator
|
||||
if (SelectedLayer != null && ShouldDrawLayer(SelectedLayer))
|
||||
{
|
||||
var layerRect = ((KeyboardPropertiesModel) SelectedLayer.Properties).GetRect();
|
||||
// Deflate the rect so that the border is drawn on the inside
|
||||
layerRect.Inflate(-0.2, -0.2);
|
||||
|
||||
// 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
|
||||
drawingContext.Pop();
|
||||
}
|
||||
var image = new DrawingImage(visual.Drawing);
|
||||
|
||||
return image;
|
||||
if (Equals(value, _keyboardPreview)) return;
|
||||
_keyboardPreview = value;
|
||||
NotifyOfPropertyChange(() => KeyboardPreview);
|
||||
}
|
||||
}
|
||||
|
||||
@ -187,7 +145,7 @@ namespace Artemis.ViewModels
|
||||
public bool CanAddLayer => _selectedProfile != null;
|
||||
public bool CanRemoveLayer => _selectedProfile != null && _selectedLayer != null;
|
||||
|
||||
private KeyboardProvider ActiveKeyboard => _mainManager.KeyboardManager.ActiveKeyboard;
|
||||
private KeyboardProvider ActiveKeyboard { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Handles chaning the active keyboard, updating the preview image and profiles collection
|
||||
@ -195,6 +153,7 @@ namespace Artemis.ViewModels
|
||||
/// <param name="message"></param>
|
||||
public void Handle(ActiveKeyboardChanged message)
|
||||
{
|
||||
ActiveKeyboard = _mainManager.KeyboardManager.ActiveKeyboard;
|
||||
NotifyOfPropertyChange(() => KeyboardImage);
|
||||
NotifyOfPropertyChange(() => PreviewSettings);
|
||||
LoadProfiles();
|
||||
@ -401,8 +360,13 @@ namespace Artemis.ViewModels
|
||||
var x = pos.X/((double) ActiveKeyboard.PreviewSettings.Width/ActiveKeyboard.Width);
|
||||
var y = pos.Y/((double) ActiveKeyboard.PreviewSettings.Height/ActiveKeyboard.Height);
|
||||
|
||||
var hoverLayer = SelectedProfile.Layers.OrderBy(l => l.Order).Where(ShouldDrawLayer)
|
||||
.FirstOrDefault(l => ((KeyboardPropertiesModel) l.Properties).GetRect(1).Contains(x, y));
|
||||
var hoverLayer = SelectedProfile.Layers
|
||||
.OrderBy(l => l.Order)
|
||||
.Where(l => l.MustDraw())
|
||||
.FirstOrDefault(l => ((KeyboardPropertiesModel) l.Properties)
|
||||
.GetRect(1)
|
||||
.Contains(x, y));
|
||||
|
||||
SelectedLayer = hoverLayer;
|
||||
}
|
||||
|
||||
@ -415,7 +379,7 @@ namespace Artemis.ViewModels
|
||||
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.OrderBy(l => l.Order).Where(ShouldDrawLayer)
|
||||
var hoverLayer = SelectedProfile.Layers.OrderBy(l => l.Order).Where(l => l.MustDraw())
|
||||
.FirstOrDefault(l => ((KeyboardPropertiesModel) l.Properties).GetRect(1).Contains(x, y));
|
||||
|
||||
HandleDragging(e, x, y, hoverLayer);
|
||||
@ -440,6 +404,62 @@ namespace Artemis.ViewModels
|
||||
KeyboardPreviewCursor = Cursors.Hand;
|
||||
}
|
||||
|
||||
private void InvokeUpdateKeyboardPreview(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
Application.Current.Dispatcher.Invoke(UpdateKeyboardPreview, DispatcherPriority.ContextIdle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a new image for the keyboard preview
|
||||
/// </summary>
|
||||
public void UpdateKeyboardPreview()
|
||||
{
|
||||
if (_selectedProfile == null || ActiveKeyboard == null)
|
||||
return;
|
||||
|
||||
var keyboardRect = ActiveKeyboard.KeyboardRectangle(4);
|
||||
var visual = new DrawingVisual();
|
||||
using (var drawingContext = visual.RenderOpen())
|
||||
{
|
||||
// Setup the DrawingVisual's size
|
||||
drawingContext.PushClip(new RectangleGeometry(keyboardRect));
|
||||
drawingContext.DrawRectangle(new SolidColorBrush(Color.FromArgb(0, 0, 0, 0)), null, keyboardRect);
|
||||
|
||||
// Draw the layers
|
||||
foreach (var layer in _selectedProfile.Layers.OrderByDescending(l => l.Order).Where(l => l.MustDraw()))
|
||||
layer.Draw<object>(null, drawingContext, true, false);
|
||||
|
||||
// Get the selection color
|
||||
var color = (Color) ThemeManager.DetectAppStyle(Application.Current).Item2.Resources["AccentColor"];
|
||||
var pen = new Pen(new SolidColorBrush(color), 0.4);
|
||||
|
||||
// Draw the selection outline and resize indicator
|
||||
if (SelectedLayer != null && SelectedLayer.MustDraw())
|
||||
{
|
||||
var layerRect = ((KeyboardPropertiesModel) SelectedLayer.Properties).GetRect();
|
||||
// Deflate the rect so that the border is drawn on the inside
|
||||
layerRect.Inflate(-0.2, -0.2);
|
||||
|
||||
// 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
|
||||
drawingContext.Pop();
|
||||
}
|
||||
KeyboardPreview = new DrawingImage(visual.Drawing);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles dragging the given layer
|
||||
/// </summary>
|
||||
@ -496,10 +516,5 @@ namespace Artemis.ViewModels
|
||||
draggingProps.Y = (int) Math.Round(y - _draggingLayerOffset.Value.Y);
|
||||
}
|
||||
}
|
||||
|
||||
private bool ShouldDrawLayer(LayerModel layer)
|
||||
{
|
||||
return layer.Enabled && (layer.LayerType == LayerType.Keyboard || layer.LayerType == LayerType.KeyboardGif);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user