From e5608907e480d4840895a19e5d8fe4820ba53052 Mon Sep 17 00:00:00 2001 From: SpoinkyNL Date: Tue, 1 Nov 2016 00:19:30 +0100 Subject: [PATCH] Added keyboard stuff to LUA --- Artemis/Artemis/Artemis.csproj | 9 +- Artemis/Artemis/Models/EffectModel.cs | 13 +- .../ProfilePreview/ProfilePreviewModel.cs | 8 +- .../Profiles/Layers/Types/Audio/AudioType.cs | 6 +- .../Layers/Types/KeyPress/KeyPressType.cs | 12 +- .../Profiles/Lua/Brushes/LuaBrushWrapper.cs | 45 +++++++ .../Artemis/Profiles/Lua/Brushes/LuaColor.cs | 59 +++++++++ .../Lua/Brushes/LuaLinearGradientBrush.cs | 66 +++------- .../Lua/Brushes/LuaRadialGradientBrush.cs | 31 +++-- .../Lua/Brushes/LuaSolidColorBrush.cs | 21 +--- .../Profiles/Lua/Events/LuaEventsWrapper.cs | 117 ++++++++++++++++++ .../Lua/Events/LuaKeyPressEventArgs.cs | 23 ++++ .../Lua/Events/LuaProfileDrawingEventArgs.cs | 21 ++++ .../Lua/Events/LuaProfileUpdatingEventArgs.cs | 19 +++ .../Artemis/Profiles/Lua/LuaBrushWrapper.cs | 34 ----- .../Artemis/Profiles/Lua/LuaEventsWrapper.cs | 113 ----------------- .../Profiles/Lua/LuaKeyboardWrapper.cs | 48 +++++++ Artemis/Artemis/Profiles/Lua/LuaWrapper.cs | 26 +++- Artemis/Artemis/Profiles/ProfileModel.cs | 14 +-- Artemis/Artemis/Resources/lua-placeholder.lua | 6 +- .../ViewModels/Abstract/GameViewModel.cs | 1 + .../Profiles/ProfileEditorViewModel.cs | 26 ++-- .../Artemis/ViewModels/SystemTrayViewModel.cs | 3 + 23 files changed, 458 insertions(+), 263 deletions(-) create mode 100644 Artemis/Artemis/Profiles/Lua/Brushes/LuaBrushWrapper.cs create mode 100644 Artemis/Artemis/Profiles/Lua/Brushes/LuaColor.cs create mode 100644 Artemis/Artemis/Profiles/Lua/Events/LuaEventsWrapper.cs create mode 100644 Artemis/Artemis/Profiles/Lua/Events/LuaKeyPressEventArgs.cs create mode 100644 Artemis/Artemis/Profiles/Lua/Events/LuaProfileDrawingEventArgs.cs create mode 100644 Artemis/Artemis/Profiles/Lua/Events/LuaProfileUpdatingEventArgs.cs delete mode 100644 Artemis/Artemis/Profiles/Lua/LuaBrushWrapper.cs delete mode 100644 Artemis/Artemis/Profiles/Lua/LuaEventsWrapper.cs create mode 100644 Artemis/Artemis/Profiles/Lua/LuaKeyboardWrapper.cs diff --git a/Artemis/Artemis/Artemis.csproj b/Artemis/Artemis/Artemis.csproj index 6654080aa..aafe6a280 100644 --- a/Artemis/Artemis/Artemis.csproj +++ b/Artemis/Artemis/Artemis.csproj @@ -415,11 +415,16 @@ + - + + + + - + + diff --git a/Artemis/Artemis/Models/EffectModel.cs b/Artemis/Artemis/Models/EffectModel.cs index 428a435c7..7dad6f719 100644 --- a/Artemis/Artemis/Models/EffectModel.cs +++ b/Artemis/Artemis/Models/EffectModel.cs @@ -8,6 +8,7 @@ using Artemis.Models.Interfaces; using Artemis.Profiles; using Artemis.Profiles.Layers.Interfaces; using Artemis.Profiles.Layers.Models; +using Artemis.Profiles.Lua; using Artemis.Settings; using Newtonsoft.Json; @@ -40,8 +41,10 @@ namespace Artemis.Models public virtual void Dispose() { - if (Profile != null) - Profile.LuaWrapper = null; + if (Profile?.LuaWrapper == null) + return; + Profile.LuaWrapper.Dispose(); + Profile.LuaWrapper = null; } // Called on creation @@ -66,12 +69,16 @@ namespace Artemis.Models // Get all enabled layers who's conditions are met var renderLayers = GetRenderLayers(keyboardOnly); + // If the profile has no active LUA wrapper, create one + if (Profile.LuaWrapper == null && !string.IsNullOrEmpty(Profile.LuaScript)) + Profile.LuaWrapper = new LuaWrapper(Profile, MainManager.DeviceManager.ActiveKeyboard); + // Render the keyboard layer-by-layer var keyboardRect = MainManager.DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale); using (var g = Graphics.FromImage(frame.KeyboardBitmap)) { Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Keyboard), - DataModel, keyboardRect, false, true); + DataModel, keyboardRect, false, true, true); } // Render mice layer-by-layer var devRec = new Rect(0, 0, 40, 40); diff --git a/Artemis/Artemis/Modules/Effects/ProfilePreview/ProfilePreviewModel.cs b/Artemis/Artemis/Modules/Effects/ProfilePreview/ProfilePreviewModel.cs index 2313363fe..f547cd0ec 100644 --- a/Artemis/Artemis/Modules/Effects/ProfilePreview/ProfilePreviewModel.cs +++ b/Artemis/Artemis/Modules/Effects/ProfilePreview/ProfilePreviewModel.cs @@ -7,6 +7,7 @@ using Artemis.Models; using Artemis.Models.Interfaces; using Artemis.Profiles.Layers.Interfaces; using Artemis.Profiles.Layers.Models; +using Artemis.Profiles.Lua; using Artemis.ViewModels.Profiles; using Castle.Components.DictionaryAdapter; using MoonSharp.Interpreter; @@ -52,13 +53,16 @@ namespace Artemis.Modules.Effects.ProfilePreview // Get all enabled layers who's conditions are met var renderLayers = GetRenderLayers(keyboardOnly); + // If the profile has no active LUA wrapper, create one + if (Profile.LuaWrapper == null && !string.IsNullOrEmpty(Profile.LuaScript)) + Profile.LuaWrapper = new LuaWrapper(Profile, MainManager.DeviceManager.ActiveKeyboard); + // Render the keyboard layer-by-layer var keyboardRect = MainManager.DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale); using (var g = Graphics.FromImage(frame.KeyboardBitmap)) { Profile.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Keyboard), - DataModel, - keyboardRect, true, true); + DataModel, keyboardRect, true, true, true); } // Render mice layer-by-layer var devRec = new Rect(0, 0, 40, 40); diff --git a/Artemis/Artemis/Profiles/Layers/Types/Audio/AudioType.cs b/Artemis/Artemis/Profiles/Layers/Types/Audio/AudioType.cs index db2122ec2..a3de34dbf 100644 --- a/Artemis/Artemis/Profiles/Layers/Types/Audio/AudioType.cs +++ b/Artemis/Artemis/Profiles/Layers/Types/Audio/AudioType.cs @@ -55,9 +55,9 @@ namespace Artemis.Profiles.Layers.Types.Audio [JsonIgnore] public List SpectrumData { get; set; } = new List(); - public string Name { get; } = "Keyboard - Audio visualization"; - public bool ShowInEdtor { get; } = true; - public DrawType DrawType { get; } = DrawType.Keyboard; + public string Name => "Keyboard - Audio visualization"; + public bool ShowInEdtor => true; + public DrawType DrawType => DrawType.Keyboard; public ImageSource DrawThumbnail(LayerModel layer) { diff --git a/Artemis/Artemis/Profiles/Layers/Types/KeyPress/KeyPressType.cs b/Artemis/Artemis/Profiles/Layers/Types/KeyPress/KeyPressType.cs index 896592b2e..01f2db9b8 100644 --- a/Artemis/Artemis/Profiles/Layers/Types/KeyPress/KeyPressType.cs +++ b/Artemis/Artemis/Profiles/Layers/Types/KeyPress/KeyPressType.cs @@ -19,13 +19,13 @@ namespace Artemis.Profiles.Layers.Types.KeyPress { internal class KeyPressType : ILayerType { - private readonly MainManager _mainManager; + private readonly DeviceManager _deviceManager; private List _keyPressLayers = new List(); private LayerModel _layerModel; - public KeyPressType(MainManager mainManager) + public KeyPressType(DeviceManager deviceManager) { - _mainManager = mainManager; + _deviceManager = deviceManager; KeyboardHook.KeyDownCallback += KeyboardHookOnKeyDownCallback; } @@ -61,8 +61,8 @@ namespace Artemis.Profiles.Layers.Types.KeyPress public void Update(LayerModel layerModel, IDataModel dataModel, bool isPreview = false) { // Key press is always as large as the entire keyboard it is drawn for - layerModel.Properties.Width = _mainManager.DeviceManager.ActiveKeyboard.Width; - layerModel.Properties.Height = _mainManager.DeviceManager.ActiveKeyboard.Height; + layerModel.Properties.Width = _deviceManager.ActiveKeyboard.Width; + layerModel.Properties.Height = _deviceManager.ActiveKeyboard.Height; layerModel.Properties.X = 0; layerModel.Properties.Y = 0; layerModel.Properties.Contain = true; @@ -126,7 +126,7 @@ namespace Artemis.Profiles.Layers.Types.KeyPress return; } - var keyMatch = _mainManager.DeviceManager.ActiveKeyboard.GetKeyPosition(e.KeyCode); + var keyMatch = _deviceManager.ActiveKeyboard.GetKeyPosition(e.KeyCode); if (keyMatch == null) return; diff --git a/Artemis/Artemis/Profiles/Lua/Brushes/LuaBrushWrapper.cs b/Artemis/Artemis/Profiles/Lua/Brushes/LuaBrushWrapper.cs new file mode 100644 index 000000000..e6a4f30db --- /dev/null +++ b/Artemis/Artemis/Profiles/Lua/Brushes/LuaBrushWrapper.cs @@ -0,0 +1,45 @@ +using System.Collections.Generic; +using System.Windows.Media; +using Artemis.Utilities; +using CUE.NET.Helper; +using MoonSharp.Interpreter; + +namespace Artemis.Profiles.Lua.Brushes +{ + [MoonSharpUserData] + public class LuaBrushWrapper + { + public LuaColor GetColor(string hexCode) + { + return new LuaColor(hexCode); + } + + public LuaColor GetColor(byte a, byte r, byte g, byte b) + { + return new LuaColor(a, r, g, b); + } + + public LuaColor GetRandomColor() + { + return new LuaColor(ColorHelpers.GetRandomRainbowMediaColor()); + } + + public LuaSolidColorBrush GetSolidColorBrush(LuaColor color) + { + return new LuaSolidColorBrush(color); + } + + public LuaLinearGradientBrush GetLinearGradientBrush(Dictionary gradientColors, + double startX = 0.5, double startY = 0.0, double endX = 0.5, double endY = 1.0) + { + return new LuaLinearGradientBrush(gradientColors, startX, startY, endX, endY); + } + + // TODO: Check default values + public LuaRadialGradientBrush GetRadialGradientBrush(Dictionary gradientColors, + double centerX = 0.5, double centerY = 0.5, double originX = 0.5, double originY = 0.5) + { + return new LuaRadialGradientBrush(gradientColors, centerX, centerY, originX, originY); + } + } +} \ No newline at end of file diff --git a/Artemis/Artemis/Profiles/Lua/Brushes/LuaColor.cs b/Artemis/Artemis/Profiles/Lua/Brushes/LuaColor.cs new file mode 100644 index 000000000..25e9a67cd --- /dev/null +++ b/Artemis/Artemis/Profiles/Lua/Brushes/LuaColor.cs @@ -0,0 +1,59 @@ +using System.Windows.Media; +using Artemis.Utilities; +using MoonSharp.Interpreter; +using MoonSharp.Interpreter.Interop; + +namespace Artemis.Profiles.Lua.Brushes +{ + [MoonSharpUserData] + public class LuaColor + { + public LuaColor(Color color) + { + Color = color; + } + + public LuaColor(string hexCode) + { + Color = new Color().FromHex(hexCode); + } + + public LuaColor(byte a, byte r, byte g, byte b) + { + Color = Color.FromArgb(a, r, g, b); + } + + [MoonSharpVisible(false)] + public Color Color { get; set; } + + public string HexCode + { + get { return Color.ToHex(); } + set { Color = Color.FromHex(value); } + } + + public byte A + { + get { return Color.A; } + set { Color = Color.FromArgb(value, R, G, B); } + } + + public byte R + { + get { return Color.R; } + set { Color = Color.FromArgb(A, value, G, B); } + } + + public byte G + { + get { return Color.G; } + set { Color = Color.FromArgb(A, R, value, B); } + } + + public byte B + { + get { return Color.B; } + set { Color = Color.FromArgb(A, R, G, value); } + } + } +} \ No newline at end of file diff --git a/Artemis/Artemis/Profiles/Lua/Brushes/LuaLinearGradientBrush.cs b/Artemis/Artemis/Profiles/Lua/Brushes/LuaLinearGradientBrush.cs index a9787fbe4..bcc784215 100644 --- a/Artemis/Artemis/Profiles/Lua/Brushes/LuaLinearGradientBrush.cs +++ b/Artemis/Artemis/Profiles/Lua/Brushes/LuaLinearGradientBrush.cs @@ -1,7 +1,7 @@ -using System.Linq; +using System.Collections.Generic; +using System.Linq; using System.Windows; using System.Windows.Media; -using Artemis.Utilities; using MoonSharp.Interpreter; using MoonSharp.Interpreter.Interop; @@ -10,19 +10,16 @@ namespace Artemis.Profiles.Lua.Brushes [MoonSharpUserData] public class LuaLinearGradientBrush : LuaBrush { - private readonly Script _script; private LinearGradientBrush _brush; - public LuaLinearGradientBrush(Script script, LinearGradientBrush linearGradientBrush) + public LuaLinearGradientBrush(LinearGradientBrush linearGradientBrush) { - _script = script; LinearGradientBrush = linearGradientBrush; } - public LuaLinearGradientBrush(Script script, Table gradientColors, - double startX, double startY, double endX, double endY) + public LuaLinearGradientBrush(Dictionary gradientColors, double startX, double startY, + double endX, double endY) { - _script = script; SetupBrush(gradientColors, startX, startY, endX, endY); } @@ -44,13 +41,18 @@ namespace Artemis.Profiles.Lua.Brushes /// /// Gets or sets the Brush's GradientStops using a LUA table /// - public Table Colors + public Dictionary GradientColors { - get { return CreateGradientTable(_script, LinearGradientBrush.GradientStops); } + get + { + return LinearGradientBrush.GradientStops.ToDictionary(gs => new LuaColor(gs.Color), gs => gs.Offset); + } set { var updatedBrush = LinearGradientBrush.CloneCurrentValue(); - updatedBrush.GradientStops = CreateGradientCollection(value); + updatedBrush.GradientStops = new GradientStopCollection(value + .Select(gc => new GradientStop(gc.Key.Color, gc.Value))); + LinearGradientBrush = updatedBrush; } } @@ -63,45 +65,13 @@ namespace Artemis.Profiles.Lua.Brushes /// /// /// - private void SetupBrush(Table gradientColors, double startX, double startY, double endX, double endY) + private void SetupBrush(Dictionary gradientColors, double startX, double startY, double endX, + double endY) { - var collection = CreateGradientCollection(gradientColors); + var collection = new GradientStopCollection(gradientColors + .Select(gc => new GradientStop(gc.Key.Color, gc.Value))); + LinearGradientBrush = new LinearGradientBrush(collection, new Point(startX, startY), new Point(endX, endY)); } - - /// - /// Maps a LUA table to a GradientStopsCollection - /// - /// - /// - public static GradientStopCollection CreateGradientCollection(Table gradientColors) - { - var collection = new GradientStopCollection(); - foreach (var gradientColor in gradientColors.Values) - { - var pair = gradientColor.Table.Values.ToList(); - var hexCode = pair[0].String; - var position = pair[1].Number; - collection.Add(new GradientStop(new Color().FromHex(hexCode), position)); - } - return collection; - } - - /// - /// Maps the current brush's GradientStopsCollection to a LUA table - /// - /// - public static Table CreateGradientTable(Script script, GradientStopCollection gradientStops) - { - var table = new Table(script); - foreach (var gradientStop in gradientStops) - { - var inner = new Table(script); - inner.Append(DynValue.NewString(gradientStop.Color.ToHex())); - inner.Append(DynValue.NewNumber(gradientStop.Offset)); - table.Append(DynValue.NewTable(inner)); - } - return table; - } } } \ No newline at end of file diff --git a/Artemis/Artemis/Profiles/Lua/Brushes/LuaRadialGradientBrush.cs b/Artemis/Artemis/Profiles/Lua/Brushes/LuaRadialGradientBrush.cs index b698d86b7..d26b7fc94 100644 --- a/Artemis/Artemis/Profiles/Lua/Brushes/LuaRadialGradientBrush.cs +++ b/Artemis/Artemis/Profiles/Lua/Brushes/LuaRadialGradientBrush.cs @@ -1,4 +1,6 @@ -using System.Windows; +using System.Collections.Generic; +using System.Linq; +using System.Windows; using System.Windows.Media; using MoonSharp.Interpreter; using MoonSharp.Interpreter.Interop; @@ -8,19 +10,16 @@ namespace Artemis.Profiles.Lua.Brushes [MoonSharpUserData] public class LuaRadialGradientBrush : LuaBrush { - private readonly Script _script; private RadialGradientBrush _brush; - public LuaRadialGradientBrush(Script script, RadialGradientBrush radialGradientBrush) + public LuaRadialGradientBrush(RadialGradientBrush radialGradientBrush) { - _script = script; RadialGradientBrush = radialGradientBrush; } - public LuaRadialGradientBrush(Script script, Table gradientColors, - double centerX, double centerY, double originX, double originY) + public LuaRadialGradientBrush(Dictionary gradientColors, double centerX, + double centerY, double originX, double originY) { - _script = script; SetupBrush(gradientColors, centerX, centerY, originX, originY); } @@ -42,13 +41,18 @@ namespace Artemis.Profiles.Lua.Brushes /// /// Gets or sets the Brush's GradientStops using a LUA table /// - public Table Colors + public Dictionary GradientColors { - get { return LuaLinearGradientBrush.CreateGradientTable(_script, RadialGradientBrush.GradientStops); } + get + { + return RadialGradientBrush.GradientStops.ToDictionary(gs => new LuaColor(gs.Color), gs => gs.Offset); + } set { var updatedBrush = RadialGradientBrush.CloneCurrentValue(); - updatedBrush.GradientStops = LuaLinearGradientBrush.CreateGradientCollection(value); + updatedBrush.GradientStops = new GradientStopCollection(value + .Select(gc => new GradientStop(gc.Key.Color, gc.Value))); + RadialGradientBrush = updatedBrush; } } @@ -61,9 +65,12 @@ namespace Artemis.Profiles.Lua.Brushes /// /// /// - private void SetupBrush(Table gradientColors, double centerX, double centerY, double originX, double originY) + private void SetupBrush(Dictionary gradientColors, double centerX, double centerY, + double originX, double originY) { - var collection = LuaLinearGradientBrush.CreateGradientCollection(gradientColors); + var collection = new GradientStopCollection(gradientColors + .Select(gc => new GradientStop(gc.Key.Color, gc.Value))); + RadialGradientBrush = new RadialGradientBrush(collection) { Center = new Point(centerX, centerY), diff --git a/Artemis/Artemis/Profiles/Lua/Brushes/LuaSolidColorBrush.cs b/Artemis/Artemis/Profiles/Lua/Brushes/LuaSolidColorBrush.cs index 9124d2d96..a06e1b78e 100644 --- a/Artemis/Artemis/Profiles/Lua/Brushes/LuaSolidColorBrush.cs +++ b/Artemis/Artemis/Profiles/Lua/Brushes/LuaSolidColorBrush.cs @@ -1,5 +1,4 @@ using System.Windows.Media; -using Artemis.Utilities; using MoonSharp.Interpreter; using MoonSharp.Interpreter.Interop; @@ -10,21 +9,16 @@ namespace Artemis.Profiles.Lua.Brushes { private SolidColorBrush _brush; - public LuaSolidColorBrush(SolidColorBrush solidColorBrush) + public LuaSolidColorBrush(LuaColor luaColor) { - SolidColorBrush = solidColorBrush; - } - - public LuaSolidColorBrush(string hexCode) - { - SolidColorBrush = new SolidColorBrush(new Color().FromHex(hexCode)); + SolidColorBrush = new SolidColorBrush(luaColor.Color); } /// /// The underlying brush /// [MoonSharpVisible(false)] - public SolidColorBrush SolidColorBrush + public SolidColorBrush SolidColorBrush { get { return _brush; } set @@ -35,13 +29,10 @@ namespace Artemis.Profiles.Lua.Brushes } } - /// - /// Gets or sets the brush's color using a hex notation - /// - public string Color + public LuaColor Color { - get { return SolidColorBrush.Color.ToHex(); } - set { SolidColorBrush = new SolidColorBrush(new Color().FromHex(value)); } + get { return new LuaColor(SolidColorBrush.Color); } + set { SolidColorBrush = new SolidColorBrush(value.Color); } } } } \ No newline at end of file diff --git a/Artemis/Artemis/Profiles/Lua/Events/LuaEventsWrapper.cs b/Artemis/Artemis/Profiles/Lua/Events/LuaEventsWrapper.cs new file mode 100644 index 000000000..bf9327c7c --- /dev/null +++ b/Artemis/Artemis/Profiles/Lua/Events/LuaEventsWrapper.cs @@ -0,0 +1,117 @@ +using System; +using System.Windows.Forms; +using System.Windows.Media; +using Artemis.Models.Interfaces; +using MoonSharp.Interpreter; +using NLog; + +namespace Artemis.Profiles.Lua.Events +{ + [MoonSharpUserData] + public class LuaEventsWrapper + { + private readonly Logger _logger = LogManager.GetCurrentClassLogger(); + public event EventHandler ProfileUpdating; + public event EventHandler ProfileDrawing; + public event EventHandler KeyboardKeyPressed; + + internal void InvokeProfileUpdate(ProfileModel profileModel, IDataModel dataModel, bool preview) + { + try + { + OnProfileUpdating(new LuaProfileWrapper(profileModel), + new LuaProfileUpdatingEventArgs(dataModel, preview)); + } + catch (Exception) + { + // ignored + } + } + + internal void InvokeProfileDraw(ProfileModel profileModel, IDataModel dataModel, bool preview, DrawingContext c) + { + try + { + OnProfileDrawing(new LuaProfileWrapper(profileModel), + new LuaProfileDrawingEventArgs(dataModel, preview, new LuaDrawWrapper(c))); + } + catch (Exception) + { + // ignored + } + } + + internal void InvokeKeyPressed(ProfileModel profileModel, LuaKeyboardWrapper keyboard, Keys key, int x, int y) + { + try + { + OnKeyboardKeyPressed(new LuaProfileWrapper(profileModel), keyboard, new LuaKeyPressEventArgs(key, x, y)); + } + catch (Exception) + { + // ignored + } + } + + protected virtual void OnProfileUpdating(LuaProfileWrapper profileModel, LuaProfileUpdatingEventArgs e) + { + try + { + ProfileUpdating?.Invoke(profileModel, e); + } + catch (InternalErrorException ex) + { + _logger.Error(ex, "[{0}-LUA]: Error: {1}", profileModel.Name, ex.DecoratedMessage); + } + catch (SyntaxErrorException ex) + { + _logger.Error(ex, "[{0}-LUA]: Error: {1}", profileModel.Name, ex.DecoratedMessage); + } + catch (ScriptRuntimeException ex) + { + _logger.Error(ex, "[{0}-LUA]: Error: {1}", profileModel.Name, ex.DecoratedMessage); + } + } + + protected virtual void OnProfileDrawing(LuaProfileWrapper profileModel, LuaProfileDrawingEventArgs e) + { + try + { + ProfileDrawing?.Invoke(profileModel, e); + } + catch (InternalErrorException ex) + { + _logger.Error(ex, "[{0}-LUA]: Error: {1}", profileModel.Name, ex.DecoratedMessage); + } + catch (SyntaxErrorException ex) + { + _logger.Error(ex, "[{0}-LUA]: Error: {1}", profileModel.Name, ex.DecoratedMessage); + } + catch (ScriptRuntimeException ex) + { + _logger.Error(ex, "[{0}-LUA]: Error: {1}", profileModel.Name, ex.DecoratedMessage); + } + } + + protected virtual void OnKeyboardKeyPressed(LuaProfileWrapper profileModel, LuaKeyboardWrapper keyboard, + LuaKeyPressEventArgs e) + { + try + { + KeyboardKeyPressed?.Invoke(profileModel, e); + } + catch (InternalErrorException ex) + { + _logger.Error(ex, "[{0}-LUA]: Error: {1}", profileModel.Name, ex.DecoratedMessage); + } + catch (SyntaxErrorException ex) + { + _logger.Error(ex, "[{0}-LUA]: Error: {1}", profileModel.Name, ex.DecoratedMessage); + } + catch (ScriptRuntimeException ex) + { + _logger.Error(ex, "[{0}-LUA]: Error: {1}", profileModel.Name, ex.DecoratedMessage); + } + } + } +} \ No newline at end of file diff --git a/Artemis/Artemis/Profiles/Lua/Events/LuaKeyPressEventArgs.cs b/Artemis/Artemis/Profiles/Lua/Events/LuaKeyPressEventArgs.cs new file mode 100644 index 000000000..9b595fb3b --- /dev/null +++ b/Artemis/Artemis/Profiles/Lua/Events/LuaKeyPressEventArgs.cs @@ -0,0 +1,23 @@ +using System; +using System.Windows.Forms; +using MoonSharp.Interpreter; + +namespace Artemis.Profiles.Lua.Events +{ + [MoonSharpUserData] + public class LuaKeyPressEventArgs : EventArgs + { + private readonly Keys _key; + + public LuaKeyPressEventArgs(Keys key, int x, int y) + { + _key = key; + X = x; + Y = y; + } + + public string Key => _key.ToString(); + public int X { get; } + public int Y { get; } + } +} \ No newline at end of file diff --git a/Artemis/Artemis/Profiles/Lua/Events/LuaProfileDrawingEventArgs.cs b/Artemis/Artemis/Profiles/Lua/Events/LuaProfileDrawingEventArgs.cs new file mode 100644 index 000000000..8043af8e2 --- /dev/null +++ b/Artemis/Artemis/Profiles/Lua/Events/LuaProfileDrawingEventArgs.cs @@ -0,0 +1,21 @@ +using System; +using Artemis.Models.Interfaces; +using MoonSharp.Interpreter; + +namespace Artemis.Profiles.Lua.Events +{ + [MoonSharpUserData] + public class LuaProfileDrawingEventArgs : EventArgs + { + public LuaProfileDrawingEventArgs(IDataModel dataModel, bool preview, LuaDrawWrapper luaDrawWrapper) + { + DataModel = dataModel; + Preview = preview; + Drawing = luaDrawWrapper; + } + + public IDataModel DataModel { get; } + public bool Preview { get; } + public LuaDrawWrapper Drawing { get; set; } + } +} \ No newline at end of file diff --git a/Artemis/Artemis/Profiles/Lua/Events/LuaProfileUpdatingEventArgs.cs b/Artemis/Artemis/Profiles/Lua/Events/LuaProfileUpdatingEventArgs.cs new file mode 100644 index 000000000..04da54a97 --- /dev/null +++ b/Artemis/Artemis/Profiles/Lua/Events/LuaProfileUpdatingEventArgs.cs @@ -0,0 +1,19 @@ +using System; +using Artemis.Models.Interfaces; +using MoonSharp.Interpreter; + +namespace Artemis.Profiles.Lua.Events +{ + [MoonSharpUserData] + public class LuaProfileUpdatingEventArgs : EventArgs + { + public LuaProfileUpdatingEventArgs(IDataModel dataModel, bool preview) + { + DataModel = dataModel; + Preview = preview; + } + + public IDataModel DataModel { get; } + public bool Preview { get; } + } +} \ No newline at end of file diff --git a/Artemis/Artemis/Profiles/Lua/LuaBrushWrapper.cs b/Artemis/Artemis/Profiles/Lua/LuaBrushWrapper.cs deleted file mode 100644 index 3b899914a..000000000 --- a/Artemis/Artemis/Profiles/Lua/LuaBrushWrapper.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Artemis.Profiles.Lua.Brushes; -using MoonSharp.Interpreter; - -namespace Artemis.Profiles.Lua -{ - [MoonSharpUserData] - public class LuaBrushWrapper - { - private readonly Script _script; - - public LuaBrushWrapper(Script script) - { - _script = script; - } - - public LuaSolidColorBrush GetSolidColorBrush(string hexCode) - { - return new LuaSolidColorBrush(hexCode); - } - - public LuaLinearGradientBrush GetLinearGradientBrush(Table gradientColors, - double startX = 0.5, double startY = 0.0, double endX = 0.5, double endY = 1.0) - { - return new LuaLinearGradientBrush(_script, gradientColors, startX, startY, endX, endY); - } - - // TODO: Check default values - public LuaRadialGradientBrush GetRadialGradientBrush(Table gradientColors, - double centerX = 0.5, double centerY = 0.5, double originX = 0.5, double originY = 0.5) - { - return new LuaRadialGradientBrush(_script, gradientColors, centerX, centerY, originX, originY); - } - } -} \ No newline at end of file diff --git a/Artemis/Artemis/Profiles/Lua/LuaEventsWrapper.cs b/Artemis/Artemis/Profiles/Lua/LuaEventsWrapper.cs deleted file mode 100644 index a1d3f8e3b..000000000 --- a/Artemis/Artemis/Profiles/Lua/LuaEventsWrapper.cs +++ /dev/null @@ -1,113 +0,0 @@ -using System; -using System.Windows.Media; -using Artemis.Models.Interfaces; -using MoonSharp.Interpreter; -using NLog; - -namespace Artemis.Profiles.Lua -{ - [MoonSharpUserData] - public class LuaEventsWrapper - { - private readonly Logger _logger = LogManager.GetCurrentClassLogger(); - public event EventHandler LuaProfileUpdating; - public event EventHandler LuaProfileDrawing; - - internal void InvokeProfileUpdate(ProfileModel profileModel, IDataModel dataModel, bool preview) - { - try - { - OnLuaProfileUpdating(new LuaProfileWrapper(profileModel), - new LuaProfileUpdatingEventArgs(dataModel, preview)); - } - catch (Exception) - { - - } - - } - - internal void InvokeProfileDraw(ProfileModel profileModel, IDataModel dataModel, bool preview, DrawingContext c) - { - try - { - OnLuaProfileDrawing(new LuaProfileWrapper(profileModel), - new LuaProfileDrawingEventArgs(dataModel, preview, new LuaDrawWrapper(c))); - } - catch (Exception) - { - - } - - } - - - protected virtual void OnLuaProfileUpdating(LuaProfileWrapper profileModel, LuaProfileUpdatingEventArgs e) - { - try - { - LuaProfileUpdating?.Invoke(profileModel, e); - } - catch (InternalErrorException ex) - { - _logger.Error(ex, "[{0}-LUA]: Error: {1}", profileModel.Name, ex.DecoratedMessage); - } - catch (SyntaxErrorException ex) - { - _logger.Error(ex, "[{0}-LUA]: Error: {1}", profileModel.Name, ex.DecoratedMessage); - } - catch (ScriptRuntimeException ex) - { - _logger.Error(ex, "[{0}-LUA]: Error: {1}", profileModel.Name, ex.DecoratedMessage); - } - } - - protected virtual void OnLuaProfileDrawing(LuaProfileWrapper profileModel, LuaProfileDrawingEventArgs e) - { - try - { - LuaProfileDrawing?.Invoke(profileModel, e); - } - catch (InternalErrorException ex) - { - _logger.Error(ex, "[{0}-LUA]: Error: {1}", profileModel.Name, ex.DecoratedMessage); - } - catch (SyntaxErrorException ex) - { - _logger.Error(ex, "[{0}-LUA]: Error: {1}", profileModel.Name, ex.DecoratedMessage); - } - catch (ScriptRuntimeException ex) - { - _logger.Error(ex, "[{0}-LUA]: Error: {1}", profileModel.Name, ex.DecoratedMessage); - } - } - } - - [MoonSharpUserData] - public class LuaProfileUpdatingEventArgs : EventArgs - { - public LuaProfileUpdatingEventArgs(IDataModel dataModel, bool preview) - { - DataModel = dataModel; - Preview = preview; - } - - public IDataModel DataModel { get; } - public bool Preview { get; } - } - - [MoonSharpUserData] - public class LuaProfileDrawingEventArgs : EventArgs - { - public LuaProfileDrawingEventArgs(IDataModel dataModel, bool preview, LuaDrawWrapper luaDrawWrapper) - { - DataModel = dataModel; - Preview = preview; - Drawing = luaDrawWrapper; - } - - public IDataModel DataModel { get; } - public bool Preview { get; } - public LuaDrawWrapper Drawing { get; set; } - } -} \ No newline at end of file diff --git a/Artemis/Artemis/Profiles/Lua/LuaKeyboardWrapper.cs b/Artemis/Artemis/Profiles/Lua/LuaKeyboardWrapper.cs new file mode 100644 index 000000000..ec5fcdf92 --- /dev/null +++ b/Artemis/Artemis/Profiles/Lua/LuaKeyboardWrapper.cs @@ -0,0 +1,48 @@ +using System; +using System.Windows.Forms; +using Artemis.DeviceProviders; +using Artemis.Utilities.Keyboard; +using MoonSharp.Interpreter; +using MoonSharp.Interpreter.Interop; + +namespace Artemis.Profiles.Lua +{ + [MoonSharpUserData] + public class LuaKeyboardWrapper : IDisposable + { + private readonly KeyboardProvider _keyboardProvider; + private readonly LuaWrapper _luaWrapper; + + public LuaKeyboardWrapper(LuaWrapper luaWrapper, KeyboardProvider keyboardProvider) + { + _luaWrapper = luaWrapper; + _keyboardProvider = keyboardProvider; + + KeyboardHook.KeyDownCallback += KeyboardHookOnKeyDownCallback; + } + + public string Name => _keyboardProvider.Name; + public string Slug => _keyboardProvider.Slug; + public int Width => _keyboardProvider.Width; + public int Height => _keyboardProvider.Height; + + [MoonSharpVisible(false)] + public void Dispose() + { + KeyboardHook.KeyDownCallback -= KeyboardHookOnKeyDownCallback; + } + + private void KeyboardHookOnKeyDownCallback(KeyEventArgs e) + { + var keyMatch = _keyboardProvider.GetKeyPosition(e.KeyCode); + if (keyMatch != null) + _luaWrapper.LuaEventsWrapper.InvokeKeyPressed(_luaWrapper.ProfileModel, this, + keyMatch.Value.KeyCode, keyMatch.Value.X, keyMatch.Value.Y); + } + + public void SendKeys(string keys) + { + System.Windows.Forms.SendKeys.SendWait(keys); + } + } +} \ No newline at end of file diff --git a/Artemis/Artemis/Profiles/Lua/LuaWrapper.cs b/Artemis/Artemis/Profiles/Lua/LuaWrapper.cs index 54a894599..ce0fda411 100644 --- a/Artemis/Artemis/Profiles/Lua/LuaWrapper.cs +++ b/Artemis/Artemis/Profiles/Lua/LuaWrapper.cs @@ -2,6 +2,9 @@ using System.IO; using System.Text; using Artemis.DAL; +using Artemis.DeviceProviders; +using Artemis.Profiles.Lua.Brushes; +using Artemis.Profiles.Lua.Events; using Artemis.Properties; using Castle.Core.Internal; using MoonSharp.Interpreter; @@ -9,22 +12,24 @@ using NLog; namespace Artemis.Profiles.Lua { - public class LuaWrapper + public class LuaWrapper : IDisposable { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - public LuaWrapper(ProfileModel profileModel) + public LuaWrapper(ProfileModel profileModel, KeyboardProvider keyboardProvider) { ProfileModel = profileModel; LuaProfileWrapper = new LuaProfileWrapper(ProfileModel); - LuaBrushWrapper = new LuaBrushWrapper(LuaScript); + LuaBrushWrapper = new LuaBrushWrapper(); + LuaKeyboardWrapper = new LuaKeyboardWrapper(this, keyboardProvider); SetupLuaScript(); } - + public ProfileModel ProfileModel { get; set; } - public LuaEventsWrapper LuaEventsWrapper { get; set; } - public LuaBrushWrapper LuaBrushWrapper { get; set; } public LuaProfileWrapper LuaProfileWrapper { get; set; } + public LuaBrushWrapper LuaBrushWrapper { get; set; } + public LuaKeyboardWrapper LuaKeyboardWrapper { get; set; } + public LuaEventsWrapper LuaEventsWrapper { get; set; } public Script LuaScript { get; set; } private void SetupLuaScript() @@ -36,6 +41,7 @@ namespace Artemis.Profiles.Lua LuaScript.Globals["Profile"] = LuaProfileWrapper; LuaScript.Globals["Events"] = LuaEventsWrapper; LuaScript.Globals["Brushes"] = LuaBrushWrapper; + LuaScript.Globals["Keyboard"] = LuaKeyboardWrapper; if (ProfileModel.LuaScript.IsNullOrEmpty()) return; @@ -121,5 +127,13 @@ namespace Artemis.Profiles.Lua } #endregion + + public void Dispose() + { + LuaKeyboardWrapper.Dispose(); + LuaScript.Globals.Clear(); + LuaScript.Registry.Clear(); + LuaScript = null; + } } } \ No newline at end of file diff --git a/Artemis/Artemis/Profiles/ProfileModel.cs b/Artemis/Artemis/Profiles/ProfileModel.cs index 7d41b6f94..d6d5173ee 100644 --- a/Artemis/Artemis/Profiles/ProfileModel.cs +++ b/Artemis/Artemis/Profiles/ProfileModel.cs @@ -11,7 +11,6 @@ using Artemis.Profiles.Layers.Models; using Artemis.Profiles.Lua; using Artemis.Utilities; using Artemis.Utilities.ParentChild; -using Castle.Core.Internal; using Newtonsoft.Json; using Color = System.Windows.Media.Color; using Point = System.Windows.Point; @@ -104,11 +103,8 @@ namespace Artemis.Profiles /// Indicates wheter the layer is drawn as a preview, ignoring dynamic properties /// Wheter or not to update the layer's animations internal void DrawLayers(Graphics g, IEnumerable renderLayers, IDataModel dataModel, Rect rect, - bool preview, bool updateAnimations) + bool preview, bool updateAnimations, bool triggerLua = false) { - if (LuaWrapper == null && !LuaScript.IsNullOrEmpty()) - LuaWrapper = new LuaWrapper(this); - var visual = new DrawingVisual(); var layerModels = renderLayers.ToList(); using (var c = visual.RenderOpen()) @@ -120,12 +116,16 @@ namespace Artemis.Profiles // Update the layers foreach (var layerModel in layerModels) layerModel.Update(dataModel, preview, updateAnimations); - LuaWrapper?.LuaEventsWrapper?.InvokeProfileUpdate(this, dataModel, preview); + + if (triggerLua) + LuaWrapper?.LuaEventsWrapper?.InvokeProfileUpdate(this, dataModel, preview); // Draw the layers foreach (var layerModel in layerModels) layerModel.Draw(dataModel, c, preview, updateAnimations); - LuaWrapper?.LuaEventsWrapper?.InvokeProfileDraw(this, dataModel, preview, c); + + if (triggerLua) + LuaWrapper?.LuaEventsWrapper?.InvokeProfileDraw(this, dataModel, preview, c); // Remove the clip c.Pop(); diff --git a/Artemis/Artemis/Resources/lua-placeholder.lua b/Artemis/Artemis/Resources/lua-placeholder.lua index 15bbabfa5..81a00a149 100644 --- a/Artemis/Artemis/Resources/lua-placeholder.lua +++ b/Artemis/Artemis/Resources/lua-placeholder.lua @@ -11,7 +11,7 @@ -- For docs and examples, see wiki: https://github.com/SpoinkyNL/Artemis/wiki/LUA -- Note: You are editing a temporary file. Whenever you save this file the --- changes are applied to the profile and the script restarted. +-- changes are applied to the profile and the script is restarted. -- This event is raised after every profile update, before drawing. function updateHandler(profile, eventArgs) @@ -36,5 +36,5 @@ end -- Register the default events, you can rename/remove these if you so desire. -- These events are raised every 40 ms (25 times a second). -Events.LuaProfileUpdating.add(updateHandler); -Events.LuaProfileDrawing.add(drawHandler); \ No newline at end of file +Events.ProfileUpdating.add(updateHandler); +Events.ProfileDrawing.add(drawHandler); \ No newline at end of file diff --git a/Artemis/Artemis/ViewModels/Abstract/GameViewModel.cs b/Artemis/Artemis/ViewModels/Abstract/GameViewModel.cs index 33b737cb5..d8c60c06f 100644 --- a/Artemis/Artemis/ViewModels/Abstract/GameViewModel.cs +++ b/Artemis/Artemis/ViewModels/Abstract/GameViewModel.cs @@ -91,6 +91,7 @@ namespace Artemis.ViewModels.Abstract { if (e.PropertyName != "SelectedProfile" && IsActive) return; + GameModel.Profile = ProfileEditor.SelectedProfile; ProfilePreviewModel.Profile = ProfileEditor.SelectedProfile; diff --git a/Artemis/Artemis/ViewModels/Profiles/ProfileEditorViewModel.cs b/Artemis/Artemis/ViewModels/Profiles/ProfileEditorViewModel.cs index eb7643546..0d973218f 100644 --- a/Artemis/Artemis/ViewModels/Profiles/ProfileEditorViewModel.cs +++ b/Artemis/Artemis/ViewModels/Profiles/ProfileEditorViewModel.cs @@ -111,8 +111,8 @@ namespace Artemis.ViewModels.Profiles return; SelectedProfile = ProfileProvider.GetProfile( - _mainManager.DeviceManager.ActiveKeyboard, - _gameModel, + _mainManager.DeviceManager.ActiveKeyboard, + _gameModel, value); NotifyOfPropertyChange(() => SelectedProfileName); @@ -125,6 +125,11 @@ namespace Artemis.ViewModels.Profiles set { if (Equals(value, _selectedProfile)) return; + if (_selectedProfile?.LuaWrapper != null) + { + _selectedProfile.LuaWrapper.Dispose(); + _selectedProfile.LuaWrapper = null; + } _selectedProfile = value; NotifyOfPropertyChange(() => SelectedProfile); } @@ -232,8 +237,11 @@ namespace Artemis.ViewModels.Profiles public void Deactivate() { ProfileViewModel.Deactivate(); - if (SelectedProfile != null) + if (SelectedProfile?.LuaWrapper != null) + { + SelectedProfile.LuaWrapper.Dispose(); SelectedProfile.LuaWrapper = null; + } _saveTimer.Stop(); } @@ -537,8 +545,8 @@ namespace Artemis.ViewModels.Profiles ProfileProvider.AddOrUpdate(profile); + LastProfile = profile.Name; LoadProfiles(); - SelectedProfile = profile; } public async void RenameProfile() @@ -564,9 +572,9 @@ namespace Artemis.ViewModels.Profiles } var profile = SelectedProfile; - SelectedProfile = null; ProfileProvider.RenameProfile(profile, name); + SelectedProfile = null; LastProfile = name; LoadProfiles(); } @@ -597,8 +605,8 @@ namespace Artemis.ViewModels.Profiles newProfile.IsDefault = false; ProfileProvider.AddOrUpdate(newProfile); + LastProfile = newProfile.Name; LoadProfiles(); - SelectedProfile = newProfile; } public async void DeleteProfile() @@ -682,9 +690,8 @@ namespace Artemis.ViewModels.Profiles } ProfileProvider.AddOrUpdate(profile); + LastProfile = profile.Name; LoadProfiles(); - - SelectedProfile = profile; } public void ExportProfile() @@ -707,7 +714,8 @@ namespace Artemis.ViewModels.Profiles try { if (SelectedProfile.LuaWrapper == null) - SelectedProfile.LuaWrapper = new LuaWrapper(SelectedProfile); + SelectedProfile.LuaWrapper = new LuaWrapper(SelectedProfile, + _mainManager.DeviceManager.ActiveKeyboard); SelectedProfile.LuaWrapper.OpenEditor(); } diff --git a/Artemis/Artemis/ViewModels/SystemTrayViewModel.cs b/Artemis/Artemis/ViewModels/SystemTrayViewModel.cs index 368ccaf46..9847678e7 100644 --- a/Artemis/Artemis/ViewModels/SystemTrayViewModel.cs +++ b/Artemis/Artemis/ViewModels/SystemTrayViewModel.cs @@ -179,6 +179,9 @@ namespace Artemis.ViewModels NotifyOfPropertyChange(() => CanShowWindow); NotifyOfPropertyChange(() => CanHideWindow); + + // Force a GC since the UI releases a lot of resources + GC.Collect(); } public void ExitApplication()