From e05191848693998c2c74ec25138ea230bd21c04f Mon Sep 17 00:00:00 2001 From: SpoinkyNL Date: Sun, 5 Feb 2017 19:16:30 +0100 Subject: [PATCH 01/16] Started work on keybinds --- Artemis/Artemis/Artemis.csproj | 1 + Artemis/Artemis/Managers/KeybindManager.cs | 85 +++++++++++++++++++ Artemis/Artemis/Managers/MainManager.cs | 2 - Artemis/Artemis/Settings/GeneralSettings.cs | 3 +- .../Utilities/Keyboard/KeyboardHook.cs | 4 +- .../Profiles/LayerConditionViewModel.cs | 51 ++++++++++- .../Views/Profiles/LayerConditionView.xaml | 6 +- 7 files changed, 143 insertions(+), 9 deletions(-) create mode 100644 Artemis/Artemis/Managers/KeybindManager.cs diff --git a/Artemis/Artemis/Artemis.csproj b/Artemis/Artemis/Artemis.csproj index e46fc944c..8baeec089 100644 --- a/Artemis/Artemis/Artemis.csproj +++ b/Artemis/Artemis/Artemis.csproj @@ -354,6 +354,7 @@ + diff --git a/Artemis/Artemis/Managers/KeybindManager.cs b/Artemis/Artemis/Managers/KeybindManager.cs new file mode 100644 index 000000000..65c7e37dc --- /dev/null +++ b/Artemis/Artemis/Managers/KeybindManager.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.Windows.Forms; +using System.Windows.Input; +using Artemis.Utilities.Keyboard; +using MahApps.Metro.Controls; +using KeyEventArgs = System.Windows.Forms.KeyEventArgs; + +namespace Artemis.Managers +{ + public static class KeybindManager + { + private static readonly Dictionary HotKeys; + + static KeybindManager() + { + KeyboardHook.KeyDownCallback += KeyboardHookOnKeyDownCallback; + HotKeys = new Dictionary(); + } + + private static void KeyboardHookOnKeyDownCallback(KeyEventArgs e) + { + // Don't trigger if none of the modifiers are held down + if (!e.Alt && !e.Control && !e.Shift) + return; + + // 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) + return; + + // Create a WPF ModifierKeys enum + var modifiers = ModifierKeys.None; + if (e.Alt) + modifiers = ModifierKeys.Alt; + if (e.Control) + if (modifiers == ModifierKeys.None) + modifiers = ModifierKeys.Control; + else + modifiers |= ModifierKeys.Control; + if (e.Shift) + if (modifiers == ModifierKeys.None) + modifiers = ModifierKeys.Shift; + else + modifiers |= ModifierKeys.Shift; + + // Create a HotKey object for comparison + var hotKey = new HotKey(KeyInterop.KeyFromVirtualKey(e.KeyValue), modifiers); + + // If the hotkey is present, invoke the action related to it + if (HotKeys.ContainsKey(hotKey)) + HotKeys[hotKey].Invoke(); + } + + /// + /// Registers a hotkey and executes the provided action when the hotkey is pressed + /// + /// The hotkey to register + /// The action to invoke on press + /// Returns true if key registed, false if already in use + public static bool RegisterHotkey(HotKey hotKey, Action action) + { + if (HotKeys.ContainsKey(hotKey)) + return false; + + HotKeys.Add(hotKey, action); + return true; + } + + /// + /// Unregister the given hotkey + /// + /// The hotkey to unregister + /// Returns true if unregistered, false if not found + public static bool UnregisterHotkey(HotKey hotKey) + { + if (!HotKeys.ContainsKey(hotKey)) + return false; + + HotKeys.Remove(hotKey); + return true; + } + } +} \ No newline at end of file diff --git a/Artemis/Artemis/Managers/MainManager.cs b/Artemis/Artemis/Managers/MainManager.cs index dba3b4657..5870984c5 100644 --- a/Artemis/Artemis/Managers/MainManager.cs +++ b/Artemis/Artemis/Managers/MainManager.cs @@ -39,7 +39,6 @@ namespace Artemis.Managers _processTimer.Start(); ProgramEnabled = false; - Running = false; // Create and start the web server GameStateWebServer = gameStateWebServer; @@ -71,7 +70,6 @@ namespace Artemis.Managers public PipeServer PipeServer { get; set; } public GameStateWebServer GameStateWebServer { get; set; } public bool ProgramEnabled { get; private set; } - public bool Running { get; private set; } public void Dispose() { diff --git a/Artemis/Artemis/Settings/GeneralSettings.cs b/Artemis/Artemis/Settings/GeneralSettings.cs index f56dbf807..b304c114d 100644 --- a/Artemis/Artemis/Settings/GeneralSettings.cs +++ b/Artemis/Artemis/Settings/GeneralSettings.cs @@ -73,11 +73,12 @@ namespace Artemis.Settings public void Save() { SettingsProvider.Save(this); + + Logging.SetupLogging(LogLevel); ApplyAutorun(); ApplyTheme(); ApplyGamestatePort(); ApplyScreenCaptureFPS(); - Logging.SetupLogging(LogLevel); } public void Reset(bool save = false) diff --git a/Artemis/Artemis/Utilities/Keyboard/KeyboardHook.cs b/Artemis/Artemis/Utilities/Keyboard/KeyboardHook.cs index 0fabc9f6a..7579c942a 100644 --- a/Artemis/Artemis/Utilities/Keyboard/KeyboardHook.cs +++ b/Artemis/Artemis/Utilities/Keyboard/KeyboardHook.cs @@ -18,10 +18,10 @@ namespace Artemis.Utilities.Keyboard } private static async void VirtualKeyboardOnKeyDown(object sender, KeyEventArgs keyEventArgs) - { + { await Task.Factory.StartNew(() => { KeyDownCallback?.Invoke(keyEventArgs); }); } - + public static event KeyDownCallbackHandler KeyDownCallback; } } \ No newline at end of file diff --git a/Artemis/Artemis/ViewModels/Profiles/LayerConditionViewModel.cs b/Artemis/Artemis/ViewModels/Profiles/LayerConditionViewModel.cs index d20f93dfc..b70d8792c 100644 --- a/Artemis/Artemis/ViewModels/Profiles/LayerConditionViewModel.cs +++ b/Artemis/Artemis/ViewModels/Profiles/LayerConditionViewModel.cs @@ -15,6 +15,19 @@ namespace Artemis.ViewModels.Profiles private readonly LayerEditorViewModel _editorViewModel; + private readonly NamedOperator[] _hotkeyOperators = + { + new NamedOperator("Pressed", "enable"), + new NamedOperator("Held down", "disable") + }; + + private readonly GeneralHelpers.PropertyCollection[] _hotkeyProperties = + { + new GeneralHelpers.PropertyCollection {Display = "Enable when hotkey", Type = "hotkeyEnable"}, + new GeneralHelpers.PropertyCollection {Display = "Disable when hotkey", Type = "hotkeyDisable"}, + new GeneralHelpers.PropertyCollection {Display = "Toggle when hotkey", Type = "hotkeyToggle"} + }; + private readonly NamedOperator[] _int32Operators = { new NamedOperator("Lower than", "<"), @@ -41,6 +54,7 @@ namespace Artemis.ViewModels.Profiles }; private bool _enumValueIsVisible; + private bool _keybindIsVisible; private GeneralHelpers.PropertyCollection _selectedDataModelProp; private string _selectedEnum; private NamedOperator _selectedOperator; @@ -52,9 +66,10 @@ namespace Artemis.ViewModels.Profiles _editorViewModel = editorViewModel; ConditionModel = conditionModel; - DataModelProps = editorViewModel.DataModelProps; Operators = new BindableCollection(); Enums = new BindableCollection(); + DataModelProps = new BindableCollection(_hotkeyProperties); + DataModelProps.AddRange(editorViewModel.DataModelProps); PropertyChanged += MapViewToModel; MapModelToView(); @@ -112,6 +127,17 @@ namespace Artemis.ViewModels.Profiles } } + public bool KeybindIsVisible + { + get { return _keybindIsVisible; } + set + { + if (value == _keybindIsVisible) return; + _keybindIsVisible = value; + NotifyOfPropertyChange(); + } + } + public NamedOperator SelectedOperator { get { return _selectedOperator; } @@ -190,6 +216,15 @@ namespace Artemis.ViewModels.Profiles Operators.AddRange(_stringOperators); UserValueIsVisible = true; break; + case "hotkeyEnable": + case "hotkeyDisable": + Operators.AddRange(_hotkeyOperators); + KeybindIsVisible = true; + break; + case "hotkeyToggle": + Operators.Add(_hotkeyOperators[0]); + KeybindIsVisible = true; + break; default: Operators.AddRange(_operators); UserValueIsVisible = true; @@ -207,7 +242,7 @@ namespace Artemis.ViewModels.Profiles Operators.Add(new NamedOperator("Increased", "increased")); } } - + SetupUserValueInput(); } @@ -215,13 +250,21 @@ namespace Artemis.ViewModels.Profiles { UserValueIsVisible = false; EnumValueIsVisible = false; + KeybindIsVisible = false; + // Event operators don't have any form of input if (SelectedOperator.Value == "changed" || SelectedOperator.Value == "decreased" || SelectedOperator.Value == "increased") return; - if (SelectedDataModelProp.Type == "Boolean") + if (SelectedDataModelProp.Type.Contains("hotkey")) + { + KeybindIsVisible = true; + } + else if (SelectedDataModelProp.Type == "Boolean") + { EnumValueIsVisible = true; + } else if (SelectedDataModelProp.EnumValues != null) { Enums.Clear(); @@ -229,7 +272,9 @@ namespace Artemis.ViewModels.Profiles EnumValueIsVisible = true; } else + { UserValueIsVisible = true; + } } /// diff --git a/Artemis/Artemis/Views/Profiles/LayerConditionView.xaml b/Artemis/Artemis/Views/Profiles/LayerConditionView.xaml index 0b62d71cc..77ea18a79 100644 --- a/Artemis/Artemis/Views/Profiles/LayerConditionView.xaml +++ b/Artemis/Artemis/Views/Profiles/LayerConditionView.xaml @@ -5,6 +5,7 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:cal="http://www.caliburnproject.org" xmlns:utilities="clr-namespace:Artemis.Utilities" + xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls" mc:Ignorable="d" d:DesignWidth="613.296" Height="46"> @@ -50,8 +51,11 @@ + + + - + Date: Mon, 6 Feb 2017 15:01:58 +0100 Subject: [PATCH 02/16] Implemented keybinds on layers --- Artemis/Artemis/Artemis.csproj | 1 + Artemis/Artemis/Managers/KeybindManager.cs | 94 ++++++++++--------- Artemis/Artemis/Models/KeybindModel.cs | 25 +++++ .../Layers/Conditions/DataModelCondition.cs | 43 ++++++++- .../Layers/Conditions/EventCondition.cs | 37 ++++++-- .../Layers/Interfaces/ILayerCondition.cs | 1 + .../Layers/Models/LayerConditionModel.cs | 2 + Artemis/Artemis/Profiles/ProfileModel.cs | 21 +++++ .../ViewModels/ProfileEditorViewModel.cs | 3 + .../Profiles/LayerConditionViewModel.cs | 79 ++++++++++------ .../Views/Profiles/LayerConditionView.xaml | 6 +- 11 files changed, 220 insertions(+), 92 deletions(-) create mode 100644 Artemis/Artemis/Models/KeybindModel.cs diff --git a/Artemis/Artemis/Artemis.csproj b/Artemis/Artemis/Artemis.csproj index 8baeec089..fa1c89fff 100644 --- a/Artemis/Artemis/Artemis.csproj +++ b/Artemis/Artemis/Artemis.csproj @@ -364,6 +364,7 @@ + diff --git a/Artemis/Artemis/Managers/KeybindManager.cs b/Artemis/Artemis/Managers/KeybindManager.cs index 65c7e37dc..263d299df 100644 --- a/Artemis/Artemis/Managers/KeybindManager.cs +++ b/Artemis/Artemis/Managers/KeybindManager.cs @@ -1,7 +1,8 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; +using System.Linq; using System.Windows.Forms; using System.Windows.Input; +using Artemis.Models; using Artemis.Utilities.Keyboard; using MahApps.Metro.Controls; using KeyEventArgs = System.Windows.Forms.KeyEventArgs; @@ -10,76 +11,77 @@ namespace Artemis.Managers { public static class KeybindManager { - private static readonly Dictionary HotKeys; + private static readonly List KeybindModels = new List(); static KeybindManager() { KeyboardHook.KeyDownCallback += KeyboardHookOnKeyDownCallback; - HotKeys = new Dictionary(); } private static void KeyboardHookOnKeyDownCallback(KeyEventArgs e) { - // Don't trigger if none of the modifiers are held down - if (!e.Alt && !e.Control && !e.Shift) - return; - // 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) return; + // Create a WPF ModifierKeys enum + var modifiers = ModifierKeysFromBooleans(e.Alt, e.Control, e.Shift); + + // Create a HotKey object for comparison + var hotKey = new HotKey(KeyInterop.KeyFromVirtualKey(e.KeyValue), modifiers); + + foreach (var keybindModel in KeybindModels) + keybindModel.InvokeIfMatched(hotKey); + } + + public static void AddOrUpdate(KeybindModel keybindModel) + { + var existing = KeybindModels.FirstOrDefault(k => k.Name == keybindModel.Name); + if (existing != null) + KeybindModels.Remove(existing); + + KeybindModels.Add(keybindModel); + } + + public static void Remove(KeybindModel keybindModel) + { + if (KeybindModels.Contains(keybindModel)) + KeybindModels.Remove(keybindModel); + } + + public static void Remove(string name) + { + var existing = KeybindModels.FirstOrDefault(k => k.Name == name); + if (existing != null) + 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 var modifiers = ModifierKeys.None; - if (e.Alt) + if (alt) modifiers = ModifierKeys.Alt; - if (e.Control) + if (control) if (modifiers == ModifierKeys.None) modifiers = ModifierKeys.Control; else modifiers |= ModifierKeys.Control; - if (e.Shift) + if (shift) if (modifiers == ModifierKeys.None) modifiers = ModifierKeys.Shift; else modifiers |= ModifierKeys.Shift; - // Create a HotKey object for comparison - var hotKey = new HotKey(KeyInterop.KeyFromVirtualKey(e.KeyValue), modifiers); - - // If the hotkey is present, invoke the action related to it - if (HotKeys.ContainsKey(hotKey)) - HotKeys[hotKey].Invoke(); - } - - /// - /// Registers a hotkey and executes the provided action when the hotkey is pressed - /// - /// The hotkey to register - /// The action to invoke on press - /// Returns true if key registed, false if already in use - public static bool RegisterHotkey(HotKey hotKey, Action action) - { - if (HotKeys.ContainsKey(hotKey)) - return false; - - HotKeys.Add(hotKey, action); - return true; - } - - /// - /// Unregister the given hotkey - /// - /// The hotkey to unregister - /// Returns true if unregistered, false if not found - public static bool UnregisterHotkey(HotKey hotKey) - { - if (!HotKeys.ContainsKey(hotKey)) - return false; - - HotKeys.Remove(hotKey); - return true; + return modifiers; } } } \ No newline at end of file diff --git a/Artemis/Artemis/Models/KeybindModel.cs b/Artemis/Artemis/Models/KeybindModel.cs new file mode 100644 index 000000000..685894c0c --- /dev/null +++ b/Artemis/Artemis/Models/KeybindModel.cs @@ -0,0 +1,25 @@ +using System; +using MahApps.Metro.Controls; + +namespace Artemis.Models +{ + public class KeybindModel + { + public KeybindModel(string name, HotKey hotKey, Action action) + { + Name = name; + HotKey = hotKey; + Action = action; + } + + public string Name { get; set; } + public HotKey HotKey { get; set; } + public Action Action { get; set; } + + public void InvokeIfMatched(HotKey hotKey) + { + if (hotKey.Equals(HotKey)) + Action.Invoke(); + } + } +} \ 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 255b059b8..190d7e1e3 100644 --- a/Artemis/Artemis/Profiles/Layers/Conditions/DataModelCondition.cs +++ b/Artemis/Artemis/Profiles/Layers/Conditions/DataModelCondition.cs @@ -1,5 +1,7 @@ using System; using System.Linq; +using System.Windows; +using System.Windows.Forms; using Artemis.Modules.Abstract; using Artemis.Profiles.Layers.Interfaces; using Artemis.Profiles.Layers.Models; @@ -8,21 +10,52 @@ namespace Artemis.Profiles.Layers.Conditions { public class DataModelCondition : ILayerCondition { + private DateTime _lastKeypress; + public bool HotKeyMet { get; set; } + private static readonly TimeSpan Delay = TimeSpan.FromMilliseconds((SystemParameters.KeyboardDelay + 1) * 250); + public bool ConditionsMet(LayerModel layerModel, ModuleDataModel dataModel) { lock (layerModel.Properties.Conditions) { + var checkConditions = layerModel.Properties.Conditions.Where(c => !c.Field.Contains("hotkey")); + var conditionMet = false; switch (layerModel.Properties.ConditionType) { case ConditionType.AnyMet: - return layerModel.Properties.Conditions.Any(cm => cm.ConditionMet(dataModel)); + conditionMet = HotKeyMet || checkConditions.Any(cm => cm.ConditionMet(dataModel)); + break; case ConditionType.AllMet: - return layerModel.Properties.Conditions.All(cm => cm.ConditionMet(dataModel)); + conditionMet = HotKeyMet && checkConditions.All(cm => cm.ConditionMet(dataModel)); + break; case ConditionType.NoneMet: - return !layerModel.Properties.Conditions.Any(cm => cm.ConditionMet(dataModel)); - default: - return false; + conditionMet = !HotKeyMet && !checkConditions.Any(cm => cm.ConditionMet(dataModel)); + 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) + { + _lastKeypress = DateTime.Now; + switch (condition.Field) + { + case "hotkeyEnable": + HotKeyMet = true; + break; + case "hotkeyDisable": + HotKeyMet = false; + break; + case "hotkeyToggle": + HotKeyMet = !HotKeyMet; + break; } } } diff --git a/Artemis/Artemis/Profiles/Layers/Conditions/EventCondition.cs b/Artemis/Artemis/Profiles/Layers/Conditions/EventCondition.cs index 5db52f958..699f9f810 100644 --- a/Artemis/Artemis/Profiles/Layers/Conditions/EventCondition.cs +++ b/Artemis/Artemis/Profiles/Layers/Conditions/EventCondition.cs @@ -1,37 +1,60 @@ -using System; -using System.Linq; +using System.Linq; using Artemis.Modules.Abstract; using Artemis.Profiles.Layers.Interfaces; using Artemis.Profiles.Layers.Models; +using Newtonsoft.Json; namespace Artemis.Profiles.Layers.Conditions { public class EventCondition : ILayerCondition { + [JsonIgnore] + public bool HotKeyMet { get;set; } + public bool ConditionsMet(LayerModel layerModel, ModuleDataModel dataModel) { lock (layerModel.Properties.Conditions) { + var checkConditions = layerModel.Properties.Conditions.Where(c => !c.Field.Contains("hotkey")); var conditionsMet = false; switch (layerModel.Properties.ConditionType) { case ConditionType.AnyMet: - conditionsMet = layerModel.Properties.Conditions.Any(cm => cm.ConditionMet(dataModel)); + conditionsMet = HotKeyMet || checkConditions.Any(cm => cm.ConditionMet(dataModel)); break; case ConditionType.AllMet: - conditionsMet = layerModel.Properties.Conditions.All(cm => cm.ConditionMet(dataModel)); + conditionsMet = HotKeyMet && checkConditions.All(cm => cm.ConditionMet(dataModel)); break; case ConditionType.NoneMet: - conditionsMet = !layerModel.Properties.Conditions.Any(cm => cm.ConditionMet(dataModel)); + conditionsMet = !HotKeyMet && !checkConditions.Any(cm => cm.ConditionMet(dataModel)); break; } + layerModel.EventProperties.Update(layerModel, conditionsMet); - if (conditionsMet && layerModel.EventProperties.CanTrigger) - layerModel.EventProperties.TriggerEvent(layerModel); + if (conditionsMet) + layerModel.EventProperties.TriggerEvent(layerModel); + if (layerModel.EventProperties.MustStop(layerModel)) + HotKeyMet = false; return layerModel.EventProperties.MustDraw; } } + + public void KeybindTask(LayerConditionModel condition) + { + switch (condition.Field) + { + case "hotkeyEnable": + HotKeyMet = true; + break; + case "hotkeyDisable": + HotKeyMet = false; + break; + case "hotkeyToggle": + HotKeyMet = !HotKeyMet; + break; + } + } } } \ No newline at end of file diff --git a/Artemis/Artemis/Profiles/Layers/Interfaces/ILayerCondition.cs b/Artemis/Artemis/Profiles/Layers/Interfaces/ILayerCondition.cs index ee2ff364b..ab19a5dcc 100644 --- a/Artemis/Artemis/Profiles/Layers/Interfaces/ILayerCondition.cs +++ b/Artemis/Artemis/Profiles/Layers/Interfaces/ILayerCondition.cs @@ -6,5 +6,6 @@ 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/LayerConditionModel.cs b/Artemis/Artemis/Profiles/Layers/Models/LayerConditionModel.cs index 71de0a2ce..560d74408 100644 --- a/Artemis/Artemis/Profiles/Layers/Models/LayerConditionModel.cs +++ b/Artemis/Artemis/Profiles/Layers/Models/LayerConditionModel.cs @@ -3,6 +3,7 @@ using System.Globalization; using Artemis.Modules.Abstract; using Artemis.Utilities; using DynamicExpresso; +using MahApps.Metro.Controls; namespace Artemis.Profiles.Layers.Models { @@ -20,6 +21,7 @@ namespace Artemis.Profiles.Layers.Models public string Value { get; set; } public string Operator { get; set; } public string Type { get; set; } + public HotKey HotKey { get; set; } public bool ConditionMet(ModuleDataModel subject) { diff --git a/Artemis/Artemis/Profiles/ProfileModel.cs b/Artemis/Artemis/Profiles/ProfileModel.cs index 610e44749..9cf4c7fd4 100644 --- a/Artemis/Artemis/Profiles/ProfileModel.cs +++ b/Artemis/Artemis/Profiles/ProfileModel.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Drawing; using System.IO; using System.Linq; @@ -184,11 +185,13 @@ namespace Artemis.Profiles public void Activate(LuaManager luaManager) { + ApplyKeybinds(); luaManager.SetupLua(this); } public void Deactivate(LuaManager luaManager) { + KeybindManager.Clear(); luaManager.ClearLua(); } @@ -210,6 +213,24 @@ namespace Artemis.Profiles return layer; } + public void ApplyKeybinds() + { + foreach (var layerModel in Layers) + { + for (var index = 0; index < layerModel.Properties.Conditions.Count; index++) + { + var condition = layerModel.Properties.Conditions[index]; + if (condition.Field == null || !condition.Field.Contains("hotkey")) + 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); + } + } + } + #region Compare protected bool Equals(ProfileModel other) diff --git a/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs b/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs index 5fbb1bfed..1092c51d9 100644 --- a/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs +++ b/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs @@ -319,6 +319,9 @@ namespace Artemis.ViewModels { Thread.Sleep(100); SelectedLayer = selectModel; + + // Let the profile reapply keybinds after messing with layers + SelectedProfile.ApplyKeybinds(); }); } diff --git a/Artemis/Artemis/ViewModels/Profiles/LayerConditionViewModel.cs b/Artemis/Artemis/ViewModels/Profiles/LayerConditionViewModel.cs index b70d8792c..031447180 100644 --- a/Artemis/Artemis/ViewModels/Profiles/LayerConditionViewModel.cs +++ b/Artemis/Artemis/ViewModels/Profiles/LayerConditionViewModel.cs @@ -3,6 +3,7 @@ using System.Linq; using Artemis.Profiles.Layers.Models; using Artemis.Utilities; using Caliburn.Micro; +using MahApps.Metro.Controls; namespace Artemis.ViewModels.Profiles { @@ -18,14 +19,14 @@ namespace Artemis.ViewModels.Profiles private readonly NamedOperator[] _hotkeyOperators = { new NamedOperator("Pressed", "enable"), - new NamedOperator("Held down", "disable") + new NamedOperator("Held down", "held") }; private readonly GeneralHelpers.PropertyCollection[] _hotkeyProperties = { - new GeneralHelpers.PropertyCollection {Display = "Enable when hotkey", Type = "hotkeyEnable"}, - new GeneralHelpers.PropertyCollection {Display = "Disable when hotkey", Type = "hotkeyDisable"}, - new GeneralHelpers.PropertyCollection {Display = "Toggle when hotkey", Type = "hotkeyToggle"} + new GeneralHelpers.PropertyCollection {Display = "Enable when hotkey", Type = "hotkeyEnable", Path = "hotkeyEnable"}, + new GeneralHelpers.PropertyCollection {Display = "Disable when hotkey", Type = "hotkeyDisable", Path = "hotkeyDisable"}, + new GeneralHelpers.PropertyCollection {Display = "Toggle when hotkey", Type = "hotkeyToggle", Path = "hotkeyToggle"} }; private readonly NamedOperator[] _int32Operators = @@ -53,11 +54,14 @@ namespace Artemis.ViewModels.Profiles new NamedOperator("Ends with", ".EndsWith") }; - private bool _enumValueIsVisible; + private HotKey _hotKey; + private bool _keybindIsVisible; private GeneralHelpers.PropertyCollection _selectedDataModelProp; - private string _selectedEnum; + private string _selectedDropdownValue; private NamedOperator _selectedOperator; + + private bool _userDropdownValueIsVisible; private string _userValue; private bool _userValueIsVisible; @@ -67,7 +71,7 @@ namespace Artemis.ViewModels.Profiles ConditionModel = conditionModel; Operators = new BindableCollection(); - Enums = new BindableCollection(); + DropdownValues = new BindableCollection(); DataModelProps = new BindableCollection(_hotkeyProperties); DataModelProps.AddRange(editorViewModel.DataModelProps); @@ -80,7 +84,7 @@ namespace Artemis.ViewModels.Profiles public BindableCollection DataModelProps { get; set; } public BindableCollection Operators { get; set; } - public BindableCollection Enums { get; set; } + public BindableCollection DropdownValues { get; set; } public string UserValue { @@ -93,6 +97,17 @@ namespace Artemis.ViewModels.Profiles } } + public HotKey HotKey + { + get { return _hotKey; } + set + { + if (Equals(value, _hotKey)) return; + _hotKey = value; + NotifyOfPropertyChange(() => HotKey); + } + } + public GeneralHelpers.PropertyCollection SelectedDataModelProp { get { return _selectedDataModelProp; } @@ -116,14 +131,14 @@ namespace Artemis.ViewModels.Profiles } } - public bool EnumValueIsVisible + public bool UserDropdownValueIsVisible { - get { return _enumValueIsVisible; } + get { return _userDropdownValueIsVisible; } set { - if (value == _enumValueIsVisible) return; - _enumValueIsVisible = value; - NotifyOfPropertyChange(() => EnumValueIsVisible); + if (value == _userDropdownValueIsVisible) return; + _userDropdownValueIsVisible = value; + NotifyOfPropertyChange(() => UserDropdownValueIsVisible); } } @@ -149,14 +164,14 @@ namespace Artemis.ViewModels.Profiles } } - public string SelectedEnum + public string SelectedDropdownValue { - get { return _selectedEnum; } + get { return _selectedDropdownValue; } set { - if (value == _selectedEnum) return; - _selectedEnum = value; - NotifyOfPropertyChange(() => SelectedEnum); + if (value == _selectedDropdownValue) return; + _selectedDropdownValue = value; + NotifyOfPropertyChange(() => SelectedDropdownValue); } } @@ -168,9 +183,10 @@ namespace Artemis.ViewModels.Profiles SelectedDataModelProp = DataModelProps.FirstOrDefault(m => m.Path == ConditionModel.Field); // Select the operator SelectedOperator = Operators.FirstOrDefault(o => o.Value == ConditionModel.Operator); + HotKey = ConditionModel.HotKey; if (ConditionModel.Type == "Enum" || ConditionModel.Type == "Boolean") - SelectedEnum = ConditionModel.Value; + SelectedDropdownValue = ConditionModel.Value; else UserValue = ConditionModel.Value; @@ -182,9 +198,10 @@ namespace Artemis.ViewModels.Profiles ConditionModel.Field = SelectedDataModelProp.Path; ConditionModel.Operator = SelectedOperator.Value; ConditionModel.Type = SelectedDataModelProp.Type; + ConditionModel.HotKey = HotKey; if (ConditionModel.Type == "Enum" || ConditionModel.Type == "Boolean") - ConditionModel.Value = SelectedEnum; + ConditionModel.Value = SelectedDropdownValue; else ConditionModel.Value = UserValue; } @@ -197,7 +214,7 @@ namespace Artemis.ViewModels.Profiles public void SetupPropertyInput() { Operators.Clear(); - Enums.Clear(); + DropdownValues.Clear(); switch (SelectedDataModelProp.Type) { @@ -208,9 +225,9 @@ namespace Artemis.ViewModels.Profiles break; case "Boolean": Operators.AddRange(_boolOperators); - Enums.Add("True"); - Enums.Add("False"); - EnumValueIsVisible = true; + DropdownValues.Add("True"); + DropdownValues.Add("False"); + UserDropdownValueIsVisible = true; break; case "String": Operators.AddRange(_stringOperators); @@ -242,14 +259,14 @@ namespace Artemis.ViewModels.Profiles Operators.Add(new NamedOperator("Increased", "increased")); } } - + SetupUserValueInput(); } private void SetupUserValueInput() { UserValueIsVisible = false; - EnumValueIsVisible = false; + UserDropdownValueIsVisible = false; KeybindIsVisible = false; // Event operators don't have any form of input @@ -257,19 +274,19 @@ namespace Artemis.ViewModels.Profiles SelectedOperator.Value == "increased") return; - if (SelectedDataModelProp.Type.Contains("hotkey")) + if (SelectedDataModelProp.Type != null && SelectedDataModelProp.Type.Contains("hotkey")) { KeybindIsVisible = true; } else if (SelectedDataModelProp.Type == "Boolean") { - EnumValueIsVisible = true; + UserDropdownValueIsVisible = true; } else if (SelectedDataModelProp.EnumValues != null) { - Enums.Clear(); - Enums.AddRange(SelectedDataModelProp.EnumValues); - EnumValueIsVisible = true; + DropdownValues.Clear(); + DropdownValues.AddRange(SelectedDataModelProp.EnumValues); + UserDropdownValueIsVisible = true; } else { diff --git a/Artemis/Artemis/Views/Profiles/LayerConditionView.xaml b/Artemis/Artemis/Views/Profiles/LayerConditionView.xaml index 77ea18a79..a2981b7f6 100644 --- a/Artemis/Artemis/Views/Profiles/LayerConditionView.xaml +++ b/Artemis/Artemis/Views/Profiles/LayerConditionView.xaml @@ -52,13 +52,13 @@ - + - - + /// 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 @@ - From ef19348e53201fac5fcd9e624d003606965348b0 Mon Sep 17 00:00:00 2001 From: SpoinkyNL Date: Tue, 21 Feb 2017 22:16:03 +0100 Subject: [PATCH 08/16] Reworked key-held keybind --- Artemis/Artemis/Managers/KeybindManager.cs | 2 +- Artemis/Artemis/Models/KeybindModel.cs | 2 +- .../Layers/Abstract/LayerCondition.cs | 30 +++++++++++++++++- .../Layers/Conditions/DataModelCondition.cs | 31 +++---------------- .../Layers/Conditions/EventCondition.cs | 28 ++--------------- Artemis/Artemis/Profiles/ProfileModel.cs | 27 ++++++++++------ 6 files changed, 55 insertions(+), 65 deletions(-) diff --git a/Artemis/Artemis/Managers/KeybindManager.cs b/Artemis/Artemis/Managers/KeybindManager.cs index 84880c46c..b75ee5741 100644 --- a/Artemis/Artemis/Managers/KeybindManager.cs +++ b/Artemis/Artemis/Managers/KeybindManager.cs @@ -37,7 +37,7 @@ namespace Artemis.Managers var hotKey = new HotKey(KeyInterop.KeyFromVirtualKey(keyEventArgs.KeyValue), modifiers); foreach (var keybindModel in KeybindModels) - keybindModel.InvokeIfMatched(hotKey, keyType); + keybindModel.InvokeIfMatched(hotKey, keyType); } private static void ProcessMouse(MouseEventArgs mouseEventArgs, KeyType keyType) diff --git a/Artemis/Artemis/Models/KeybindModel.cs b/Artemis/Artemis/Models/KeybindModel.cs index e1d71ab56..0f9c3714c 100644 --- a/Artemis/Artemis/Models/KeybindModel.cs +++ b/Artemis/Artemis/Models/KeybindModel.cs @@ -34,7 +34,7 @@ namespace Artemis.Models return; if (hotKey.Equals(HotKey)) - Action?.Invoke(); + Action?.Invoke(); } public void InvokeIfMatched(MouseButtons mouseButtons, KeyType keyType) diff --git a/Artemis/Artemis/Profiles/Layers/Abstract/LayerCondition.cs b/Artemis/Artemis/Profiles/Layers/Abstract/LayerCondition.cs index 06503f7e5..eff5be489 100644 --- a/Artemis/Artemis/Profiles/Layers/Abstract/LayerCondition.cs +++ b/Artemis/Artemis/Profiles/Layers/Abstract/LayerCondition.cs @@ -1,11 +1,39 @@ using Artemis.Modules.Abstract; using Artemis.Profiles.Layers.Models; +using Newtonsoft.Json; namespace Artemis.Profiles.Layers.Abstract { public abstract class LayerCondition { + [JsonIgnore] + public bool HotKeyMet { get; set; } + public abstract bool ConditionsMet(LayerModel layerModel, ModuleDataModel dataModel); - public abstract void KeybindTask(LayerConditionModel condition); + + + public void KeyDownTask(LayerConditionModel condition) + { + switch (condition.Field) + { + case "hotkeyEnable": + HotKeyMet = true; + break; + case "hotkeyDisable": + HotKeyMet = false; + break; + case "hotkeyToggle": + HotKeyMet = !HotKeyMet; + break; + } + } + + public void KeyUpTask(LayerConditionModel condition) + { + if (condition.Field == "hotkeyEnable") + HotKeyMet = false; + else + HotKeyMet = true; + } } } \ 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 8f5560da4..7588a3055 100644 --- a/Artemis/Artemis/Profiles/Layers/Conditions/DataModelCondition.cs +++ b/Artemis/Artemis/Profiles/Layers/Conditions/DataModelCondition.cs @@ -1,24 +1,18 @@ -using System; -using System.Collections.Generic; +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 : LayerCondition { - public bool HotKeyMet { get; set; } - public override bool ConditionsMet(LayerModel layerModel, ModuleDataModel dataModel) { lock (layerModel.Properties.Conditions) { - var checkConditions = layerModel.Properties.Conditions - .Where(c => c.Field != null && !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); @@ -41,24 +35,7 @@ namespace Artemis.Profiles.Layers.Conditions } } - public override void KeybindTask(LayerConditionModel condition) - { - switch (condition.Field) - { - case "hotkeyEnable": - HotKeyMet = true; - break; - case "hotkeyDisable": - HotKeyMet = false; - break; - case "hotkeyToggle": - HotKeyMet = !HotKeyMet; - break; - } - } - - private static bool SimpleConditionsMet(LayerModel layerModel, ModuleDataModel dataModel, - IEnumerable checkConditions) + private static bool SimpleConditionsMet(LayerModel layerModel, ModuleDataModel dataModel, IEnumerable checkConditions) { switch (layerModel.Properties.ConditionType) { @@ -73,4 +50,4 @@ namespace Artemis.Profiles.Layers.Conditions } } } -} \ No newline at end of file +} diff --git a/Artemis/Artemis/Profiles/Layers/Conditions/EventCondition.cs b/Artemis/Artemis/Profiles/Layers/Conditions/EventCondition.cs index bcc1c3f01..9856d9537 100644 --- a/Artemis/Artemis/Profiles/Layers/Conditions/EventCondition.cs +++ b/Artemis/Artemis/Profiles/Layers/Conditions/EventCondition.cs @@ -2,23 +2,17 @@ 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 : LayerCondition { - [JsonIgnore] - public bool HotKeyMet { get; set; } - public override bool ConditionsMet(LayerModel layerModel, ModuleDataModel dataModel) { lock (layerModel.Properties.Conditions) { - var checkConditions = layerModel.Properties.Conditions - .Where(c => c.Field != null && !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); @@ -48,24 +42,8 @@ namespace Artemis.Profiles.Layers.Conditions } } - public override void KeybindTask(LayerConditionModel condition) - { - switch (condition.Field) - { - case "hotkeyEnable": - HotKeyMet = true; - break; - case "hotkeyDisable": - HotKeyMet = false; - break; - case "hotkeyToggle": - HotKeyMet = !HotKeyMet; - break; - } - } - private static bool SimpleConditionsMet(LayerModel layerModel, ModuleDataModel dataModel, - IEnumerable checkConditions) + private static bool SimpleConditionsMet(LayerModel layerModel, ModuleDataModel dataModel, IEnumerable checkConditions) { switch (layerModel.Properties.ConditionType) { @@ -80,4 +58,4 @@ namespace Artemis.Profiles.Layers.Conditions } } } -} \ No newline at end of file +} diff --git a/Artemis/Artemis/Profiles/ProfileModel.cs b/Artemis/Artemis/Profiles/ProfileModel.cs index 42f92a303..d7e7a4ac8 100644 --- a/Artemis/Artemis/Profiles/ProfileModel.cs +++ b/Artemis/Artemis/Profiles/ProfileModel.cs @@ -19,10 +19,13 @@ namespace Artemis.Profiles public class ProfileModel { private readonly char[] _invalidFileNameChars; + private List _profileBinds; public ProfileModel() { _invalidFileNameChars = Path.GetInvalidFileNameChars(); + _profileBinds = new List(); + Layers = new ChildItemCollection(this); OnProfileUpdatedEvent += OnOnProfileUpdatedEvent; } @@ -220,6 +223,7 @@ namespace Artemis.Profiles public void ApplyKeybinds() { + _profileBinds.Clear(); foreach (var layerModel in GetLayers()) { for (var index = 0; index < layerModel.Properties.Conditions.Count; index++) @@ -231,18 +235,23 @@ namespace Artemis.Profiles // Create an action for the layer, the layer's specific condition type handles activation 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); + var downAction = new Action(() => layerModel.LayerCondition.KeyDownTask(condition)); + var downKb = new KeybindModel($"{GameName}-{Name}-{layerModel.Name}-down-{index}", condition.HotKey, KeyType.KeyDown, downAction); + var upAction = new Action(() => layerModel.LayerCondition.KeyUpTask(condition)); + var upKb = new KeybindModel($"{GameName}-{Name}-{layerModel.Name}-up-{index}", condition.HotKey, KeyType.KeyUp, upAction); + KeybindManager.AddOrUpdate(downKb); KeybindManager.AddOrUpdate(upKb); + _profileBinds.Add(downKb); + _profileBinds.Add(upKb); } else { - var action = new Action(() => layerModel.LayerCondition.KeybindTask(condition)); + var action = new Action(() => layerModel.LayerCondition.KeyDownTask(condition)); var kb = new KeybindModel($"{GameName}-{Name}-{layerModel.Name}-{index}", condition.HotKey, KeyType.KeyDown, action); + KeybindManager.AddOrUpdate(kb); + _profileBinds.Add(kb); } } } @@ -250,11 +259,9 @@ namespace Artemis.Profiles 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}"); - } + foreach (var keybindModel in _profileBinds) + KeybindManager.Remove(keybindModel); + _profileBinds.Clear(); } #region Compare From 809e38da7e847a16b68801d76b6078f20fb33179 Mon Sep 17 00:00:00 2001 From: SpoinkyNL Date: Sat, 25 Feb 2017 18:25:02 +0100 Subject: [PATCH 09/16] Added window resize support to the profile editor Fixed UI alignments in profile editor --- .../Artemis/InjectionModules/BaseModules.cs | 2 +- Artemis/Artemis/Models/KeybindModel.cs | 6 +- .../Games/AssettoCorsa/AssettoCorsaView.xaml | 83 +-- .../CounterStrike/CounterStrikeView.xaml | 73 +-- .../CounterStrike/CounterStrikeViewModel.cs | 23 +- .../Modules/Games/Dota2/Dota2View.xaml | 58 +- .../Modules/Games/Dota2/Dota2ViewModel.cs | 24 +- .../EurotruckSimulator2View.xaml | 160 ++--- .../Artemis/Modules/Games/GtaV/GtaVView.xaml | 66 +- .../Modules/Games/LightFx/LightFxView.xaml | 56 +- .../Games/Overwatch/OverwatchView.xaml | 94 +-- .../Games/Overwatch/OverwatchViewModel.cs | 5 + .../Methods/pCarsAPI-MapStructToClass.cs | 5 +- .../Data/_pCarsAPIStruct/pCarsAPI-ReadAPI.cs | 4 + .../Games/ProjectCars/ProjectCarsView.xaml | 71 +-- .../Games/RocketLeague/RocketLeagueView.xaml | 87 ++- .../RocketLeague/RocketLeagueViewModel.cs | 6 +- .../Games/TheDivision/TheDivisionView.xaml | 72 +-- .../UnrealTournamentView.xaml | 62 +- .../UnrealTournamentViewModel.cs | 7 + .../Modules/Games/Witcher3/Witcher3View.xaml | 61 +- .../Artemis/Modules/Games/WoW/WoWView.xaml | 56 +- .../GeneralProfile/GeneralProfileView.xaml | 53 +- .../OverlayProfile/OverlayProfileView.xaml | 65 +- .../Layers/Abstract/LayerCondition.cs | 35 +- .../Layers/Conditions/DataModelCondition.cs | 41 +- .../Layers/Conditions/EventCondition.cs | 37 +- .../Profiles/Layers/Models/LayerModel.cs | 2 +- Artemis/Artemis/Profiles/ProfileModel.cs | 594 +++++++++--------- Artemis/Artemis/ViewModels/ShellViewModel.cs | 6 +- Artemis/Artemis/Views/GamesView.xaml | 3 +- Artemis/Artemis/Views/GeneralView.xaml | 2 +- Artemis/Artemis/Views/OverlaysView.xaml | 4 +- Artemis/Artemis/Views/ProfileEditorView.xaml | 198 +++--- .../Artemis/Views/ProfileEditorView.xaml.cs | 2 +- Artemis/Artemis/Views/ShellView.xaml | 52 +- Artemis/Artemis/Views/WelcomeView.xaml | 2 +- 37 files changed, 954 insertions(+), 1223 deletions(-) diff --git a/Artemis/Artemis/InjectionModules/BaseModules.cs b/Artemis/Artemis/InjectionModules/BaseModules.cs index af74463cf..7018eef22 100644 --- a/Artemis/Artemis/InjectionModules/BaseModules.cs +++ b/Artemis/Artemis/InjectionModules/BaseModules.cs @@ -93,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/Models/KeybindModel.cs b/Artemis/Artemis/Models/KeybindModel.cs index 0f9c3714c..1b4587648 100644 --- a/Artemis/Artemis/Models/KeybindModel.cs +++ b/Artemis/Artemis/Models/KeybindModel.cs @@ -23,10 +23,10 @@ namespace Artemis.Models } public string Name { get; set; } - public MouseButtons MouseButtons { get; } public HotKey HotKey { get; set; } - public Action Action { get; set; } + public MouseButtons MouseButtons { get; } public KeyType KeyType { get; set; } + public Action Action { get; set; } public void InvokeIfMatched(HotKey hotKey, KeyType keyType) { @@ -34,7 +34,7 @@ namespace Artemis.Models return; if (hotKey.Equals(HotKey)) - Action?.Invoke(); + Action?.Invoke(); } public void InvokeIfMatched(MouseButtons mouseButtons, KeyType keyType) diff --git a/Artemis/Artemis/Modules/Games/AssettoCorsa/AssettoCorsaView.xaml b/Artemis/Artemis/Modules/Games/AssettoCorsa/AssettoCorsaView.xaml index f531cbb36..96823eaec 100644 --- a/Artemis/Artemis/Modules/Games/AssettoCorsa/AssettoCorsaView.xaml +++ b/Artemis/Artemis/Modules/Games/AssettoCorsa/AssettoCorsaView.xaml @@ -1,70 +1,51 @@  - - + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:cal="http://www.caliburnproject.org" + xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls" + mc:Ignorable="d" + d:DesignHeight="600" d:DesignWidth="900"> + + + - - + - - - - - - - - - - + + - - The Assetto Corsa module uses the - - Assetto Corsa Shared Memory Library - - project by mdjarv - - - - + + + The Assetto Corsa module uses the Assetto Corsa Shared Memory Library project by mdjarv. + + + + + - + - - - - + + + \ No newline at end of file diff --git a/Artemis/Artemis/Views/Profiles/LayerDynamicPropertiesView.xaml b/Artemis/Artemis/Views/Profiles/LayerDynamicPropertiesView.xaml index 70ea80c43..a81344761 100644 --- a/Artemis/Artemis/Views/Profiles/LayerDynamicPropertiesView.xaml +++ b/Artemis/Artemis/Views/Profiles/LayerDynamicPropertiesView.xaml @@ -1,16 +1,14 @@  - + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:sys="clr-namespace:System;assembly=mscorlib" + xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls" + xmlns:models="clr-namespace:Artemis.Profiles.Layers.Models" + xmlns:converters="clr-namespace:Artemis.Utilities.Converters" + mc:Ignorable="d" + d:DesignWidth="500"> @@ -19,20 +17,19 @@ - + - + - + \ No newline at end of file diff --git a/Artemis/Artemis/Views/Profiles/LayerKeybindView.xaml.cs b/Artemis/Artemis/Views/Profiles/LayerKeybindView.xaml.cs new file mode 100644 index 000000000..8b11d18a3 --- /dev/null +++ b/Artemis/Artemis/Views/Profiles/LayerKeybindView.xaml.cs @@ -0,0 +1,15 @@ +using System.Windows.Controls; + +namespace Artemis.Views.Profiles +{ + /// + /// Interaction logic for LayerKeybindView.xaml + /// + public partial class LayerKeybindView : UserControl + { + public LayerKeybindView() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/Artemis/Artemis/Views/ShellView.xaml b/Artemis/Artemis/Views/ShellView.xaml index bf5c27746..ab1bde511 100644 --- a/Artemis/Artemis/Views/ShellView.xaml +++ b/Artemis/Artemis/Views/ShellView.xaml @@ -10,7 +10,7 @@ xmlns:tb="http://www.hardcodet.net/taskbar" dialogs:DialogParticipation.Register="{Binding RelativeSource={RelativeSource Self}, Path=DataContext}" mc:Ignorable="d" d:DataContext="{d:DesignInstance viewModels:ShellViewModel}" - Title="Artemis" Height="800" Width="1210" ResizeMode="NoResize" GlowBrush="{DynamicResource AccentColorBrush}" Icon="../logo.ico"> + Title="Artemis" Height="800" Width="1210" MinHeight="600" MinWidth="1000" GlowBrush="{DynamicResource AccentColorBrush}" Icon="../logo.ico"> From 87a30b8936053ca495c5468d432326c532b18546 Mon Sep 17 00:00:00 2001 From: SpoinkyNL Date: Sat, 18 Mar 2017 17:23:51 +0100 Subject: [PATCH 13/16] Added K95 Platinum support Added default profiles for Assetto Corsa resolving #131 Fixed default profiles for the CM Pro S resolving #316 Fixed keybinds on folders #276 Fixed window scaling with many layers #276 --- Artemis/Artemis/Artemis.csproj | 17 +- .../Corsair/CorsairKeyboard.cs | 21 ++- .../Artemis/Modules/Abstract/ModuleModel.cs | 7 +- .../Games/AssettoCorsa/AssettoCorsaView.xaml | 72 +++++---- .../Games/CounterStrike/CounterStrikeModel.cs | 13 +- .../CounterStrike/CounterStrikeView.xaml | 82 +++++----- .../Modules/Games/Dota2/Dota2View.xaml | 98 ++++++------ .../EurotruckSimulator2View.xaml | 146 +++++++++--------- .../Artemis/Modules/Games/GtaV/GtaVView.xaml | 64 ++++---- .../Modules/Games/LightFx/LightFxView.xaml | 80 +++++----- .../Games/Overwatch/OverwatchView.xaml | 106 +++++++------ .../Games/ProjectCars/ProjectCarsView.xaml | 88 ++++++----- .../Games/RocketLeague/RocketLeagueView.xaml | 94 ++++++----- .../Games/TheDivision/TheDivisionView.xaml | 72 +++++---- .../UnrealTournamentView.xaml | 100 ++++++------ .../Modules/Games/Witcher3/Witcher3View.xaml | 94 ++++++----- .../Artemis/Modules/Games/WoW/WoWView.xaml | 90 ++++++----- .../GeneralProfile/GeneralProfileView.xaml | 80 +++++----- .../OverlayProfile/OverlayProfileView.xaml | 64 ++++---- Artemis/Artemis/NLog.xsd | 33 +++- .../Profiles/Layers/Models/LayerModel.cs | 39 +++-- Artemis/Artemis/Profiles/ProfileModel.cs | 19 ++- .../Artemis/Properties/Resources.Designer.cs | 12 +- Artemis/Artemis/Properties/Resources.resx | 3 + .../csgoGamestateConfiguration.txt | 1 + .../Resources/Keyboards/default-profiles.zip | Bin 401430 -> 463942 bytes .../Resources/Keyboards/k95-platinum.png | Bin 0 -> 307003 bytes .../Utilities/DataReaders/DllManager.cs | 49 +++--- .../Utilities/Keyboard/KeyboardHook.cs | 13 +- .../ViewModels/ProfileEditorViewModel.cs | 14 +- .../Profiles/LayerConditionViewModel.cs | 54 ++----- Artemis/Artemis/Views/ProfileEditorView.xaml | 2 +- .../Views/Profiles/LayerKeybindView.xaml | 6 +- Artemis/Artemis/packages.config | 10 +- 34 files changed, 844 insertions(+), 799 deletions(-) create mode 100644 Artemis/Artemis/Resources/Keyboards/k95-platinum.png diff --git a/Artemis/Artemis/Artemis.csproj b/Artemis/Artemis/Artemis.csproj index 2181a19b4..d7ddc8851 100644 --- a/Artemis/Artemis/Artemis.csproj +++ b/Artemis/Artemis/Artemis.csproj @@ -163,8 +163,8 @@ ..\packages\CSCore.1.2.0\lib\net35-client\CSCore.dll True - - ..\packages\CUE.NET.1.1.2.1\lib\net45\CUE.NET.dll + + ..\packages\CUE.NET.1.1.3.0\lib\net45\CUE.NET.dll True @@ -199,8 +199,8 @@ ..\packages\squirrel.windows.1.4.4\lib\Net45\ICSharpCode.SharpZipLib.dll True - - ..\packages\log4net.2.0.7\lib\net45-full\log4net.dll + + ..\packages\log4net.2.0.8\lib\net45-full\log4net.dll True @@ -248,7 +248,7 @@ True - ..\packages\NLog.4.4.3\lib\net45\NLog.dll + ..\packages\NLog.4.4.4\lib\net45\NLog.dll True @@ -272,7 +272,7 @@ True - ..\packages\SpotifyAPI-NET.2.12.0\lib\SpotifyAPI.dll + ..\packages\SpotifyAPI-NET.2.13.1\lib\SpotifyAPI.dll True @@ -778,6 +778,7 @@ Designer + @@ -1064,12 +1065,12 @@ - + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + - + + - - - The Assetto Corsa module uses the Assetto Corsa Shared Memory Library project by mdjarv. - + + + The Assetto Corsa module uses the Assetto Corsa Shared Memory Library project by mdjarv. + - - - + + + - - + + - - - -