diff --git a/Artemis/Artemis/Artemis.csproj b/Artemis/Artemis/Artemis.csproj
index 698c34680..614e91570 100644
--- a/Artemis/Artemis/Artemis.csproj
+++ b/Artemis/Artemis/Artemis.csproj
@@ -183,6 +183,10 @@
..\packages\DynamicExpresso.Core.1.3.3.5\lib\net40\DynamicExpresso.Core.dll
True
+
+ ..\packages\MouseKeyHook.5.4.0\lib\net40\Gma.System.MouseKeyHook.dll
+ True
+
..\packages\gong-wpf-dragdrop.0.1.4.3\lib\net40\GongSolutions.Wpf.DragDrop.dll
True
@@ -251,10 +255,6 @@
..\packages\squirrel.windows.1.4.4\lib\Net45\NuGet.Squirrel.dll
True
-
- ..\packages\Open.WinKeyboardHook.1.0.11\lib\net45\Open.WinKeyboardHook.dll
- True
-
..\packages\Process.NET.1.0.8\lib\Process.NET.dll
True
@@ -485,6 +485,9 @@
OverlayProfileView.xaml
+
+
+
@@ -622,7 +625,7 @@
-
+
diff --git a/Artemis/Artemis/InjectionModules/BaseModules.cs b/Artemis/Artemis/InjectionModules/BaseModules.cs
index 7447fb67d..af74463cf 100644
--- a/Artemis/Artemis/InjectionModules/BaseModules.cs
+++ b/Artemis/Artemis/InjectionModules/BaseModules.cs
@@ -2,6 +2,7 @@
using Artemis.Managers;
using Artemis.Models;
using Artemis.Modules.Abstract;
+using Artemis.Profiles.Layers.Abstract;
using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Types.Audio.AudioCapturing;
using Artemis.Profiles.Lua;
@@ -92,7 +93,7 @@ namespace Artemis.InjectionModules
Kernel.Bind(x =>
x.FromThisAssembly()
.SelectAllClasses()
- .InheritedFrom()
+ .InheritedFrom()
.BindAllInterfaces());
Kernel.Bind(x =>
x.FromThisAssembly()
diff --git a/Artemis/Artemis/Managers/KeybindManager.cs b/Artemis/Artemis/Managers/KeybindManager.cs
index 263d299df..84880c46c 100644
--- a/Artemis/Artemis/Managers/KeybindManager.cs
+++ b/Artemis/Artemis/Managers/KeybindManager.cs
@@ -6,6 +6,7 @@ using Artemis.Models;
using Artemis.Utilities.Keyboard;
using MahApps.Metro.Controls;
using KeyEventArgs = System.Windows.Forms.KeyEventArgs;
+using MouseEventArgs = System.Windows.Forms.MouseEventArgs;
namespace Artemis.Managers
{
@@ -15,25 +16,34 @@ namespace Artemis.Managers
static KeybindManager()
{
- KeyboardHook.KeyDownCallback += KeyboardHookOnKeyDownCallback;
+ KeyboardHook.KeyDownCallback += args => ProcessKey(args, KeyType.KeyDown);
+ KeyboardHook.KeyUpCallback += args => ProcessKey(args, KeyType.KeyUp);
+ KeyboardHook.MouseDownCallback += args => ProcessMouse(args, KeyType.MouseDown);
+ KeyboardHook.MouseUpCallback += args => ProcessMouse(args, KeyType.MouseUp);
}
-
- private static void KeyboardHookOnKeyDownCallback(KeyEventArgs e)
+
+ private static void ProcessKey(KeyEventArgs keyEventArgs, KeyType keyType)
{
// Don't trigger if the key itself is a modifier
- if (e.KeyCode == Keys.LShiftKey || e.KeyCode == Keys.RShiftKey ||
- e.KeyCode == Keys.LControlKey || e.KeyCode == Keys.RControlKey ||
- e.KeyCode == Keys.LMenu || e.KeyCode == Keys.RMenu)
+ if (keyEventArgs.KeyCode == Keys.LShiftKey || keyEventArgs.KeyCode == Keys.RShiftKey ||
+ keyEventArgs.KeyCode == Keys.LControlKey || keyEventArgs.KeyCode == Keys.RControlKey ||
+ keyEventArgs.KeyCode == Keys.LMenu || keyEventArgs.KeyCode == Keys.RMenu)
return;
// Create a WPF ModifierKeys enum
- var modifiers = ModifierKeysFromBooleans(e.Alt, e.Control, e.Shift);
+ var modifiers = ModifierKeysFromBooleans(keyEventArgs.Alt, keyEventArgs.Control, keyEventArgs.Shift);
// Create a HotKey object for comparison
- var hotKey = new HotKey(KeyInterop.KeyFromVirtualKey(e.KeyValue), modifiers);
+ var hotKey = new HotKey(KeyInterop.KeyFromVirtualKey(keyEventArgs.KeyValue), modifiers);
foreach (var keybindModel in KeybindModels)
- keybindModel.InvokeIfMatched(hotKey);
+ keybindModel.InvokeIfMatched(hotKey, keyType);
+ }
+
+ private static void ProcessMouse(MouseEventArgs mouseEventArgs, KeyType keyType)
+ {
+ foreach (var keybindModel in KeybindModels)
+ keybindModel.InvokeIfMatched(mouseEventArgs.Button, keyType);
}
public static void AddOrUpdate(KeybindModel keybindModel)
@@ -58,12 +68,6 @@ namespace Artemis.Managers
KeybindModels.Remove(existing);
}
- public static void Clear()
- {
- // TODO: Re-add future global keybinds here or just exclude them from the clear
- KeybindModels.Clear();
- }
-
public static ModifierKeys ModifierKeysFromBooleans(bool alt, bool control, bool shift)
{
// Create a WPF ModifierKeys enum
@@ -84,4 +88,4 @@ namespace Artemis.Managers
return modifiers;
}
}
-}
\ No newline at end of file
+}
diff --git a/Artemis/Artemis/Managers/LoopManager.cs b/Artemis/Artemis/Managers/LoopManager.cs
index 3b5aca4f4..31b7300c8 100644
--- a/Artemis/Artemis/Managers/LoopManager.cs
+++ b/Artemis/Artemis/Managers/LoopManager.cs
@@ -56,12 +56,15 @@ namespace Artemis.Managers
Render();
- int sleep = (int)(40f - (DateTime.Now.Ticks - preUpdateTicks) / 10000f);
+ int sleep = (int) (40f - (DateTime.Now.Ticks - preUpdateTicks) / 10000f);
if (sleep > 0)
Thread.Sleep(sleep);
}
catch (Exception e)
{
+#if DEBUG
+ throw e;
+#endif
_logger.Warn(e, "Exception in render loop");
}
}
@@ -155,11 +158,13 @@ namespace Artemis.Managers
var headsets = _deviceManager.HeadsetProviders.Where(m => m.CanUse).ToList();
var generics = _deviceManager.GenericProviders.Where(m => m.CanUse).ToList();
var mousemats = _deviceManager.MousematProviders.Where(m => m.CanUse).ToList();
-
+
var keyboardOnly = !mice.Any() && !headsets.Any() && !generics.Any() && !mousemats.Any();
// Setup the frame for this tick
- using (var frame = new FrameModel(_deviceManager.ActiveKeyboard, mice.Any(), headsets.Any(), generics.Any(), mousemats.Any()))
+ using (
+ var frame = new FrameModel(_deviceManager.ActiveKeyboard, mice.Any(), headsets.Any(), generics.Any(),
+ mousemats.Any()))
{
if (renderModule.IsInitialized)
renderModule.Render(frame, keyboardOnly);
diff --git a/Artemis/Artemis/Models/KeybindModel.cs b/Artemis/Artemis/Models/KeybindModel.cs
index 685894c0c..e1d71ab56 100644
--- a/Artemis/Artemis/Models/KeybindModel.cs
+++ b/Artemis/Artemis/Models/KeybindModel.cs
@@ -1,25 +1,57 @@
using System;
+using System.Windows.Forms;
using MahApps.Metro.Controls;
namespace Artemis.Models
{
public class KeybindModel
{
- public KeybindModel(string name, HotKey hotKey, Action action)
+ public KeybindModel(string name, HotKey hotKey, KeyType keyType, Action action)
{
Name = name;
HotKey = hotKey;
+ KeyType = keyType;
+ Action = action;
+ }
+
+ public KeybindModel(string name, MouseButtons mouseButtons, KeyType keyType, Action action)
+ {
+ Name = name;
+ MouseButtons = mouseButtons;
+ KeyType = keyType;
Action = action;
}
public string Name { get; set; }
+ public MouseButtons MouseButtons { get; }
public HotKey HotKey { get; set; }
public Action Action { get; set; }
+ public KeyType KeyType { get; set; }
- public void InvokeIfMatched(HotKey hotKey)
+ public void InvokeIfMatched(HotKey hotKey, KeyType keyType)
{
+ if (HotKey == null || hotKey == null || KeyType != keyType)
+ return;
+
if (hotKey.Equals(HotKey))
- Action.Invoke();
+ Action?.Invoke();
+ }
+
+ public void InvokeIfMatched(MouseButtons mouseButtons, KeyType keyType)
+ {
+ if (KeyType != keyType)
+ return;
+
+ if (mouseButtons.Equals(MouseButtons))
+ Action?.Invoke();
}
}
-}
\ No newline at end of file
+
+ public enum KeyType
+ {
+ KeyDown,
+ KeyUp,
+ MouseDown,
+ MouseUp
+ }
+}
diff --git a/Artemis/Artemis/Profiles/Layers/Abstract/LayerCondition.cs b/Artemis/Artemis/Profiles/Layers/Abstract/LayerCondition.cs
new file mode 100644
index 000000000..06503f7e5
--- /dev/null
+++ b/Artemis/Artemis/Profiles/Layers/Abstract/LayerCondition.cs
@@ -0,0 +1,11 @@
+using Artemis.Modules.Abstract;
+using Artemis.Profiles.Layers.Models;
+
+namespace Artemis.Profiles.Layers.Abstract
+{
+ public abstract class LayerCondition
+ {
+ public abstract bool ConditionsMet(LayerModel layerModel, ModuleDataModel dataModel);
+ public abstract void KeybindTask(LayerConditionModel condition);
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Profiles/Layers/Animations/RotateClockwiseAnimation.cs b/Artemis/Artemis/Profiles/Layers/Animations/RotateClockwiseAnimation.cs
new file mode 100644
index 000000000..2fd32a8d4
--- /dev/null
+++ b/Artemis/Artemis/Profiles/Layers/Animations/RotateClockwiseAnimation.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Windows.Media;
+using Artemis.Profiles.Layers.Interfaces;
+using Artemis.Profiles.Layers.Models;
+
+namespace Artemis.Profiles.Layers.Animations
+{
+ public class RotateClockwiseAnimation : ILayerAnimation
+ {
+ public string Name => "Rotate clockwise";
+
+ public void Update(LayerModel layerModel, bool updateAnimations)
+ {
+ var progress = layerModel.AnimationProgress;
+
+ if (MustExpire(layerModel))
+ progress = 0;
+ progress = progress + layerModel.Properties.AnimationSpeed / 2.5;
+
+ // If not previewing, store the animation progress in the actual model for the next frame
+ if (updateAnimations)
+ layerModel.AnimationProgress = progress;
+ }
+
+ public void Draw(LayerModel layerModel, DrawingContext c, int drawScale)
+ {
+ if (layerModel.Brush == null)
+ return;
+
+ // Set up variables for this frame
+ var fillRect = layerModel.Properties.PropertiesRect(drawScale);
+ var fillSize = Math.Sqrt(fillRect.Width * fillRect.Width + fillRect.Height * fillRect.Height);
+ fillRect.Inflate(fillSize - fillRect.Width, fillSize - fillRect.Height);
+
+ var clip = layerModel.LayerRect(drawScale);
+
+ c.PushClip(new RectangleGeometry(clip));
+ c.PushTransform(new RotateTransform(36 * layerModel.AnimationProgress, fillRect.X + fillRect.Width / 2, fillRect.Y + fillRect.Height / 2));
+ c.DrawRectangle(layerModel.Brush, null, fillRect);
+ c.Pop();
+ c.Pop();
+ }
+
+ public bool MustExpire(LayerModel layer) => layer.AnimationProgress >= 10;
+ }
+}
diff --git a/Artemis/Artemis/Profiles/Layers/Animations/RotateCounterclockwiseAnimation.cs b/Artemis/Artemis/Profiles/Layers/Animations/RotateCounterclockwiseAnimation.cs
new file mode 100644
index 000000000..b79f2c2dc
--- /dev/null
+++ b/Artemis/Artemis/Profiles/Layers/Animations/RotateCounterclockwiseAnimation.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Windows.Media;
+using Artemis.Profiles.Layers.Interfaces;
+using Artemis.Profiles.Layers.Models;
+
+namespace Artemis.Profiles.Layers.Animations
+{
+ public class RotateCounterclockwiseAnimation : ILayerAnimation
+ {
+ public string Name => "Rotate counterclockwise";
+
+ public void Update(LayerModel layerModel, bool updateAnimations)
+ {
+ var progress = layerModel.AnimationProgress;
+
+ if (MustExpire(layerModel))
+ progress = 0;
+ progress = progress + layerModel.Properties.AnimationSpeed / 2.5;
+
+ // If not previewing, store the animation progress in the actual model for the next frame
+ if (updateAnimations)
+ layerModel.AnimationProgress = progress;
+ }
+
+ public void Draw(LayerModel layerModel, DrawingContext c, int drawScale)
+ {
+ if (layerModel.Brush == null)
+ return;
+
+ // Set up variables for this frame
+ var fillRect = layerModel.Properties.PropertiesRect(drawScale);
+ var fillSize = Math.Sqrt(fillRect.Width * fillRect.Width + fillRect.Height * fillRect.Height);
+ fillRect.Inflate(fillSize - fillRect.Width, fillSize - fillRect.Height);
+
+ var clip = layerModel.LayerRect(drawScale);
+
+ c.PushClip(new RectangleGeometry(clip));
+ c.PushTransform(new RotateTransform(36 * layerModel.AnimationProgress*-1, fillRect.X + fillRect.Width / 2, fillRect.Y + fillRect.Height / 2));
+ c.DrawRectangle(layerModel.Brush, null, fillRect);
+ c.Pop();
+ c.Pop();
+ }
+
+ public bool MustExpire(LayerModel layer) => layer.AnimationProgress >= 10;
+ }
+}
diff --git a/Artemis/Artemis/Profiles/Layers/Animations/ShrinkAnimation.cs b/Artemis/Artemis/Profiles/Layers/Animations/ShrinkAnimation.cs
new file mode 100644
index 000000000..185821f0b
--- /dev/null
+++ b/Artemis/Artemis/Profiles/Layers/Animations/ShrinkAnimation.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Windows.Media;
+using Artemis.Profiles.Layers.Interfaces;
+using Artemis.Profiles.Layers.Models;
+
+namespace Artemis.Profiles.Layers.Animations
+{
+ public class ShrinkAnimation : ILayerAnimation
+ {
+ public string Name => "Shrink";
+
+ public void Update(LayerModel layerModel, bool updateAnimations)
+ {
+ // TODO: Generic implementation
+ // Reset animation progress if layer wasn't drawn for 100ms
+ if ((new TimeSpan(0, 0, 0, 0, 100) < DateTime.Now - layerModel.LastRender) && updateAnimations)
+ layerModel.AnimationProgress = 0;
+
+ var progress = layerModel.AnimationProgress;
+
+ if (MustExpire(layerModel))
+ progress = 10;
+ progress = progress - layerModel.Properties.AnimationSpeed/2.5;
+
+ // If not previewing, store the animation progress in the actual model for the next frame
+ if (updateAnimations)
+ layerModel.AnimationProgress = progress;
+ }
+
+ public void Draw(LayerModel layerModel, DrawingContext c, int drawScale)
+ {
+ if (layerModel.Brush == null)
+ return;
+
+ // Set up variables for this frame
+ var rect = layerModel.Properties.Contain
+ ? layerModel.LayerRect(drawScale)
+ : layerModel.Properties.PropertiesRect(drawScale);
+
+ var clip = layerModel.LayerRect(drawScale);
+
+ // Take an offset of 4 to allow layers to slightly leave their bounds
+ var progress = (6.0 - layerModel.AnimationProgress)*10.0;
+ if (progress < 0)
+ {
+ // Can't meddle with the original brush because it's frozen.
+ var brush = layerModel.Brush.Clone();
+ brush.Opacity = 1 + 0.025*progress;
+ if (brush.Opacity < 0)
+ brush.Opacity = 0;
+ if (brush.Opacity > 1)
+ brush.Opacity = 1;
+ layerModel.Brush = brush;
+ }
+ rect.Inflate(-rect.Width/100.0*progress, -rect.Height/100.0*progress);
+ clip.Inflate(-clip.Width/100.0*progress, -clip.Height/100.0*progress);
+
+ c.PushClip(new RectangleGeometry(clip));
+ c.DrawRectangle(layerModel.Brush, null, rect);
+ c.Pop();
+ }
+
+ public bool MustExpire(LayerModel layer) => layer.AnimationProgress <= 0;
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Profiles/Layers/Conditions/DataModelCondition.cs b/Artemis/Artemis/Profiles/Layers/Conditions/DataModelCondition.cs
index 797b0f1a5..8f5560da4 100644
--- a/Artemis/Artemis/Profiles/Layers/Conditions/DataModelCondition.cs
+++ b/Artemis/Artemis/Profiles/Layers/Conditions/DataModelCondition.cs
@@ -3,22 +3,23 @@ using System.Collections.Generic;
using System.Linq;
using System.Windows;
using Artemis.Modules.Abstract;
+using Artemis.Profiles.Layers.Abstract;
using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Models;
namespace Artemis.Profiles.Layers.Conditions
{
- public class DataModelCondition : ILayerCondition
+ public class DataModelCondition : LayerCondition
{
- private static readonly TimeSpan Delay = TimeSpan.FromMilliseconds((SystemParameters.KeyboardDelay + 1) * 250);
- private DateTime _lastKeypress;
public bool HotKeyMet { get; set; }
- public bool ConditionsMet(LayerModel layerModel, ModuleDataModel dataModel)
+ public override bool ConditionsMet(LayerModel layerModel, ModuleDataModel dataModel)
{
lock (layerModel.Properties.Conditions)
{
- var checkConditions = layerModel.Properties.Conditions.Where(c => !c.Field.Contains("hotkey")).ToList();
+ var checkConditions = layerModel.Properties.Conditions
+ .Where(c => c.Field != null && !c.Field.Contains("hotkey")).ToList();
+
if (checkConditions.Count == layerModel.Properties.Conditions.Count)
return SimpleConditionsMet(layerModel, dataModel, checkConditions);
@@ -36,20 +37,12 @@ namespace Artemis.Profiles.Layers.Conditions
break;
}
- // If there is a held down keybind on it, reset every 2 frames, after 500 ms
- if (layerModel.Properties.Conditions.Any(c => c.Operator == "held") &&
- DateTime.Now - _lastKeypress > Delay)
- {
- HotKeyMet = false;
- }
-
return conditionMet;
}
}
- public void KeybindTask(LayerConditionModel condition)
+ public override void KeybindTask(LayerConditionModel condition)
{
- _lastKeypress = DateTime.Now;
switch (condition.Field)
{
case "hotkeyEnable":
diff --git a/Artemis/Artemis/Profiles/Layers/Conditions/EventCondition.cs b/Artemis/Artemis/Profiles/Layers/Conditions/EventCondition.cs
index 1700c6b5e..bcc1c3f01 100644
--- a/Artemis/Artemis/Profiles/Layers/Conditions/EventCondition.cs
+++ b/Artemis/Artemis/Profiles/Layers/Conditions/EventCondition.cs
@@ -1,22 +1,25 @@
using System.Collections.Generic;
using System.Linq;
using Artemis.Modules.Abstract;
+using Artemis.Profiles.Layers.Abstract;
using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Models;
using Newtonsoft.Json;
namespace Artemis.Profiles.Layers.Conditions
{
- public class EventCondition : ILayerCondition
+ public class EventCondition : LayerCondition
{
[JsonIgnore]
public bool HotKeyMet { get; set; }
- public bool ConditionsMet(LayerModel layerModel, ModuleDataModel dataModel)
+ public override bool ConditionsMet(LayerModel layerModel, ModuleDataModel dataModel)
{
lock (layerModel.Properties.Conditions)
{
- var checkConditions = layerModel.Properties.Conditions.Where(c => !c.Field.Contains("hotkey")).ToList();
+ var checkConditions = layerModel.Properties.Conditions
+ .Where(c => c.Field != null && !c.Field.Contains("hotkey")).ToList();
+
if (checkConditions.Count == layerModel.Properties.Conditions.Count)
return SimpleConditionsMet(layerModel, dataModel, checkConditions);
@@ -45,7 +48,7 @@ namespace Artemis.Profiles.Layers.Conditions
}
}
- public void KeybindTask(LayerConditionModel condition)
+ public override void KeybindTask(LayerConditionModel condition)
{
switch (condition.Field)
{
diff --git a/Artemis/Artemis/Profiles/Layers/Interfaces/ILayerCondition.cs b/Artemis/Artemis/Profiles/Layers/Interfaces/ILayerCondition.cs
deleted file mode 100644
index ab19a5dcc..000000000
--- a/Artemis/Artemis/Profiles/Layers/Interfaces/ILayerCondition.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using Artemis.Modules.Abstract;
-using Artemis.Profiles.Layers.Models;
-
-namespace Artemis.Profiles.Layers.Interfaces
-{
- public interface ILayerCondition
- {
- bool ConditionsMet(LayerModel layerModel, ModuleDataModel dataModel);
- void KeybindTask(LayerConditionModel condition);
- }
-}
\ No newline at end of file
diff --git a/Artemis/Artemis/Profiles/Layers/Models/LayerModel.cs b/Artemis/Artemis/Profiles/Layers/Models/LayerModel.cs
index e04354364..90a61584b 100644
--- a/Artemis/Artemis/Profiles/Layers/Models/LayerModel.cs
+++ b/Artemis/Artemis/Profiles/Layers/Models/LayerModel.cs
@@ -4,6 +4,7 @@ using System.Linq;
using System.Windows;
using System.Windows.Media;
using Artemis.Modules.Abstract;
+using Artemis.Profiles.Layers.Abstract;
using Artemis.Profiles.Layers.Animations;
using Artemis.Profiles.Layers.Conditions;
using Artemis.Profiles.Layers.Interfaces;
@@ -291,7 +292,7 @@ namespace Artemis.Profiles.Layers.Models
#region Layer type properties
public ILayerType LayerType { get; set; }
- public ILayerCondition LayerCondition { get; set; }
+ public LayerCondition LayerCondition { get; set; }
public ILayerAnimation LayerAnimation { get; set; }
#endregion
diff --git a/Artemis/Artemis/Profiles/Layers/Types/ConicalBrush/ConicalBrushType.cs b/Artemis/Artemis/Profiles/Layers/Types/ConicalBrush/ConicalBrushType.cs
index cb2e4cff2..f96b597ee 100644
--- a/Artemis/Artemis/Profiles/Layers/Types/ConicalBrush/ConicalBrushType.cs
+++ b/Artemis/Artemis/Profiles/Layers/Types/ConicalBrush/ConicalBrushType.cs
@@ -36,7 +36,7 @@ namespace Artemis.Profiles.Layers.Types.ConicalBrush
public ImageSource DrawThumbnail(LayerModel layer)
{
- _conicalGradientDrawerThumbnail.GradientStops = GetGradientStops(layer.Brush).Select(x => new Tuple(x.Offset, x.Color)).ToList();
+ _conicalGradientDrawerThumbnail.GradientStops = GetGradientStops(layer.Properties.Brush).Select(x => new Tuple(x.Offset, x.Color)).ToList();
_conicalGradientDrawerThumbnail.Update();
Rect thumbnailRect = new Rect(0, 0, 18, 18);
diff --git a/Artemis/Artemis/Profiles/Layers/Types/KeyPress/KeyPressType.cs b/Artemis/Artemis/Profiles/Layers/Types/KeyPress/KeyPressType.cs
index f0b463067..eebd4d68f 100644
--- a/Artemis/Artemis/Profiles/Layers/Types/KeyPress/KeyPressType.cs
+++ b/Artemis/Artemis/Profiles/Layers/Types/KeyPress/KeyPressType.cs
@@ -140,6 +140,9 @@ namespace Artemis.Profiles.Layers.Types.KeyPress
lock (_keyPressLayers)
{
+ // Ensure the layer has keypress properties
+ SetupProperties(_layerModel);
+
var properties = (KeyPressPropertiesModel) _layerModel.Properties;
var layer = LayerModel.CreateLayer();
layer.Properties.X = keyMatch.Value.X - properties.Scale/2;
diff --git a/Artemis/Artemis/Profiles/Lua/Modules/LuaKeybindModule.cs b/Artemis/Artemis/Profiles/Lua/Modules/LuaKeybindModule.cs
index 54c9a3ab8..ab608690a 100644
--- a/Artemis/Artemis/Profiles/Lua/Modules/LuaKeybindModule.cs
+++ b/Artemis/Artemis/Profiles/Lua/Modules/LuaKeybindModule.cs
@@ -33,10 +33,14 @@ namespace Artemis.Profiles.Lua.Modules
///
/// Name of the keybind
/// Hotkey in string format, per example: ALT+CTRL+SHIFT+D
+ /// The key type, either key up or key down
/// LUA function to call
/// Optional arguments for the passed function
- public void SetKeybind(string name, string hotKey, DynValue function, params DynValue[] args)
+ public void SetKeybind(string name, string hotKey, KeyType keyType, DynValue function, params DynValue[] args)
{
+ if (keyType != KeyType.KeyDown && keyType != KeyType.KeyUp)
+ throw new ScriptRuntimeException("Key type must either be KeyDown or KeyUp.");
+
var modifierKeys = ModifierKeys.None;
var key = Key.System;
var hotKeyParts = hotKey.Split('+').Select(p => p.Trim());
@@ -55,8 +59,8 @@ namespace Artemis.Profiles.Lua.Modules
var hk = new HotKey(key, modifierKeys);
var model = args != null
- ? new KeybindModel("LUA-" + name, hk, () => LuaManager.Call(function, args))
- : new KeybindModel("LUA-" + name, hk, () => LuaManager.Call(function));
+ ? new KeybindModel("LUA-" + name, hk, keyType, () => LuaManager.Call(function, args))
+ : new KeybindModel("LUA-" + name, hk, keyType, () => LuaManager.Call(function));
KeybindManager.AddOrUpdate(model);
@@ -88,4 +92,4 @@ namespace Artemis.Profiles.Lua.Modules
LuaManager.ProfileModel.OnProfileUpdatedEvent -= ProfileModelOnOnProfileUpdatedEvent;
}
}
-}
\ No newline at end of file
+}
diff --git a/Artemis/Artemis/Profiles/ProfileModel.cs b/Artemis/Artemis/Profiles/ProfileModel.cs
index 91de4d6b3..42f92a303 100644
--- a/Artemis/Artemis/Profiles/ProfileModel.cs
+++ b/Artemis/Artemis/Profiles/ProfileModel.cs
@@ -41,6 +41,7 @@ namespace Artemis.Profiles
private void OnOnProfileUpdatedEvent(object sender, EventArgs e)
{
+ ClearKeybinds();
ApplyKeybinds();
}
@@ -194,13 +195,8 @@ namespace Artemis.Profiles
}
public void Deactivate(LuaManager luaManager)
- {
- foreach (var layerModel in Layers)
- {
- for (var index = 0; index < layerModel.Properties.Conditions.Count; index++)
- KeybindManager.Remove($"{GameName}-{Name}-{layerModel.Name}-{index}");
- }
-
+ {
+ ClearKeybinds();
luaManager.ClearLua();
}
@@ -224,7 +220,7 @@ namespace Artemis.Profiles
public void ApplyKeybinds()
{
- foreach (var layerModel in Layers)
+ foreach (var layerModel in GetLayers())
{
for (var index = 0; index < layerModel.Properties.Conditions.Count; index++)
{
@@ -233,13 +229,34 @@ namespace Artemis.Profiles
continue;
// Create an action for the layer, the layer's specific condition type handles activation
- var action = new Action(() => layerModel.LayerCondition.KeybindTask(condition));
- var kb = new KeybindModel($"{GameName}-{Name}-{layerModel.Name}-{index}", condition.HotKey, action);
- KeybindManager.AddOrUpdate(kb);
+ if (condition.Operator == "held")
+ {
+ var downAction = new Action(() => layerModel.LayerCondition.KeybindTask(condition));
+ var downKb = new KeybindModel($"{GameName}-{Name}-{layerModel.Name}-{index}", condition.HotKey, KeyType.KeyDown, downAction);
+ var upAction = new Action(() => layerModel.LayerCondition.KeybindTask(condition));
+ var upKb = new KeybindModel($"{GameName}-{Name}-{layerModel.Name}-{index}", condition.HotKey, KeyType.KeyUp, upAction);
+ KeybindManager.AddOrUpdate(downKb);
+ KeybindManager.AddOrUpdate(upKb);
+ }
+ else
+ {
+ var action = new Action(() => layerModel.LayerCondition.KeybindTask(condition));
+ var kb = new KeybindModel($"{GameName}-{Name}-{layerModel.Name}-{index}", condition.HotKey, KeyType.KeyDown, action);
+ KeybindManager.AddOrUpdate(kb);
+ }
}
}
}
+ public void ClearKeybinds()
+ {
+ foreach (var layerModel in GetLayers())
+ {
+ for (var index = 0; index < layerModel.Properties.Conditions.Count; index++)
+ KeybindManager.Remove($"{GameName}-{Name}-{layerModel.Name}-{index}");
+ }
+ }
+
#region Compare
protected bool Equals(ProfileModel other)
@@ -270,4 +287,4 @@ namespace Artemis.Profiles
#endregion
}
-}
\ No newline at end of file
+}
diff --git a/Artemis/Artemis/Utilities/Keyboard/KeyboardHook.cs b/Artemis/Artemis/Utilities/Keyboard/KeyboardHook.cs
index 7579c942a..3c1d3bf71 100644
--- a/Artemis/Artemis/Utilities/Keyboard/KeyboardHook.cs
+++ b/Artemis/Artemis/Utilities/Keyboard/KeyboardHook.cs
@@ -1,27 +1,49 @@
using System.Threading.Tasks;
using System.Windows.Forms;
-using Open.WinKeyboardHook;
+using Gma.System.MouseKeyHook;
namespace Artemis.Utilities.Keyboard
{
public static class KeyboardHook
{
- private static KeyboardInterceptor _interceptor;
+ public delegate void KeyCallbackHandler(KeyEventArgs e);
- public delegate void KeyDownCallbackHandler(KeyEventArgs e);
+ public delegate void MouseCallbackHandler(MouseEventArgs e);
+
+ private static IKeyboardMouseEvents _globalHook;
public static void SetupKeyboardHook()
{
- _interceptor = new KeyboardInterceptor();
- _interceptor.KeyDown += VirtualKeyboardOnKeyDown;
- _interceptor.StartCapturing();
+ _globalHook = Hook.GlobalEvents();
+ _globalHook.KeyDown += GlobalHookOnKeyDown;
+ _globalHook.KeyUp += GlobalHookOnKeyUp;
+ _globalHook.MouseDown += GlobalHookOnMouseDown;
+ _globalHook.MouseUp += GlobalHookOnMouseUp;
}
- private static async void VirtualKeyboardOnKeyDown(object sender, KeyEventArgs keyEventArgs)
- {
- await Task.Factory.StartNew(() => { KeyDownCallback?.Invoke(keyEventArgs); });
+ private static async void GlobalHookOnMouseDown(object sender, MouseEventArgs e)
+ {
+ await Task.Factory.StartNew(() => { MouseDownCallback?.Invoke(e); });
}
-
- public static event KeyDownCallbackHandler KeyDownCallback;
+
+ private static async void GlobalHookOnMouseUp(object sender, MouseEventArgs e)
+ {
+ await Task.Factory.StartNew(() => { MouseUpCallback?.Invoke(e); });
+ }
+
+ private static async void GlobalHookOnKeyDown(object sender, KeyEventArgs e)
+ {
+ await Task.Factory.StartNew(() => { KeyDownCallback?.Invoke(e); });
+ }
+
+ private static async void GlobalHookOnKeyUp(object sender, KeyEventArgs e)
+ {
+ await Task.Factory.StartNew(() => { KeyUpCallback?.Invoke(e); });
+ }
+
+ public static event KeyCallbackHandler KeyDownCallback;
+ public static event KeyCallbackHandler KeyUpCallback;
+ public static event MouseCallbackHandler MouseDownCallback;
+ public static event MouseCallbackHandler MouseUpCallback;
}
-}
\ No newline at end of file
+}
diff --git a/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs b/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs
index ade255270..9419a5c1e 100644
--- a/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs
+++ b/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs
@@ -65,8 +65,8 @@ namespace Artemis.ViewModels
_loopManager = loopManager;
_moduleModel = moduleModel;
_dialogService = dialogService;
- _copyKeybind = new KeybindModel("copy", new HotKey(Key.C, ModifierKeys.Control), LayerToClipboard);
- _pasteKeybind = new KeybindModel("paste", new HotKey(Key.V, ModifierKeys.Control), ClipboardToLayer);
+ _copyKeybind = new KeybindModel("copy", new HotKey(Key.C, ModifierKeys.Control), KeyType.KeyDown, LayerToClipboard);
+ _pasteKeybind = new KeybindModel("paste", new HotKey(Key.V, ModifierKeys.Control), KeyType.KeyDown, ClipboardToLayer);
ProfileNames = new ObservableCollection();
Layers = new ObservableCollection();
diff --git a/Artemis/Artemis/packages.config b/Artemis/Artemis/packages.config
index d78a83092..df1dd799e 100644
--- a/Artemis/Artemis/packages.config
+++ b/Artemis/Artemis/packages.config
@@ -16,6 +16,7 @@
+
@@ -23,7 +24,6 @@
-