diff --git a/Artemis/Artemis/Artemis.csproj b/Artemis/Artemis/Artemis.csproj
index 00dba2b00..5f0aea86c 100644
--- a/Artemis/Artemis/Artemis.csproj
+++ b/Artemis/Artemis/Artemis.csproj
@@ -384,6 +384,13 @@
AssettoCorsaView.xaml
+
+
+
+
+ TerrariaView.xaml
+
+
@@ -561,15 +568,27 @@
+
+
+
+
+
+
+
+ LuaWindowView.xaml
+
+
+
+
@@ -645,6 +664,7 @@
True
Resources.resx
+
@@ -653,7 +673,11 @@
-
+
+
+
+
+
@@ -856,6 +880,10 @@
MSBuild:Compile
Designer
+
+ Designer
+ MSBuild:Compile
+
Designer
MSBuild:Compile
@@ -924,6 +952,10 @@
MSBuild:Compile
Designer
+
+ Designer
+ MSBuild:Compile
+
MSBuild:Compile
Designer
diff --git a/Artemis/Artemis/ArtemisBootstrapper.cs b/Artemis/Artemis/ArtemisBootstrapper.cs
index cc6fd3565..978297814 100644
--- a/Artemis/Artemis/ArtemisBootstrapper.cs
+++ b/Artemis/Artemis/ArtemisBootstrapper.cs
@@ -8,8 +8,10 @@ using System.Windows.Controls;
using System.Windows.Input;
using Artemis.DAL;
using Artemis.InjectionModules;
+using Artemis.Services;
using Artemis.Settings;
using Artemis.Utilities;
+using Artemis.Utilities.ActiveWindowDetection;
using Artemis.Utilities.Converters;
using Artemis.Utilities.DataReaders;
using Artemis.ViewModels;
@@ -31,10 +33,11 @@ namespace Artemis
Logging.SetupLogging(SettingsProvider.Load().LogLevel);
// Restore DDLs before interacting with any SDKs
DllManager.RestoreLogitechDll();
+ // Check compatibility before trying to boot further
+ CompatibilityService.CheckRivaTuner();
Initialize();
BindSpecialValues();
- InputHook.Start();
AppDomain.CurrentDomain.UnhandledException += CurrentDomainOnUnhandledException;
}
@@ -61,7 +64,7 @@ namespace Artemis
}
// If there is another type of of IInputControl get the non-scaled position - or do some processing to get a scaled position, whatever needs to happen
- if ((e != null) && (input != null))
+ if (e != null && input != null)
return e.GetPosition(input).X;
// Return 0 if no processing could be done
@@ -98,6 +101,7 @@ namespace Artemis
logger.Info("Artemis was run using the autorun shortcut, sleeping for 15 sec.");
Thread.Sleep(15000);
}
+
_kernel = new StandardKernel(new BaseModules(), new ManagerModules());
_kernel.Bind().To().InSingletonScope();
@@ -113,7 +117,7 @@ namespace Artemis
//TODO DarthAffe 17.12.2016: Is this the right location for this?
//TODO Move to Mainmanager and make disposable
- ActiveWindowHelper.Initialize();
+ ActiveWindowHelper.SetActiveWindowDetectionType(SettingsProvider.Load().ActiveWindowDetection);
}
protected override void OnExit(object sender, EventArgs e)
@@ -144,6 +148,7 @@ namespace Artemis
protected override void OnStartup(object sender, StartupEventArgs e)
{
DisplayRootViewFor();
+ InputHook.Start();
}
}
}
\ No newline at end of file
diff --git a/Artemis/Artemis/DAL/ProfileProvider.cs b/Artemis/Artemis/DAL/ProfileProvider.cs
index 356c53ec0..9a64c6446 100644
--- a/Artemis/Artemis/DAL/ProfileProvider.cs
+++ b/Artemis/Artemis/DAL/ProfileProvider.cs
@@ -134,7 +134,7 @@ namespace Artemis.DAL
return null;
return prof;
}
- catch (JsonSerializationException)
+ catch (JsonException)
{
return null;
}
diff --git a/Artemis/Artemis/DeviceProviders/CoolerMaster/MasterkeysProL.cs b/Artemis/Artemis/DeviceProviders/CoolerMaster/MasterkeysProL.cs
index 6b83f28e8..c84f7d4d4 100644
--- a/Artemis/Artemis/DeviceProviders/CoolerMaster/MasterkeysProL.cs
+++ b/Artemis/Artemis/DeviceProviders/CoolerMaster/MasterkeysProL.cs
@@ -1,4 +1,5 @@
-using System.Drawing;
+using System;
+using System.Drawing;
using System.Linq;
using System.Threading;
using System.Windows;
@@ -67,6 +68,8 @@ namespace Artemis.DeviceProviders.CoolerMaster
for (var y = 0; y < Height; y++)
{
var c = b.GetPixel(x, y);
+ if (c.R != 0)
+ Console.WriteLine();
matrix.KeyColor[y, x] = new KEY_COLOR(c.R, c.G, c.B);
}
}
diff --git a/Artemis/Artemis/DeviceProviders/CoolerMaster/MastermouseProL.cs b/Artemis/Artemis/DeviceProviders/CoolerMaster/MastermouseProL.cs
index 284b970f9..057439fb9 100644
--- a/Artemis/Artemis/DeviceProviders/CoolerMaster/MastermouseProL.cs
+++ b/Artemis/Artemis/DeviceProviders/CoolerMaster/MastermouseProL.cs
@@ -42,9 +42,16 @@ namespace Artemis.DeviceProviders.CoolerMaster
CmSdk.SetControlDevice(DEVICE_INDEX.DEV_MMouse_L);
// Doesn't seem reliable but better than nothing I suppose
- CanUse = CmSdk.IsDevicePlug();
- if (CanUse)
- CmSdk.EnableLedControl(true);
+ try
+ {
+ CanUse = CmSdk.IsDevicePlug();
+ if (CanUse)
+ CmSdk.EnableLedControl(true);
+ }
+ catch (Exception)
+ {
+ CanUse = false;
+ }
Logger.Debug("Attempted to enable Mastermouse Pro L. CanUse: {0}", CanUse);
return CanUse;
diff --git a/Artemis/Artemis/DeviceProviders/CoolerMaster/MastermouseProS.cs b/Artemis/Artemis/DeviceProviders/CoolerMaster/MastermouseProS.cs
index 3d1fcafc7..ebb07185c 100644
--- a/Artemis/Artemis/DeviceProviders/CoolerMaster/MastermouseProS.cs
+++ b/Artemis/Artemis/DeviceProviders/CoolerMaster/MastermouseProS.cs
@@ -38,10 +38,17 @@ namespace Artemis.DeviceProviders.CoolerMaster
CmSdk.SetControlDevice(DEVICE_INDEX.DEV_MMouse_S);
// Doesn't seem reliable but better than nothing I suppose
- CanUse = CmSdk.IsDevicePlug();
- if (CanUse)
- CmSdk.EnableLedControl(true);
-
+ try
+ {
+ CanUse = CmSdk.IsDevicePlug();
+ if (CanUse)
+ CmSdk.EnableLedControl(true);
+ }
+ catch (Exception)
+ {
+ CanUse = false;
+ }
+
Logger.Debug("Attempted to enable Mastermouse Pro S. CanUse: {0}", CanUse);
return CanUse;
}
diff --git a/Artemis/Artemis/DeviceProviders/Corsair/CorsairKeyboard.cs b/Artemis/Artemis/DeviceProviders/Corsair/CorsairKeyboard.cs
index 3be6500e2..4468016b9 100644
--- a/Artemis/Artemis/DeviceProviders/Corsair/CorsairKeyboard.cs
+++ b/Artemis/Artemis/DeviceProviders/Corsair/CorsairKeyboard.cs
@@ -81,10 +81,10 @@ namespace Artemis.DeviceProviders.Corsair
PreviewSettings = new PreviewSettings(new Rect(15, 30, 751, 284), Resources.k65);
break;
case "STRAFE RGB":
- Height = 7;
+ Height = 8;
Width = 22;
Slug = "corsair-strafe-rgb";
- PreviewSettings = new PreviewSettings(new Rect(23, 30, 940, 303), Resources.strafe);
+ PreviewSettings = new PreviewSettings(new Rect(23, 12, 937, 324), Resources.strafe);
break;
}
@@ -114,29 +114,8 @@ namespace Artemis.DeviceProviders.Corsair
///
public override void DrawBitmap(Bitmap bitmap)
{
-
- // For STRAFE, stretch the image on row 2.
- if (_keyboard.DeviceInfo.Model == "STRAFE RGB")
- {
- using (var strafeBitmap = new Bitmap(22, 8))
- {
- using (var g = Graphics.FromImage(strafeBitmap))
- {
- g.DrawImage(bitmap, new Point(0, 0));
- g.DrawImage(bitmap, new Rectangle(0, 3, 22, 7), new Rectangle(0, 2, 22, 7),
- GraphicsUnit.Pixel);
-
- _keyboardBrush.Image = strafeBitmap;
- _keyboard.Update();
- }
- }
- }
- else
- {
- _keyboardBrush.Image = bitmap;
- _keyboard.Update();
- }
-
+ _keyboardBrush.Image = bitmap;
+ _keyboard.Update();
}
public override KeyMatch? GetKeyPosition(Keys keyCode)
diff --git a/Artemis/Artemis/DeviceProviders/Logitech/LogitechKeyboard.cs b/Artemis/Artemis/DeviceProviders/Logitech/LogitechKeyboard.cs
index d7eaa7bfc..ec8ecd391 100644
--- a/Artemis/Artemis/DeviceProviders/Logitech/LogitechKeyboard.cs
+++ b/Artemis/Artemis/DeviceProviders/Logitech/LogitechKeyboard.cs
@@ -14,8 +14,7 @@ namespace Artemis.DeviceProviders.Logitech
DllManager.RestoreLogitechDll();
// Check to see if VC++ 2012 x64 is installed.
- if (Registry.LocalMachine.OpenSubKey(
- @"SOFTWARE\Classes\Installer\Dependencies\{ca67548a-5ebe-413a-b50c-4b9ceb6d66c6}") == null)
+ if (Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Classes\Installer\Dependencies\{ca67548a-5ebe-413a-b50c-4b9ceb6d66c6}") == null)
{
CantEnableText = "Couldn't connect to your Logitech keyboard.\n" +
"The Visual C++ 2012 Redistributable v11.0.61030.0 could not be found, which is required.\n" +
diff --git a/Artemis/Artemis/DeviceProviders/Razer/BlackWidow.cs b/Artemis/Artemis/DeviceProviders/Razer/BlackWidow.cs
index bc185fc6c..aff9bfcf7 100644
--- a/Artemis/Artemis/DeviceProviders/Razer/BlackWidow.cs
+++ b/Artemis/Artemis/DeviceProviders/Razer/BlackWidow.cs
@@ -37,8 +37,11 @@ namespace Artemis.DeviceProviders.Razer
return false;
// Some people have Synapse installed, but not a Chroma keyboard, deal with this
+ Chroma.Instance.Initialize();
var blackWidowFound = Chroma.Instance.Query(Devices.Blackwidow).Connected;
var blackWidowTeFound = Chroma.Instance.Query(Devices.BlackwidowTe).Connected;
+ Chroma.Instance.Uninitialize();
+
return blackWidowFound || blackWidowTeFound;
}
diff --git a/Artemis/Artemis/InjectionModules/BaseModules.cs b/Artemis/Artemis/InjectionModules/BaseModules.cs
index 7018eef22..3cf6d05be 100644
--- a/Artemis/Artemis/InjectionModules/BaseModules.cs
+++ b/Artemis/Artemis/InjectionModules/BaseModules.cs
@@ -6,6 +6,7 @@ using Artemis.Profiles.Layers.Abstract;
using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Types.Audio.AudioCapturing;
using Artemis.Profiles.Lua;
+using Artemis.Profiles.Lua.Modules.Gui;
using Artemis.Services;
using Artemis.Utilities.DataReaders;
using Artemis.Utilities.GameState;
@@ -116,6 +117,8 @@ namespace Artemis.InjectionModules
.InheritedFrom()
.BindAllBaseClasses());
+ Bind().ToSelf();
+
#endregion
}
}
diff --git a/Artemis/Artemis/Managers/LuaManager.cs b/Artemis/Artemis/Managers/LuaManager.cs
index bae48462d..a01b6b2cd 100644
--- a/Artemis/Artemis/Managers/LuaManager.cs
+++ b/Artemis/Artemis/Managers/LuaManager.cs
@@ -1,10 +1,12 @@
using System;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.Linq;
using Artemis.DeviceProviders;
using Artemis.Profiles;
using Artemis.Profiles.Lua;
using Artemis.Profiles.Lua.Modules;
+using Artemis.Profiles.Lua.Modules.Gui;
using Castle.Core.Internal;
using MoonSharp.Interpreter;
using Ninject;
@@ -17,7 +19,6 @@ namespace Artemis.Managers
private readonly DeviceManager _deviceManager;
private readonly IKernel _kernel;
private readonly ILogger _logger;
- private readonly Script _luaScript;
private List _luaModules;
public LuaManager(IKernel kernel, ILogger logger, DeviceManager deviceManager)
@@ -25,13 +26,17 @@ namespace Artemis.Managers
_kernel = kernel;
_logger = logger;
_deviceManager = deviceManager;
- _luaScript = new Script(CoreModules.Preset_SoftSandbox);
+
+ EditorButtons = new ObservableCollection();
+ LuaScript = new Script(CoreModules.Preset_SoftSandbox);
}
public ProfileModel ProfileModel { get; private set; }
public KeyboardProvider KeyboardProvider { get; private set; }
public LuaProfileModule ProfileModule { get; private set; }
public LuaEventsModule EventsModule { get; private set; }
+ public Script LuaScript { get; }
+ public ObservableCollection EditorButtons { get; set; }
public void SetupLua(ProfileModel profileModel)
{
@@ -52,11 +57,11 @@ namespace Artemis.Managers
EventsModule = (LuaEventsModule) _luaModules.First(m => m.ModuleName == "Events");
// Setup new state
- _luaScript.Options.DebugPrint = LuaPrint;
+ LuaScript.Options.DebugPrint = LuaPrint;
- // Insert each module into the script's globals
- foreach (var luaModule in _luaModules)
- _luaScript.Globals[luaModule.ModuleName] = luaModule;
+ // Insert each module with a ModuleName into the script's globals
+ foreach (var luaModule in _luaModules.Where(m => m.ModuleName != null))
+ LuaScript.Globals[luaModule.ModuleName] = luaModule;
// If there is no LUA script, don't bother executing the string
if (ProfileModel.LuaScript.IsNullOrEmpty())
@@ -66,9 +71,9 @@ namespace Artemis.Managers
{
lock (EventsModule.InvokeLock)
{
- lock (_luaScript)
+ lock (LuaScript)
{
- _luaScript.DoString(ProfileModel.LuaScript);
+ LuaScript.DoString(ProfileModel.LuaScript);
}
}
}
@@ -97,12 +102,12 @@ namespace Artemis.Managers
try
{
- _luaScript.Globals.Clear();
- _luaScript.Registry.Clear();
- _luaScript.Registry.RegisterConstants();
- _luaScript.Registry.RegisterCoreModules(CoreModules.Preset_SoftSandbox);
- _luaScript.Globals.RegisterConstants();
- _luaScript.Globals.RegisterCoreModules(CoreModules.Preset_SoftSandbox);
+ LuaScript.Globals.Clear();
+ LuaScript.Registry.Clear();
+ LuaScript.Registry.RegisterConstants();
+ LuaScript.Registry.RegisterCoreModules(CoreModules.Preset_SoftSandbox);
+ LuaScript.Globals.RegisterConstants();
+ LuaScript.Globals.RegisterCoreModules(CoreModules.Preset_SoftSandbox);
}
catch (NullReferenceException)
{
@@ -112,15 +117,15 @@ namespace Artemis.Managers
if (EventsModule != null)
lock (EventsModule.InvokeLock)
{
- lock (_luaScript)
+ lock (LuaScript)
{
- _luaScript.DoString("");
+ LuaScript.DoString("");
}
}
else
- lock (_luaScript)
+ lock (LuaScript)
{
- _luaScript.DoString("");
+ LuaScript.DoString("");
}
}
@@ -138,12 +143,12 @@ namespace Artemis.Managers
{
lock (EventsModule.InvokeLock)
{
- lock (_luaScript)
+ lock (LuaScript)
{
if (args != null)
- _luaScript.Call(function, args);
+ LuaScript.Call(function, args);
else
- _luaScript.Call(function);
+ LuaScript.Call(function);
}
}
}
diff --git a/Artemis/Artemis/Managers/MainManager.cs b/Artemis/Artemis/Managers/MainManager.cs
index 5870984c5..a5965fa73 100644
--- a/Artemis/Artemis/Managers/MainManager.cs
+++ b/Artemis/Artemis/Managers/MainManager.cs
@@ -108,6 +108,7 @@ namespace Artemis.Managers
public async void EnableProgram()
{
Logger.Debug("Enabling program");
+
ProgramEnabled = true;
await LoopManager.StartAsync();
@@ -121,9 +122,12 @@ namespace Artemis.Managers
public void DisableProgram()
{
Logger.Debug("Disabling program");
+
foreach (var overlayModule in ModuleManager.OverlayModules)
+ {
if (overlayModule.Settings.IsEnabled)
overlayModule.Dispose();
+ }
LoopManager.Stop();
ProgramEnabled = false;
RaiseEnabledChangedEvent(new EnabledChangedEventArgs(ProgramEnabled));
@@ -178,4 +182,4 @@ namespace Artemis.Managers
handler?.Invoke(this, e);
}
}
-}
\ No newline at end of file
+}
diff --git a/Artemis/Artemis/Managers/PreviewManager.cs b/Artemis/Artemis/Managers/PreviewManager.cs
index 612f2e120..68a7f8aed 100644
--- a/Artemis/Artemis/Managers/PreviewManager.cs
+++ b/Artemis/Artemis/Managers/PreviewManager.cs
@@ -5,6 +5,7 @@ using Artemis.DAL;
using Artemis.Modules.Abstract;
using Artemis.Settings;
using Artemis.Utilities;
+using Artemis.Utilities.ActiveWindowDetection;
using Ninject.Extensions.Logging;
namespace Artemis.Managers
diff --git a/Artemis/Artemis/Models/ProfileEditorModel.cs b/Artemis/Artemis/Models/ProfileEditorModel.cs
index cb9af3a15..389d5ecf7 100644
--- a/Artemis/Artemis/Models/ProfileEditorModel.cs
+++ b/Artemis/Artemis/Models/ProfileEditorModel.cs
@@ -27,8 +27,7 @@ namespace Artemis.Models
private FileSystemWatcher _watcher;
private ModuleModel _luaModule;
- public ProfileEditorModel(WindowService windowService, MetroDialogService dialogService,
- DeviceManager deviceManager, LuaManager luaManager)
+ public ProfileEditorModel(WindowService windowService, MetroDialogService dialogService, DeviceManager deviceManager, LuaManager luaManager)
{
_windowService = windowService;
_dialogService = dialogService;
@@ -50,7 +49,7 @@ namespace Artemis.Models
new ConstructorArgument("dataModel", dataModel),
new ConstructorArgument("layer", layer)
};
- _windowService.ShowDialog("Artemis | Edit layer", args);
+ _windowService.ShowDialog("Artemis | Edit layer", null, args);
// If the layer was a folder, but isn't anymore, assign it's children to it's parent.
if (layer.LayerType is FolderType || !layer.Children.Any())
@@ -345,7 +344,8 @@ namespace Artemis.Models
private void DisposeLuaWatcher()
{
- if (_watcher == null) return;
+ if (_watcher == null)
+ return;
_watcher.Changed -= LuaFileChanged;
_watcher.Dispose();
_watcher = null;
@@ -360,8 +360,6 @@ namespace Artemis.Models
#region Rendering
-
-
#endregion
}
-}
\ No newline at end of file
+}
diff --git a/Artemis/Artemis/Modules/Games/AssettoCorsa/AssettoCorsaView.xaml b/Artemis/Artemis/Modules/Games/AssettoCorsa/AssettoCorsaView.xaml
index e454ed3af..04e57ed28 100644
--- a/Artemis/Artemis/Modules/Games/AssettoCorsa/AssettoCorsaView.xaml
+++ b/Artemis/Artemis/Modules/Games/AssettoCorsa/AssettoCorsaView.xaml
@@ -22,7 +22,7 @@
diff --git a/Artemis/Artemis/Modules/Games/GtaV/GtaVModel.cs b/Artemis/Artemis/Modules/Games/GtaV/GtaVModel.cs
index 38f854a65..f97e8c245 100644
--- a/Artemis/Artemis/Modules/Games/GtaV/GtaVModel.cs
+++ b/Artemis/Artemis/Modules/Games/GtaV/GtaVModel.cs
@@ -29,7 +29,6 @@ namespace Artemis.Modules.Games.GtaV
public override void Enable()
{
- var process = System.Diagnostics.Process.GetProcessesByName("GTA5").First();
DllManager.PlaceLogitechDll();
_pipeServer.PipeMessage += PipeServerOnPipeMessage;
base.Enable();
diff --git a/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueViewModel.cs b/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueViewModel.cs
index e46759d75..a1f168377 100644
--- a/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueViewModel.cs
+++ b/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueViewModel.cs
@@ -36,7 +36,7 @@ namespace Artemis.Modules.Games.RocketLeague
{
if (!SettingsProvider.Load().EnablePointersUpdate)
{
- VersionText = "You disabled pointer updates, this could result in the Rocket League effect not working after a game update.";
+ VersionText = "You disabled pointer updates, this could result in the Rocket League module not working after a game update.";
return;
}
diff --git a/Artemis/Artemis/Modules/Games/Terraria/TerrariaDataModel.cs b/Artemis/Artemis/Modules/Games/Terraria/TerrariaDataModel.cs
new file mode 100644
index 000000000..ce01c1f18
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/Terraria/TerrariaDataModel.cs
@@ -0,0 +1,18 @@
+using Artemis.Modules.Abstract;
+using MoonSharp.Interpreter;
+
+namespace Artemis.Modules.Games.Terraria
+{
+ [MoonSharpUserData]
+ public class TerrariaDataModel : ModuleDataModel
+ {
+ public int Hp { get; set; }
+ public int MaxHp { get; set; }
+ public int Mana { get; set; }
+ public int MaxMana { get; set; }
+ public int Breath { get; set; }
+ public int MaxBreath { get; set; }
+ public bool InWater { get; set; }
+ public bool InLava { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/Terraria/TerrariaModel.cs b/Artemis/Artemis/Modules/Games/Terraria/TerrariaModel.cs
new file mode 100644
index 000000000..c7f3c0c8c
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/Terraria/TerrariaModel.cs
@@ -0,0 +1,91 @@
+using System;
+using System.Linq;
+using Artemis.DAL;
+using Artemis.Managers;
+using Artemis.Modules.Abstract;
+using Artemis.Settings;
+using Artemis.Utilities;
+using Artemis.Utilities.Memory;
+
+namespace Artemis.Modules.Games.Terraria
+{
+ public class TerrariaModel : ModuleModel
+ {
+ private Memory _memory;
+ private GamePointersCollection _pointer;
+
+ public TerrariaModel(DeviceManager deviceManager, LuaManager luaManager) : base(deviceManager, luaManager)
+ {
+ Settings = SettingsProvider.Load();
+ DataModel = new TerrariaDataModel();
+ ProcessNames.Add("Terraria");
+
+ // Generate a new offset when the game is updated
+ //_pointer = new GamePointersCollection
+ //{
+ // Game = "Terraria",
+ // GameVersion = "1.3.4.4",
+ // GameAddresses = new List
+ // {
+ // new GamePointer
+ // {
+ // Description = "PlayerBase",
+ // BasePointer = new IntPtr(0x0039C078),
+ // Offsets = new[] {0x280, 0x6C0, 0x674, 0x3C}
+ // }
+ // }
+ //};
+ //var res = JsonConvert.SerializeObject(_pointer, Formatting.Indented);
+ }
+
+ public override string Name => "Terraria";
+ public override bool IsOverlay => false;
+ public override bool IsBoundToProcess => true;
+
+ public override void Dispose()
+ {
+ base.Dispose();
+
+ _memory?.Dispose();
+ _memory = null;
+ }
+
+ public override void Enable()
+ {
+ Updater.GetPointers();
+ _pointer = SettingsProvider.Load().Terraria;
+
+ base.Enable();
+ }
+
+ public override void Update()
+ {
+ if (_memory == null)
+ {
+ var tempProcess = MemoryHelpers.GetProcessIfRunning(ProcessNames[0]);
+ if (tempProcess == null)
+ return;
+
+ _memory = new Memory(tempProcess);
+ }
+
+ if (ProfileModel == null || DataModel == null || _memory == null)
+ return;
+
+ var offsets = _pointer.GameAddresses.First(ga => ga.Description == "PlayerBase").ToString();
+ var baseAddress = _memory.GetAddress("\"Terraria.exe\"" + offsets);
+ var basePointer = new IntPtr(_memory.ReadInt32(baseAddress));
+ var playerPointer = new IntPtr(_memory.ReadInt32(basePointer + 0x18));
+
+ var dataModel = (TerrariaDataModel) DataModel;
+ dataModel.Hp = _memory.ReadInt32(playerPointer + 0x340);
+ dataModel.MaxHp = _memory.ReadInt32(playerPointer + 0x338);
+ dataModel.Mana = _memory.ReadInt32(playerPointer + 0x344);
+ dataModel.MaxMana = _memory.ReadInt32(playerPointer + 0x348);
+ dataModel.Breath = _memory.ReadInt32(playerPointer + 0x2B4);
+ dataModel.MaxBreath = _memory.ReadInt32(playerPointer + 0x2B0);
+ dataModel.InWater = Convert.ToBoolean(_memory.ReadInt32(playerPointer + 0x1D));
+ dataModel.InLava = Convert.ToBoolean(_memory.ReadInt32(playerPointer + 0x20));
+ }
+ }
+}
diff --git a/Artemis/Artemis/Modules/Games/Terraria/TerrariaSettings.cs b/Artemis/Artemis/Modules/Games/Terraria/TerrariaSettings.cs
new file mode 100644
index 000000000..c155ff365
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/Terraria/TerrariaSettings.cs
@@ -0,0 +1,8 @@
+using Artemis.Modules.Abstract;
+
+namespace Artemis.Modules.Games.Terraria
+{
+ public class TerrariaSettings : ModuleSettings
+ {
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/Terraria/TerrariaView.xaml b/Artemis/Artemis/Modules/Games/Terraria/TerrariaView.xaml
new file mode 100644
index 000000000..f5cf0d7e4
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/Terraria/TerrariaView.xaml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/Terraria/TerrariaView.xaml.cs b/Artemis/Artemis/Modules/Games/Terraria/TerrariaView.xaml.cs
new file mode 100644
index 000000000..74e35cfb8
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/Terraria/TerrariaView.xaml.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace Artemis.Modules.Games.Terraria
+{
+ ///
+ /// Interaction logic for TerrariaView.xaml
+ ///
+ public partial class TerrariaView : UserControl
+ {
+ public TerrariaView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Artemis/Artemis/Modules/Games/Terraria/TerrariaViewModel.cs b/Artemis/Artemis/Modules/Games/Terraria/TerrariaViewModel.cs
new file mode 100644
index 000000000..709d7e748
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/Terraria/TerrariaViewModel.cs
@@ -0,0 +1,47 @@
+using Artemis.DAL;
+using Artemis.Managers;
+using Artemis.Modules.Abstract;
+using Artemis.Settings;
+using Artemis.Utilities;
+using Ninject;
+
+namespace Artemis.Modules.Games.Terraria
+{
+ public sealed class TerrariaViewModel : ModuleViewModel
+ {
+ private string _versionText;
+
+
+ public TerrariaViewModel(MainManager mainManager, [Named(nameof(TerrariaModel))] ModuleModel moduleModel, IKernel kernel) : base(mainManager, moduleModel, kernel)
+ {
+ DisplayName = "Terraria";
+ SetVersionText();
+ }
+
+ public override bool UsesProfileEditor => true;
+
+ public string VersionText
+ {
+ get { return _versionText; }
+ set
+ {
+ if (value == _versionText) return;
+ _versionText = value;
+ NotifyOfPropertyChange(() => VersionText);
+ }
+ }
+
+ private void SetVersionText()
+ {
+ if (!SettingsProvider.Load().EnablePointersUpdate)
+ {
+ VersionText = "You disabled pointer updates, this could result in the Terraria module not working after a game update.";
+ return;
+ }
+
+ Updater.GetPointers();
+ var version = SettingsProvider.Load().Terraria?.GameVersion;
+ VersionText = $"Requires patch {version}. When a new patch is released Artemis downloads new pointers for the latest version (unless disabled in settings).";
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/General/GeneralProfile/GeneralProfileModel.cs b/Artemis/Artemis/Modules/General/GeneralProfile/GeneralProfileModel.cs
index 56ac83987..dbe22a298 100644
--- a/Artemis/Artemis/Modules/General/GeneralProfile/GeneralProfileModel.cs
+++ b/Artemis/Artemis/Modules/General/GeneralProfile/GeneralProfileModel.cs
@@ -11,6 +11,7 @@ using Artemis.Events;
using Artemis.Managers;
using Artemis.Modules.Abstract;
using Artemis.Utilities;
+using Artemis.Utilities.ActiveWindowDetection;
using CSCore.CoreAudioAPI;
using Newtonsoft.Json;
using SpotifyAPI.Local;
diff --git a/Artemis/Artemis/Modules/General/GeneralProfile/GeneralProfileView.xaml b/Artemis/Artemis/Modules/General/GeneralProfile/GeneralProfileView.xaml
index ba95e4a36..a512a3593 100644
--- a/Artemis/Artemis/Modules/General/GeneralProfile/GeneralProfileView.xaml
+++ b/Artemis/Artemis/Modules/General/GeneralProfile/GeneralProfileView.xaml
@@ -1,12 +1,6 @@
-
+
diff --git a/Artemis/Artemis/Profiles/Layers/Models/LayerKeybindModel.cs b/Artemis/Artemis/Profiles/Layers/Models/LayerKeybindModel.cs
index 087e506ec..74453a110 100644
--- a/Artemis/Artemis/Profiles/Layers/Models/LayerKeybindModel.cs
+++ b/Artemis/Artemis/Profiles/Layers/Models/LayerKeybindModel.cs
@@ -63,9 +63,15 @@ namespace Artemis.Profiles.Layers.Models
switch (ToggleType)
{
case ToggleType.Enable:
+ // Apply RenderAllowed only if this is the first keybind
+ if (index == 0)
+ layerModel.RenderAllowed = false;
action = () => layerModel.RenderAllowed = true;
break;
case ToggleType.Disable:
+ // Apply RenderAllowed only if this is the first keybind
+ if (index == 0)
+ layerModel.RenderAllowed = false;
action = () => layerModel.RenderAllowed = false;
break;
case ToggleType.Toggle:
diff --git a/Artemis/Artemis/Profiles/Layers/Models/LayerModel.cs b/Artemis/Artemis/Profiles/Layers/Models/LayerModel.cs
index 8007936f5..25f27bf48 100644
--- a/Artemis/Artemis/Profiles/Layers/Models/LayerModel.cs
+++ b/Artemis/Artemis/Profiles/Layers/Models/LayerModel.cs
@@ -1,261 +1,261 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Windows;
-using System.Windows.Media;
-using Artemis.Modules.Abstract;
-using Artemis.Profiles.Layers.Abstract;
-using Artemis.Profiles.Layers.Animations;
-using Artemis.Profiles.Layers.Conditions;
-using Artemis.Profiles.Layers.Interfaces;
-using Artemis.Profiles.Layers.Types.Keyboard;
-using Artemis.Utilities;
-using Artemis.Utilities.ParentChild;
-using Newtonsoft.Json;
-
-namespace Artemis.Profiles.Layers.Models
-{
- public class LayerModel : IChildItem, IChildItem
- {
- public LayerModel()
- {
- Children = new ChildItemCollection(this);
- TweenModel = new TweenModel(this);
- RenderAllowed = true;
-
- var model = Properties as KeyboardPropertiesModel;
- if (model != null)
- GifImage = new GifImage(model.GifFile, Properties.AnimationSpeed);
- }
-
- [JsonIgnore]
- public ImageSource LayerImage => LayerType.DrawThumbnail(this);
-
- [JsonIgnore]
- public TweenModel TweenModel { get; set; }
-
- ///
- /// Checks whether this layers conditions are met.
- /// If they are met and this layer is an event, this also triggers that event.
- ///
- ///
- ///
- public bool AreConditionsMet(ModuleDataModel dataModel)
- {
- // Conditions are not even checked if the layer isn't enabled
- return Enabled && LayerCondition.ConditionsMet(this, dataModel);
- }
-
- ///
- /// Update the layer
- ///
- ///
- ///
- ///
- public void Update(ModuleDataModel dataModel, bool preview, bool updateAnimations)
- {
- if (LayerType == null)
- return;
-
- LayerType.Update(this, dataModel, preview);
- LayerAnimation?.Update(this, updateAnimations);
-
- if (!preview)
- TweenModel.Update();
-
- LastRender = DateTime.Now;
- }
-
- ///
- /// Applies the saved properties to the current properties
- ///
- /// Include advanced properties (opacity, brush)
- public void ApplyProperties(bool advanced)
- {
- X = Properties.X;
- Y = Properties.Y;
- Width = Properties.Width;
- Height = Properties.Height;
-
- if (!advanced)
- return;
-
- Opacity = Properties.Opacity;
- Brush = Properties.Brush;
- }
-
- ///
- /// Draw the layer using the provided context
- ///
- ///
- ///
- ///
- ///
- public void Draw(ModuleDataModel dataModel, DrawingContext c, bool preview, bool updateAnimations)
- {
- if (Brush == null || !preview && !RenderAllowed)
- return;
-
- LayerType.Draw(this, c);
- }
-
- ///
- /// Tells the current layer type to setup the layer's LayerProperties
- ///
- public void SetupProperties()
- {
- LayerType.SetupProperties(this);
-
- // If the type is an event, set it up
- if (IsEvent && EventProperties == null)
- EventProperties = new KeyboardEventPropertiesModel
- {
- ExpirationType = ExpirationType.Time,
- Length = new TimeSpan(0, 0, 1),
- TriggerDelay = new TimeSpan(0)
- };
- }
-
- ///
- /// Ensures all child layers have a unique order
- ///
- public void FixOrder()
- {
- Children.Sort(l => l.Order);
- for (var i = 0; i < Children.Count; i++)
- Children[i].Order = i;
- }
-
- ///
- /// Returns whether the layer meets the requirements to be drawn in the profile editor
- ///
- ///
- public bool MustDraw()
- {
- // If any of the parents are disabled, this layer must not be drawn
- var parent = Parent;
- while (parent != null)
- {
- if (!parent.Enabled)
- return false;
- parent = parent.Parent;
- }
- return Enabled && LayerType.ShowInEdtor;
- }
-
- ///
- /// Returns every descendant of this layer
- ///
- ///
- public IEnumerable GetLayers()
- {
- var layers = new List();
- foreach (var layerModel in Children.OrderBy(c => c.Order))
- {
- layers.Add(layerModel);
- layers.AddRange(layerModel.GetLayers());
- }
-
- return layers;
- }
-
- ///
- /// Creates a new Keyboard layer with default settings
- ///
- ///
- public static LayerModel CreateLayer()
- {
- return new LayerModel
- {
- Name = "New layer",
- Enabled = true,
- Order = -1,
- LayerType = new KeyboardType(),
- LayerCondition = new DataModelCondition(),
- LayerAnimation = new NoneAnimation(),
- Properties = new KeyboardPropertiesModel
- {
- Brush = new SolidColorBrush(ColorHelpers.GetRandomRainbowMediaColor()),
- Height = 1,
- Width = 1,
- X = 0,
- Y = 0,
- Opacity = 1,
- HeightEaseTime = 0,
- HeightEase = "Linear",
- WidthEaseTime = 0,
- WidthEase = "Linear",
- OpacityEaseTime = 0,
- OpacityEase = "Linear"
- }
- };
- }
-
- ///
- /// Insert this layer before the given layer
- ///
- ///
- public void InsertBefore(LayerModel source)
- {
- source.Order = Order;
- Insert(source);
- }
-
- ///
- /// Insert this layer after the given layer
- ///
- ///
- public void InsertAfter(LayerModel source)
- {
- source.Order = Order + 1;
- Insert(source);
- }
-
- ///
- /// Insert the layer as a sibling
- ///
- ///
- private void Insert(LayerModel source)
- {
- if (Parent != null)
- {
- foreach (var child in Parent.Children.OrderBy(c => c.Order))
- if (child.Order >= source.Order)
- child.Order++;
- Parent.Children.Add(source);
- }
- else if (Profile != null)
- {
- foreach (var layer in Profile.Layers.OrderBy(l => l.Order))
- if (layer.Order >= source.Order)
- layer.Order++;
- Profile.Layers.Add(source);
- }
- }
-
- public Rect LayerRect(int scale = 4)
- {
- var width = Width;
- var height = Height;
- if (width < 0)
- width = 0;
- if (height < 0)
- height = 0;
-
- return new Rect(X * scale, Y * scale, width * scale, height * scale);
- }
-
- // TODO: Make this and ProfileModel's GetRenderLayers the same through inheritance
- ///
- /// Generates a flat list containing all layers that must be rendered on the keyboard,
- /// the first mouse layer to be rendered and the first headset layer to be rendered
- ///
- /// Instance of said game data model
- /// Whether or not to ignore anything but keyboards
- ///
- /// A flat list containing all layers that must be rendered
- public List GetRenderLayers(ModuleDataModel dataModel, bool keyboardOnly, bool ignoreConditions = false)
- {
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows;
+using System.Windows.Media;
+using Artemis.Modules.Abstract;
+using Artemis.Profiles.Layers.Abstract;
+using Artemis.Profiles.Layers.Animations;
+using Artemis.Profiles.Layers.Conditions;
+using Artemis.Profiles.Layers.Interfaces;
+using Artemis.Profiles.Layers.Types.Keyboard;
+using Artemis.Utilities;
+using Artemis.Utilities.ParentChild;
+using Newtonsoft.Json;
+
+namespace Artemis.Profiles.Layers.Models
+{
+ public class LayerModel : IChildItem, IChildItem
+ {
+ public LayerModel()
+ {
+ Children = new ChildItemCollection(this);
+ TweenModel = new TweenModel(this);
+ RenderAllowed = true;
+
+ var model = Properties as KeyboardPropertiesModel;
+ if (model != null)
+ GifImage = new GifImage(model.GifFile, Properties.AnimationSpeed);
+ }
+
+ [JsonIgnore]
+ public ImageSource LayerImage => LayerType.DrawThumbnail(this);
+
+ [JsonIgnore]
+ public TweenModel TweenModel { get; set; }
+
+ ///
+ /// Checks whether this layers conditions are met.
+ /// If they are met and this layer is an event, this also triggers that event.
+ ///
+ ///
+ ///
+ public bool AreConditionsMet(ModuleDataModel dataModel)
+ {
+ // Conditions are not even checked if the layer isn't enabled
+ return Enabled && LayerCondition.ConditionsMet(this, dataModel);
+ }
+
+ ///
+ /// Update the layer
+ ///
+ ///
+ ///
+ ///
+ public void Update(ModuleDataModel dataModel, bool preview, bool updateAnimations)
+ {
+ if (LayerType == null)
+ return;
+
+ LayerType.Update(this, dataModel, preview);
+ LayerAnimation?.Update(this, updateAnimations);
+
+ if (!preview)
+ TweenModel.Update();
+
+ LastRender = DateTime.Now;
+ }
+
+ ///
+ /// Applies the saved properties to the current properties
+ ///
+ /// Include advanced properties (opacity, brush)
+ public void ApplyProperties(bool advanced)
+ {
+ X = Properties.X;
+ Y = Properties.Y;
+ Width = Properties.Width;
+ Height = Properties.Height;
+
+ if (!advanced)
+ return;
+
+ Opacity = Properties.Opacity;
+ Brush = Properties.Brush;
+ }
+
+ ///
+ /// Draw the layer using the provided context
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void Draw(ModuleDataModel dataModel, DrawingContext c, bool preview, bool updateAnimations)
+ {
+ if (Brush == null || !preview && !RenderAllowed)
+ return;
+
+ LayerType.Draw(this, c);
+ }
+
+ ///
+ /// Tells the current layer type to setup the layer's LayerProperties
+ ///
+ public void SetupProperties()
+ {
+ LayerType.SetupProperties(this);
+
+ // If the type is an event, set it up
+ if (IsEvent && EventProperties == null)
+ EventProperties = new KeyboardEventPropertiesModel
+ {
+ ExpirationType = ExpirationType.Time,
+ Length = new TimeSpan(0, 0, 1),
+ TriggerDelay = new TimeSpan(0)
+ };
+ }
+
+ ///
+ /// Ensures all child layers have a unique order
+ ///
+ public void FixOrder()
+ {
+ Children.Sort(l => l.Order);
+ for (var i = 0; i < Children.Count; i++)
+ Children[i].Order = i;
+ }
+
+ ///
+ /// Returns whether the layer meets the requirements to be drawn in the profile editor
+ ///
+ ///
+ public bool MustDraw()
+ {
+ // If any of the parents are disabled, this layer must not be drawn
+ var parent = Parent;
+ while (parent != null)
+ {
+ if (!parent.Enabled)
+ return false;
+ parent = parent.Parent;
+ }
+ return Enabled && LayerType.ShowInEdtor;
+ }
+
+ ///
+ /// Returns every descendant of this layer
+ ///
+ ///
+ public IEnumerable GetLayers()
+ {
+ var layers = new List();
+ foreach (var layerModel in Children.OrderBy(c => c.Order))
+ {
+ layers.Add(layerModel);
+ layers.AddRange(layerModel.GetLayers());
+ }
+
+ return layers;
+ }
+
+ ///
+ /// Creates a new Keyboard layer with default settings
+ ///
+ ///
+ public static LayerModel CreateLayer()
+ {
+ return new LayerModel
+ {
+ Name = "New layer",
+ Enabled = true,
+ Order = -1,
+ LayerType = new KeyboardType(),
+ LayerCondition = new DataModelCondition(),
+ LayerAnimation = new NoneAnimation(),
+ Properties = new KeyboardPropertiesModel
+ {
+ Brush = new SolidColorBrush(ColorHelpers.GetRandomRainbowMediaColor()),
+ Height = 1,
+ Width = 1,
+ X = 0,
+ Y = 0,
+ Opacity = 1,
+ HeightEaseTime = 0,
+ HeightEase = "Linear",
+ WidthEaseTime = 0,
+ WidthEase = "Linear",
+ OpacityEaseTime = 0,
+ OpacityEase = "Linear"
+ }
+ };
+ }
+
+ ///
+ /// Insert this layer before the given layer
+ ///
+ ///
+ public void InsertBefore(LayerModel source)
+ {
+ source.Order = Order;
+ Insert(source);
+ }
+
+ ///
+ /// Insert this layer after the given layer
+ ///
+ ///
+ public void InsertAfter(LayerModel source)
+ {
+ source.Order = Order + 1;
+ Insert(source);
+ }
+
+ ///
+ /// Insert the layer as a sibling
+ ///
+ ///
+ private void Insert(LayerModel source)
+ {
+ if (Parent != null)
+ {
+ foreach (var child in Parent.Children.OrderBy(c => c.Order))
+ if (child.Order >= source.Order)
+ child.Order++;
+ Parent.Children.Add(source);
+ }
+ else if (Profile != null)
+ {
+ foreach (var layer in Profile.Layers.OrderBy(l => l.Order))
+ if (layer.Order >= source.Order)
+ layer.Order++;
+ Profile.Layers.Add(source);
+ }
+ }
+
+ public Rect LayerRect(int scale = 4)
+ {
+ var width = Width;
+ var height = Height;
+ if (width < 0)
+ width = 0;
+ if (height < 0)
+ height = 0;
+
+ return new Rect(X * scale, Y * scale, width * scale, height * scale);
+ }
+
+ // TODO: Make this and ProfileModel's GetRenderLayers the same through inheritance
+ ///
+ /// Generates a flat list containing all layers that must be rendered on the keyboard,
+ /// the first mouse layer to be rendered and the first headset layer to be rendered
+ ///
+ /// Instance of said game data model
+ /// Whether or not to ignore anything but keyboards
+ ///
+ /// A flat list containing all layers that must be rendered
+ public List GetRenderLayers(ModuleDataModel dataModel, bool keyboardOnly, bool ignoreConditions = false)
+ {
var layers = new List();
foreach (var layerModel in Children.OrderByDescending(l => l.Order))
{
@@ -272,149 +272,149 @@ namespace Artemis.Profiles.Layers.Models
layers.AddRange(layerModel.GetRenderLayers(dataModel, keyboardOnly, ignoreConditions));
}
- return layers;
- }
-
- public void SetupCondition()
- {
- if (IsEvent && !(LayerCondition is EventCondition))
- LayerCondition = new EventCondition();
- else if (!IsEvent && !(LayerCondition is DataModelCondition))
- LayerCondition = new DataModelCondition();
- }
-
- public void SetupKeybinds()
- {
- RenderAllowed = true;
-
- // Clean up old keybinds
- RemoveKeybinds();
-
- for (var index = 0; index < Properties.LayerKeybindModels.Count; index++)
- {
- var keybindModel = Properties.LayerKeybindModels[index];
- keybindModel.Register(this, index);
- }
- }
-
- public void RemoveKeybinds()
- {
- foreach (var keybindModel in Properties.LayerKeybindModels)
- keybindModel.Unregister();
- }
-
- #region Properties
-
- #region Layer type properties
-
- public ILayerType LayerType { get; set; }
- public ILayerCondition LayerCondition { get; set; }
- public ILayerAnimation LayerAnimation { get; set; }
-
- #endregion
-
- #region Generic properties
-
- public string Name { get; set; }
- public int Order { get; set; }
- public bool Enabled { get; set; }
- public bool RenderAllowed { get; set; }
- public bool Expanded { get; set; }
- public bool IsEvent { get; set; }
- public LayerPropertiesModel Properties { get; set; }
- public EventPropertiesModel EventProperties { get; set; }
-
- #endregion
-
- #region Relational properties
-
- public ChildItemCollection Children { get; }
-
- [JsonIgnore]
- public LayerModel Parent { get; internal set; }
-
- [JsonIgnore]
- public ProfileModel Profile { get; internal set; }
-
- #endregion
-
- #region Render properties
-
- [JsonIgnore] private Brush _brush;
-
- [JsonIgnore]
- public double X { get; set; }
-
- [JsonIgnore]
- public double Y { get; set; }
-
- [JsonIgnore]
- public double Width { get; set; }
-
- [JsonIgnore]
- public double Height { get; set; }
-
- [JsonIgnore]
- public double Opacity { get; set; }
-
- [JsonIgnore]
- public Brush Brush
- {
- get { return _brush; }
- set
- {
- if (value == null)
- {
- _brush = null;
- return;
- }
-
- if (value.IsFrozen)
- {
- _brush = value;
- return;
- }
-
- // Clone the brush off of the UI thread and freeze it
- var cloned = value.Dispatcher.Invoke(value.CloneCurrentValue);
- cloned.Freeze();
- _brush = cloned;
- }
- }
-
- [JsonIgnore]
- public double AnimationProgress { get; set; }
-
- [JsonIgnore]
- public GifImage GifImage { get; set; }
-
- [JsonIgnore]
- public DateTime LastRender { get; set; }
-
- #endregion
-
- #endregion
-
- #region IChildItem Members
-
- LayerModel IChildItem.Parent
- {
- get { return Parent; }
- set { Parent = value; }
- }
-
- ProfileModel IChildItem.Parent
- {
- get { return Profile; }
- set { Profile = value; }
- }
-
- #endregion
-
- ///
- public override string ToString()
- {
- return $"{nameof(Name)}: {Name}, {nameof(Order)}: {Order}, {nameof(X)}: {X}, {nameof(Y)}: {Y}, {nameof(Width)}: {Width}, {nameof(Height)}: {Height}";
- }
- }
-}
+ return layers;
+ }
+
+ public void SetupCondition()
+ {
+ if (IsEvent && !(LayerCondition is EventCondition))
+ LayerCondition = new EventCondition();
+ else if (!IsEvent && !(LayerCondition is DataModelCondition))
+ LayerCondition = new DataModelCondition();
+ }
+
+ public void SetupKeybinds()
+ {
+ RenderAllowed = true;
+
+ // Clean up old keybinds
+ RemoveKeybinds();
+
+ for (var index = 0; index < Properties.LayerKeybindModels.Count; index++)
+ {
+ var keybindModel = Properties.LayerKeybindModels[index];
+ keybindModel.Register(this, index);
+ }
+ }
+
+ public void RemoveKeybinds()
+ {
+ foreach (var keybindModel in Properties.LayerKeybindModels)
+ keybindModel.Unregister();
+ }
+
+ #region Properties
+
+ #region Layer type properties
+
+ public ILayerType LayerType { get; set; }
+ public ILayerCondition LayerCondition { get; set; }
+ public ILayerAnimation LayerAnimation { get; set; }
+
+ #endregion
+
+ #region Generic properties
+
+ public string Name { get; set; }
+ public int Order { get; set; }
+ public bool Enabled { get; set; }
+ public bool RenderAllowed { get; set; }
+ public bool Expanded { get; set; }
+ public bool IsEvent { get; set; }
+ public LayerPropertiesModel Properties { get; set; }
+ public EventPropertiesModel EventProperties { get; set; }
+
+ #endregion
+
+ #region Relational properties
+
+ public ChildItemCollection Children { get; }
+
+ [JsonIgnore]
+ public LayerModel Parent { get; internal set; }
+
+ [JsonIgnore]
+ public ProfileModel Profile { get; internal set; }
+
+ #endregion
+
+ #region Render properties
+
+ [JsonIgnore] private Brush _brush;
+
+ [JsonIgnore]
+ public double X { get; set; }
+
+ [JsonIgnore]
+ public double Y { get; set; }
+
+ [JsonIgnore]
+ public double Width { get; set; }
+
+ [JsonIgnore]
+ public double Height { get; set; }
+
+ [JsonIgnore]
+ public double Opacity { get; set; }
+
+ [JsonIgnore]
+ public Brush Brush
+ {
+ get { return _brush; }
+ set
+ {
+ if (value == null)
+ {
+ _brush = null;
+ return;
+ }
+
+ if (value.IsFrozen)
+ {
+ _brush = value;
+ return;
+ }
+
+ // Clone the brush off of the UI thread and freeze it
+ var cloned = value.Dispatcher.Invoke(value.CloneCurrentValue);
+ cloned.Freeze();
+ _brush = cloned;
+ }
+ }
+
+ [JsonIgnore]
+ public double AnimationProgress { get; set; }
+
+ [JsonIgnore]
+ public GifImage GifImage { get; set; }
+
+ [JsonIgnore]
+ public DateTime LastRender { get; set; }
+
+ #endregion
+
+ #endregion
+
+ #region IChildItem Members
+
+ LayerModel IChildItem.Parent
+ {
+ get { return Parent; }
+ set { Parent = value; }
+ }
+
+ ProfileModel IChildItem.Parent
+ {
+ get { return Profile; }
+ set { Profile = value; }
+ }
+
+ #endregion
+
+ ///
+ public override string ToString()
+ {
+ return $"{nameof(Name)}: {Name}, {nameof(Order)}: {Order}, {nameof(X)}: {X}, {nameof(Y)}: {Y}, {nameof(Width)}: {Width}, {nameof(Height)}: {Height}";
+ }
+ }
+}
diff --git a/Artemis/Artemis/Profiles/Layers/Models/LayerPropertiesModel.cs b/Artemis/Artemis/Profiles/Layers/Models/LayerPropertiesModel.cs
index c1ec39f17..3fcd8df46 100644
--- a/Artemis/Artemis/Profiles/Layers/Models/LayerPropertiesModel.cs
+++ b/Artemis/Artemis/Profiles/Layers/Models/LayerPropertiesModel.cs
@@ -1,95 +1,95 @@
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Windows;
-using System.Windows.Media;
-using Artemis.Utilities.Converters;
-using Newtonsoft.Json;
-
-namespace Artemis.Profiles.Layers.Models
-{
- public abstract class LayerPropertiesModel
- {
- private Brush _brush;
-
- public LayerPropertiesModel(LayerPropertiesModel source = null)
- {
- if (source == null)
- return;
-
- // Clone the source's properties onto the new properties model (useful when changing property type)
- X = source.X;
- Y = source.Y;
- Width = source.Width;
- Height = source.Height;
- Contain = source.Contain;
- Opacity = source.Opacity;
- AnimationSpeed = source.AnimationSpeed;
- Conditions = source.Conditions;
- LayerKeybindModels = source.LayerKeybindModels;
- ConditionType = source.ConditionType;
- DynamicProperties = source.DynamicProperties;
- Brush = source.Brush;
- HeightEase = source.HeightEase;
- WidthEase = source.WidthEase;
- OpacityEase = source.OpacityEase;
- HeightEaseTime = source.HeightEaseTime;
- WidthEaseTime = source.WidthEaseTime;
- OpacityEaseTime = source.OpacityEaseTime;
- }
-
- public double X { get; set; }
- public double Y { get; set; }
- public double Width { get; set; }
- public double Height { get; set; }
- public bool Contain { get; set; }
- public double Opacity { get; set; }
- public double AnimationSpeed { get; set; }
- public double OpacityEaseTime { get; set; }
- public double HeightEaseTime { get; set; }
- public double WidthEaseTime { get; set; }
- public string WidthEase { set; get; }
- public string HeightEase { get; set; }
- public string OpacityEase { get; set; }
- public ConditionType ConditionType { get; set; }
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Windows;
+using System.Windows.Media;
+using Artemis.Utilities.Converters;
+using Newtonsoft.Json;
+
+namespace Artemis.Profiles.Layers.Models
+{
+ public abstract class LayerPropertiesModel
+ {
+ private Brush _brush;
+
+ public LayerPropertiesModel(LayerPropertiesModel source = null)
+ {
+ if (source == null)
+ return;
+
+ // Clone the source's properties onto the new properties model (useful when changing property type)
+ X = source.X;
+ Y = source.Y;
+ Width = source.Width;
+ Height = source.Height;
+ Contain = source.Contain;
+ Opacity = source.Opacity;
+ AnimationSpeed = source.AnimationSpeed;
+ Conditions = source.Conditions;
+ LayerKeybindModels = source.LayerKeybindModels;
+ ConditionType = source.ConditionType;
+ DynamicProperties = source.DynamicProperties;
+ Brush = source.Brush;
+ HeightEase = source.HeightEase;
+ WidthEase = source.WidthEase;
+ OpacityEase = source.OpacityEase;
+ HeightEaseTime = source.HeightEaseTime;
+ WidthEaseTime = source.WidthEaseTime;
+ OpacityEaseTime = source.OpacityEaseTime;
+ }
+
+ public double X { get; set; }
+ public double Y { get; set; }
+ public double Width { get; set; }
+ public double Height { get; set; }
+ public bool Contain { get; set; }
+ public double Opacity { get; set; }
+ public double AnimationSpeed { get; set; }
+ public double OpacityEaseTime { get; set; }
+ public double HeightEaseTime { get; set; }
+ public double WidthEaseTime { get; set; }
+ public string WidthEase { set; get; }
+ public string HeightEase { get; set; }
+ public string OpacityEase { get; set; }
+ public ConditionType ConditionType { get; set; }
public List Conditions { get; set; } = new List();
- public List LayerKeybindModels { get; set; } = new List();
- public List DynamicProperties { get; set; } = new List();
-
- [JsonConverter(typeof(BrushJsonConverter))]
- public Brush Brush
- {
- get { return _brush; }
- set
- {
- if (value == null)
- {
- _brush = null;
- return;
- }
-
- if (value.IsFrozen)
- {
- _brush = value;
- return;
- }
-
- // Clone the brush off of the UI thread and freeze it
- var cloned = value.Dispatcher.Invoke(value.CloneCurrentValue);
- cloned.Freeze();
- _brush = cloned;
- }
- }
-
- public Rect PropertiesRect(int scale = 4)
- {
- return new Rect(X*scale, Y*scale, Width*scale, Height*scale);
- }
- }
-
- public enum ConditionType
- {
- [Description("All met")] AllMet,
- [Description("Any met")] AnyMet,
- [Description("None met")] NoneMet
- }
+ public List LayerKeybindModels { get; set; } = new List();
+ public List DynamicProperties { get; set; } = new List();
+
+ [JsonConverter(typeof(BrushJsonConverter))]
+ public Brush Brush
+ {
+ get { return _brush; }
+ set
+ {
+ if (value == null)
+ {
+ _brush = null;
+ return;
+ }
+
+ if (value.IsFrozen)
+ {
+ _brush = value;
+ return;
+ }
+
+ // Clone the brush off of the UI thread and freeze it
+ var cloned = value.Dispatcher.Invoke(value.CloneCurrentValue);
+ cloned.Freeze();
+ _brush = cloned;
+ }
+ }
+
+ public Rect PropertiesRect(int scale = 4)
+ {
+ return new Rect(X*scale, Y*scale, Width*scale, Height*scale);
+ }
+ }
+
+ public enum ConditionType
+ {
+ [Description("All met")] AllMet,
+ [Description("Any met")] AnyMet,
+ [Description("None met")] NoneMet
+ }
}
\ No newline at end of file
diff --git a/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/ScreenCapturing/DX9ScreenCapture.cs b/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/ScreenCapturing/DX9ScreenCapture.cs
index 13c8c02c3..a9b467703 100644
--- a/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/ScreenCapturing/DX9ScreenCapture.cs
+++ b/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/ScreenCapturing/DX9ScreenCapture.cs
@@ -2,6 +2,7 @@
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Windows.Media;
+using Microsoft.Win32;
using SharpDX.Direct3D9;
namespace Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing
@@ -15,6 +16,14 @@ namespace Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing
Width = Screen.PrimaryScreen.Bounds.Width;
Height = Screen.PrimaryScreen.Bounds.Height;
+ //DarthAffe 08.04.2017: Fix for systems using windows-scaling. The primary screen size is reported 'wrong'.
+ double scaling = GetScaling();
+ if (Math.Abs(scaling - 1.0) > 0.01)
+ {
+ Width = (int)(Width / scaling);
+ Height = (int)(Height / scaling);
+ }
+
var presentParams = new PresentParameters(Width, Height)
{
Windowed = true,
@@ -24,7 +33,7 @@ namespace Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing
_device = new Device(new Direct3D(), 0, DeviceType.Hardware, IntPtr.Zero,
CreateFlags.SoftwareVertexProcessing, presentParams);
_surface = Surface.CreateOffscreenPlain(_device, Width, Height, Format.A8R8G8B8, Pool.Scratch);
- _buffer = new byte[Width*Height*4];
+ _buffer = new byte[Width * Height * 4];
}
#endregion
@@ -43,6 +52,19 @@ namespace Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing
#region Methods
+ private double GetScaling()
+ {
+ try
+ {
+ int currentDpi = (int)Registry.GetValue("HKEY_CURRENT_USER\\Control Panel\\Desktop", "LogPixels", 96);
+ return 96.0 / currentDpi;
+ }
+ catch
+ {
+ return 1.0;
+ }
+ }
+
public byte[] CaptureScreen()
{
_device.GetFrontBufferData(0, _surface);
diff --git a/Artemis/Artemis/Profiles/Layers/Types/Audio/AudioCapturing/AudioCapture.cs b/Artemis/Artemis/Profiles/Layers/Types/Audio/AudioCapturing/AudioCapture.cs
index 147deb123..7c721f37a 100644
--- a/Artemis/Artemis/Profiles/Layers/Types/Audio/AudioCapturing/AudioCapture.cs
+++ b/Artemis/Artemis/Profiles/Layers/Types/Audio/AudioCapturing/AudioCapture.cs
@@ -97,18 +97,23 @@ namespace Artemis.Profiles.Layers.Types.Audio.AudioCapturing
}
}
+ private LineSpectrum _lineSpectrum;
public LineSpectrum GetLineSpectrum(int barCount, ScalingStrategy scalingStrategy)
{
- if (_spectrumProvider == null)
+ if (_spectrumProvider == null || barCount <= 0)
return null;
- return new LineSpectrum(FftSize)
- {
- SpectrumProvider = _spectrumProvider,
- UseAverage = true,
- BarCount = barCount,
- IsXLogScale = true,
- ScalingStrategy = scalingStrategy
- };
+
+ if (_lineSpectrum == null)
+ _lineSpectrum = new LineSpectrum(FftSize)
+ {
+ SpectrumProvider = _spectrumProvider,
+ UseAverage = true,
+ BarCount = barCount,
+ IsXLogScale = true,
+ ScalingStrategy = scalingStrategy
+ };
+
+ return _lineSpectrum;
}
///
@@ -148,13 +153,13 @@ namespace Artemis.Profiles.Layers.Types.Audio.AudioCapturing
if (Type == MmDeviceType.Input)
{
_soundIn = Device != null
- ? new WasapiCapture {Device = Device}
+ ? new WasapiCapture { Device = Device }
: new WasapiCapture();
}
else
{
_soundIn = Device != null
- ? new WasapiLoopbackCapture {Device = Device}
+ ? new WasapiLoopbackCapture { Device = Device }
: new WasapiLoopbackCapture();
}
@@ -182,6 +187,7 @@ namespace Artemis.Profiles.Layers.Types.Audio.AudioCapturing
}
};
+ _lineSpectrum = null;
_singleSpectrum = new SingleSpectrum(FftSize, _spectrumProvider);
_mayStop = false;
diff --git a/Artemis/Artemis/Profiles/Layers/Types/Audio/AudioType.cs b/Artemis/Artemis/Profiles/Layers/Types/Audio/AudioType.cs
index eb0b6ef5d..0a6b126e4 100644
--- a/Artemis/Artemis/Profiles/Layers/Types/Audio/AudioType.cs
+++ b/Artemis/Artemis/Profiles/Layers/Types/Audio/AudioType.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Media;
@@ -26,6 +27,7 @@ namespace Artemis.Profiles.Layers.Types.Audio
private List _lineValues;
private AudioPropertiesModel _properties;
private bool _subscribed;
+ private DateTime _lastRender;
public AudioType(AudioCaptureManager audioCaptureManager)
{
@@ -123,8 +125,7 @@ namespace Artemis.Profiles.Layers.Types.Audio
SubscribeToAudioChange();
- if (_audioCapture == null || newProperties.Device != _properties.Device ||
- newProperties.DeviceType != _properties.DeviceType)
+ if (_audioCapture == null || newProperties.Device != _properties.Device || newProperties.DeviceType != _properties.DeviceType)
{
var device = GetMmDevice();
if (device != null)
@@ -153,17 +154,19 @@ namespace Artemis.Profiles.Layers.Types.Audio
currentHeight = layerModel.Width;
}
- if (_lines != currentLines || _lineSpectrum == null)
+ // Get a new line spectrum if the lines changed, it is null or the layer hasn't rendered for a few frames
+ if (_lines != currentLines || _lineSpectrum == null || DateTime.Now - _lastRender > TimeSpan.FromMilliseconds(100))
{
_lines = currentLines;
_lineSpectrum = _audioCapture.GetLineSpectrum(_lines, ScalingStrategy.Decibel);
- if (_lineSpectrum == null)
- return;
}
-
- var newLineValues = _lineSpectrum?.GetLineValues(currentHeight);
+
+ var newLineValues = _audioCapture.GetLineSpectrum(_lines, ScalingStrategy.Decibel)?.GetLineValues(currentHeight);
if (newLineValues != null)
+ {
_lineValues = newLineValues;
+ _lastRender = DateTime.Now;
+ }
}
public void SetupProperties(LayerModel layerModel)
diff --git a/Artemis/Artemis/Profiles/Lua/Modules/Gui/EditorButton.cs b/Artemis/Artemis/Profiles/Lua/Modules/Gui/EditorButton.cs
new file mode 100644
index 000000000..7fe85734b
--- /dev/null
+++ b/Artemis/Artemis/Profiles/Lua/Modules/Gui/EditorButton.cs
@@ -0,0 +1,25 @@
+using Artemis.Managers;
+using MoonSharp.Interpreter;
+
+namespace Artemis.Profiles.Lua.Modules.Gui
+{
+ public class EditorButton
+ {
+ private readonly LuaManager _luaManager;
+
+ public EditorButton(LuaManager luaManager, string text, DynValue action)
+ {
+ _luaManager = luaManager;
+ Text = text;
+ Action = action;
+ }
+
+ public void Invoke()
+ {
+ _luaManager.Call(Action);
+ }
+
+ public string Text { get; }
+ public DynValue Action { get; }
+ }
+}
diff --git a/Artemis/Artemis/Profiles/Lua/Modules/Gui/LuaButton.cs b/Artemis/Artemis/Profiles/Lua/Modules/Gui/LuaButton.cs
new file mode 100644
index 000000000..8cbbbcb92
--- /dev/null
+++ b/Artemis/Artemis/Profiles/Lua/Modules/Gui/LuaButton.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Windows;
+using System.Windows.Controls;
+using Artemis.Managers;
+using MoonSharp.Interpreter;
+using MoonSharp.Interpreter.Interop;
+
+namespace Artemis.Profiles.Lua.Modules.Gui
+{
+ [MoonSharpUserData]
+ public class LuaButton
+ {
+ private readonly LuaManager _luaManager;
+
+ public LuaButton(LuaManager luaManager, string text, double x, double y, double? width, double? height)
+ {
+ _luaManager = luaManager;
+
+ Button = new Button {Content = text};
+ if (width != null)
+ Button.Width = width.Value;
+ if (height != null)
+ Button.Height = height.Value;
+
+ Button.Click += ButtonOnClick;
+ }
+
+ [MoonSharpVisible(false)]
+ public Button Button { get; }
+
+ public string Text
+ {
+ get => Button.Dispatcher.Invoke(() => (string) Button.Content);
+ set => Button.Dispatcher.Invoke(() => Button.Content = value);
+ }
+
+ private void ButtonOnClick(object sender, RoutedEventArgs routedEventArgs)
+ {
+ _luaManager.EventsModule.LuaInvoke(_luaManager.ProfileModel, () => OnClick(this));
+ }
+
+ public event EventHandler Click;
+
+ protected virtual void OnClick(LuaButton button)
+ {
+ Click?.Invoke(button, null);
+ }
+ }
+}
diff --git a/Artemis/Artemis/Profiles/Lua/Modules/Gui/LuaCheckBox.cs b/Artemis/Artemis/Profiles/Lua/Modules/Gui/LuaCheckBox.cs
new file mode 100644
index 000000000..825fe0ca1
--- /dev/null
+++ b/Artemis/Artemis/Profiles/Lua/Modules/Gui/LuaCheckBox.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Windows;
+using System.Windows.Controls;
+using Artemis.Managers;
+using MoonSharp.Interpreter;
+using MoonSharp.Interpreter.Interop;
+
+namespace Artemis.Profiles.Lua.Modules.Gui
+{
+ [MoonSharpUserData]
+ public class LuaCheckBox
+ {
+ private readonly LuaManager _luaManager;
+
+ public LuaCheckBox(LuaManager luaManager, string text, bool isChecked, double x, double y, double? width, double? height)
+ {
+ _luaManager = luaManager;
+
+ CheckBox = new CheckBox {Content = text, IsChecked = isChecked};
+ if (width != null)
+ CheckBox.Width = width.Value;
+ if (height != null)
+ CheckBox.Height = height.Value;
+
+ CheckBox.Click += CheckBoxOnClick;
+ }
+
+ [MoonSharpVisible(false)]
+ public CheckBox CheckBox { get; }
+
+ public string Text
+ {
+ get => CheckBox.Dispatcher.Invoke(() => (string) CheckBox.Content);
+ set => CheckBox.Dispatcher.Invoke(() => CheckBox.Content = value);
+ }
+
+ public bool IsChecked
+ {
+ get => CheckBox.Dispatcher.Invoke(() => CheckBox.IsChecked != null && (bool) CheckBox.IsChecked);
+ set => CheckBox.Dispatcher.Invoke(() => CheckBox.IsChecked = value);
+ }
+
+ private void CheckBoxOnClick(object sender, RoutedEventArgs routedEventArgs)
+ {
+ _luaManager.EventsModule.LuaInvoke(_luaManager.ProfileModel, () => OnClick(this));
+ }
+
+ public event EventHandler Click;
+
+ protected virtual void OnClick(LuaCheckBox checkBox)
+ {
+ Click?.Invoke(checkBox, null);
+ }
+ }
+}
diff --git a/Artemis/Artemis/Profiles/Lua/Modules/Gui/LuaComboBox.cs b/Artemis/Artemis/Profiles/Lua/Modules/Gui/LuaComboBox.cs
new file mode 100644
index 000000000..bb67d84eb
--- /dev/null
+++ b/Artemis/Artemis/Profiles/Lua/Modules/Gui/LuaComboBox.cs
@@ -0,0 +1,70 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Windows.Controls;
+using Artemis.Managers;
+using MoonSharp.Interpreter;
+using MoonSharp.Interpreter.Interop;
+
+namespace Artemis.Profiles.Lua.Modules.Gui
+{
+ [MoonSharpUserData]
+ public class LuaComboBox
+ {
+ private readonly LuaManager _luaManager;
+
+ public LuaComboBox(LuaManager luaManager, string value, List values, double x, double y, double? width, double? height)
+ {
+ _luaManager = luaManager;
+
+ ComboBox = new ComboBox {ItemsSource = new ObservableCollection(values), SelectedItem = value};
+ if (width != null)
+ ComboBox.Width = (double) width;
+ if (height != null)
+ ComboBox.Height = (double) height;
+
+ ComboBox.SelectionChanged += ComboBoxOnSelectionChanged;
+ }
+
+ [MoonSharpVisible(false)]
+ public ComboBox ComboBox { get; }
+
+ public string Value
+ {
+ get => ComboBox.Dispatcher.Invoke(() => (string) ComboBox.SelectedItem);
+ set => ComboBox.Dispatcher.Invoke(() => ComboBox.SelectedItem = value);
+ }
+
+ public void SetValues(string[] values)
+ {
+ var collection = (ObservableCollection) ComboBox.ItemsSource;
+ collection.Clear();
+ foreach (var value in values)
+ collection.Add(value);
+ }
+
+ public void AddValue(string value)
+ {
+ ((ObservableCollection) ComboBox.ItemsSource).Add(value);
+ }
+
+ public void RemoveValue(string value)
+ {
+ var collection = (ObservableCollection) ComboBox.ItemsSource;
+ if (collection.Contains(value))
+ collection.Remove(value);
+ }
+
+ private void ComboBoxOnSelectionChanged(object sender, SelectionChangedEventArgs selectionChangedEventArgs)
+ {
+ _luaManager.EventsModule.LuaInvoke(_luaManager.ProfileModel, () => OnSelectionChanged(this));
+ }
+
+ public event EventHandler SelectionChanged;
+
+ protected virtual void OnSelectionChanged(LuaComboBox comboBox)
+ {
+ SelectionChanged?.Invoke(comboBox, null);
+ }
+ }
+}
diff --git a/Artemis/Artemis/Profiles/Lua/Modules/Gui/LuaLabel.cs b/Artemis/Artemis/Profiles/Lua/Modules/Gui/LuaLabel.cs
new file mode 100644
index 000000000..fa10a4cc2
--- /dev/null
+++ b/Artemis/Artemis/Profiles/Lua/Modules/Gui/LuaLabel.cs
@@ -0,0 +1,30 @@
+using System.Windows;
+using System.Windows.Controls;
+using MoonSharp.Interpreter;
+using MoonSharp.Interpreter.Interop;
+
+namespace Artemis.Profiles.Lua.Modules.Gui
+{
+ [MoonSharpUserData]
+ public class LuaLabel
+ {
+ public LuaLabel(string text, double x, double y, double fontSize = 12, int fontWeight = 400)
+ {
+ Label = new Label
+ {
+ Content = text,
+ FontSize = fontSize,
+ FontWeight = FontWeight.FromOpenTypeWeight(fontWeight)
+ };
+ }
+
+ [MoonSharpVisible(false)]
+ public Label Label { get; }
+
+ public string Text
+ {
+ get => Label.Dispatcher.Invoke(() => (string) Label.Content);
+ set => Label.Dispatcher.Invoke(() => Label.Content = value);
+ }
+ }
+}
diff --git a/Artemis/Artemis/Profiles/Lua/Modules/Gui/LuaTextBox.cs b/Artemis/Artemis/Profiles/Lua/Modules/Gui/LuaTextBox.cs
new file mode 100644
index 000000000..13376adf8
--- /dev/null
+++ b/Artemis/Artemis/Profiles/Lua/Modules/Gui/LuaTextBox.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Windows.Controls;
+using Artemis.Managers;
+using MoonSharp.Interpreter;
+using MoonSharp.Interpreter.Interop;
+
+namespace Artemis.Profiles.Lua.Modules.Gui
+{
+ [MoonSharpUserData]
+ public class LuaTextBox
+ {
+ private readonly LuaManager _luaManager;
+
+ public LuaTextBox(LuaManager luaManager, string text, double x, double y, double? width, double? height)
+ {
+ _luaManager = luaManager;
+
+ TextBox = new TextBox {Text = text};
+ if (width != null)
+ TextBox.Width = width.Value;
+ if (height != null)
+ TextBox.Height = height.Value;
+
+ TextBox.TextChanged += TextBoxOnTextChanged;
+ }
+
+ [MoonSharpVisible(false)]
+ public TextBox TextBox { get; }
+
+ public string Text
+ {
+ get => TextBox.Dispatcher.Invoke(() => TextBox.Text);
+ set => TextBox.Dispatcher.Invoke(() => TextBox.Text = value);
+ }
+
+ private void TextBoxOnTextChanged(object sender, TextChangedEventArgs textChangedEventArgs)
+ {
+ _luaManager.EventsModule.LuaInvoke(_luaManager.ProfileModel, () => OnTextChanged(this));
+ }
+
+ public event EventHandler TextChanged;
+
+ protected virtual void OnTextChanged(LuaTextBox button)
+ {
+ TextChanged?.Invoke(button, null);
+ }
+ }
+}
diff --git a/Artemis/Artemis/Profiles/Lua/Modules/Gui/LuaWindowView.xaml b/Artemis/Artemis/Profiles/Lua/Modules/Gui/LuaWindowView.xaml
new file mode 100644
index 000000000..849d91643
--- /dev/null
+++ b/Artemis/Artemis/Profiles/Lua/Modules/Gui/LuaWindowView.xaml
@@ -0,0 +1,8 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Artemis/Artemis/Profiles/Lua/Modules/Gui/LuaWindowView.xaml.cs b/Artemis/Artemis/Profiles/Lua/Modules/Gui/LuaWindowView.xaml.cs
new file mode 100644
index 000000000..c10b953ac
--- /dev/null
+++ b/Artemis/Artemis/Profiles/Lua/Modules/Gui/LuaWindowView.xaml.cs
@@ -0,0 +1,15 @@
+using MahApps.Metro.Controls;
+
+namespace Artemis.Profiles.Lua.Modules.Gui
+{
+ ///
+ /// Interaction logic for LuaWindowView.xaml
+ ///
+ public partial class LuaWindowView : MetroWindow
+ {
+ public LuaWindowView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Artemis/Artemis/Profiles/Lua/Modules/Gui/LuaWindowViewModel.cs b/Artemis/Artemis/Profiles/Lua/Modules/Gui/LuaWindowViewModel.cs
new file mode 100644
index 000000000..5c927cdb1
--- /dev/null
+++ b/Artemis/Artemis/Profiles/Lua/Modules/Gui/LuaWindowViewModel.cs
@@ -0,0 +1,93 @@
+using System.Collections.Generic;
+using System.Windows;
+using System.Windows.Controls;
+using Artemis.Managers;
+using Caliburn.Micro;
+using MoonSharp.Interpreter;
+
+namespace Artemis.Profiles.Lua.Modules.Gui
+{
+ [MoonSharpUserData]
+ public class LuaWindowViewModel : Screen
+ {
+ private readonly LuaManager _luaManager;
+
+ public LuaWindowViewModel(LuaManager luaManager)
+ {
+ _luaManager = luaManager;
+
+ Canvas = new Canvas();
+ Content = new List {Canvas};
+ }
+
+ public Canvas Canvas { get; set; }
+ public List Content { get; set; }
+
+ public LuaLabel CreateLabel(string text, double x, double y, double fontSize = 12, int fontWeight = 400)
+ {
+ LuaLabel element = null;
+ Execute.OnUIThread(() =>
+ {
+ element = new LuaLabel(text, x, y, fontSize, fontWeight);
+ AddControl(element.Label, x, y);
+ });
+
+ return element;
+ }
+
+ public LuaButton CreateButton(string text, double x, double y, double? width, double? height)
+ {
+ LuaButton element = null;
+ Execute.OnUIThread(() =>
+ {
+ element = new LuaButton(_luaManager, text, x, y, width, height);
+ AddControl(element.Button, x, y);
+ });
+
+ return element;
+ }
+
+ public LuaTextBox CreateTextBox(string text, double x, double y, double? width, double? height)
+ {
+ LuaTextBox element = null;
+ Execute.OnUIThread(() =>
+ {
+ element = new LuaTextBox(_luaManager, text, x, y, width, height);
+ AddControl(element.TextBox, x, y);
+ });
+
+ return element;
+ }
+
+ public LuaComboBox CreateComboBox(string value, List values, double x, double y, double? width, double? height)
+ {
+ LuaComboBox element = null;
+ Execute.OnUIThread(() =>
+ {
+ element = new LuaComboBox(_luaManager, value, values, x, y, width, height);
+ AddControl(element.ComboBox, x, y);
+ });
+
+ return element;
+ }
+
+ public LuaCheckBox CreateCheckBox(string text, bool isChecked, double x, double y, double? width, double? height)
+ {
+ LuaCheckBox element = null;
+ Execute.OnUIThread(() =>
+ {
+ element = new LuaCheckBox(_luaManager, text, isChecked, x, y, width, height);
+ AddControl(element.CheckBox, x, y);
+ });
+
+ return element;
+ }
+
+ private void AddControl(UIElement uiElement, double x, double y)
+ {
+ Canvas.Children.Add(uiElement);
+ Canvas.SetLeft(uiElement, x);
+ Canvas.SetTop(uiElement, y);
+ }
+ }
+}
diff --git a/Artemis/Artemis/Profiles/Lua/Modules/LuaEventsModule.cs b/Artemis/Artemis/Profiles/Lua/Modules/LuaEventsModule.cs
index 02abc90dd..41ceb2176 100644
--- a/Artemis/Artemis/Profiles/Lua/Modules/LuaEventsModule.cs
+++ b/Artemis/Artemis/Profiles/Lua/Modules/LuaEventsModule.cs
@@ -73,7 +73,7 @@ namespace Artemis.Profiles.Lua.Modules
}
}
- private void LuaInvoke(ProfileModel profileModel, Action action)
+ public void LuaInvoke(ProfileModel profileModel, Action action)
{
lock (InvokeLock)
{
diff --git a/Artemis/Artemis/Profiles/Lua/Modules/LuaGuiModule.cs b/Artemis/Artemis/Profiles/Lua/Modules/LuaGuiModule.cs
new file mode 100644
index 000000000..78412738c
--- /dev/null
+++ b/Artemis/Artemis/Profiles/Lua/Modules/LuaGuiModule.cs
@@ -0,0 +1,64 @@
+using System.Collections.Generic;
+using System.Dynamic;
+using System.Linq;
+using Artemis.Managers;
+using Artemis.Profiles.Lua.Modules.Gui;
+using Artemis.Services;
+using Caliburn.Micro;
+using MoonSharp.Interpreter;
+using Ninject.Parameters;
+
+namespace Artemis.Profiles.Lua.Modules
+{
+ [MoonSharpUserData]
+ public class LuaGuiModule : LuaModule
+ {
+ private readonly WindowService _windowService;
+ private readonly List _windows;
+
+ public LuaGuiModule(LuaManager luaManager, WindowService windowService) : base(luaManager)
+ {
+ _windowService = windowService;
+ _windows = new List();
+ }
+
+ public override string ModuleName => "Gui";
+
+ public LuaWindowViewModel CreateWindow(string title, double width, double height)
+ {
+ lock (_windows)
+ {
+ dynamic settings = new ExpandoObject();
+ settings.Width = width;
+ settings.Height = height;
+ IParameter[] args =
+ {
+ new ConstructorArgument("luaManager", LuaManager)
+ };
+
+ Execute.OnUIThread(() => _windows.Add(_windowService.ShowWindow("Artemis | " + title, settings, args)));
+ return _windows.Last();
+ }
+ }
+
+ public void AddEditorButton(string name, DynValue action)
+ {
+ Execute.OnUIThread(() => LuaManager.EditorButtons.Add(new EditorButton(LuaManager, name, action)));
+ }
+
+ public void RemoveEditorButton(string name)
+ {
+ var button = LuaManager.EditorButtons.FirstOrDefault(b => b.Text == name);
+ if (button != null)
+ Execute.OnUIThread(() => LuaManager.EditorButtons.Remove(button));
+ }
+
+ public override void Dispose()
+ {
+ foreach (var window in _windows)
+ window.TryClose();
+
+ Execute.OnUIThread(() => LuaManager.EditorButtons.Clear());
+ }
+ }
+}
diff --git a/Artemis/Artemis/Profiles/Lua/Modules/LuaStorageModule.cs b/Artemis/Artemis/Profiles/Lua/Modules/LuaStorageModule.cs
new file mode 100644
index 000000000..dc3840ba4
--- /dev/null
+++ b/Artemis/Artemis/Profiles/Lua/Modules/LuaStorageModule.cs
@@ -0,0 +1,68 @@
+using Artemis.DAL;
+using Artemis.Managers;
+using Artemis.Settings;
+using MoonSharp.Interpreter;
+using static MoonSharp.Interpreter.Serialization.Json.JsonTableConverter;
+
+namespace Artemis.Profiles.Lua.Modules
+{
+ [MoonSharpUserData]
+ public class LuaStorageModule : LuaModule
+ {
+ private readonly Table _globalValues;
+ private readonly Table _profileValues;
+ private readonly LuaGlobalSettings _globalSettings;
+
+ public LuaStorageModule(LuaManager luaManager) : base(luaManager)
+ {
+ _globalSettings = SettingsProvider.Load();
+
+ // Load profile values
+ if (LuaManager.ProfileModel.LuaStorage != null)
+ _profileValues = JsonToTable(LuaManager.ProfileModel.LuaStorage, LuaManager.LuaScript);
+ else
+ _profileValues = new Table(LuaManager.LuaScript);
+
+ // Load global values
+ if (_globalSettings.GlobalValues != null)
+ _globalValues = JsonToTable(_globalSettings.GlobalValues, LuaManager.LuaScript);
+ else
+ _globalValues = new Table(LuaManager.LuaScript);
+
+ // Set the values onto the globals table so scripters can access them
+ LuaManager.LuaScript.Globals["ProfileStorage"] = _profileValues;
+ LuaManager.LuaScript.Globals["GlobalStorage"] = _globalValues;
+ }
+
+ public override string ModuleName => null;
+
+ public override void Dispose()
+ {
+ // Store profile values
+ LuaManager.ProfileModel.LuaStorage = _profileValues.TableToJson();
+ ProfileProvider.AddOrUpdate(LuaManager.ProfileModel);
+
+ // Store global values
+ _globalSettings.GlobalValues = _globalValues.TableToJson();
+ _globalSettings.Save();
+ }
+ }
+
+ public class LuaGlobalSettings : IArtemisSettings
+ {
+ public string GlobalValues { get; set; }
+
+ public void Save()
+ {
+ SettingsProvider.Save(this);
+ }
+
+ public void Reset(bool save = false)
+ {
+ GlobalValues = null;
+
+ if (save)
+ Save();
+ }
+ }
+}
diff --git a/Artemis/Artemis/Profiles/ProfileModel.cs b/Artemis/Artemis/Profiles/ProfileModel.cs
index f54714c0f..17cfeb245 100644
--- a/Artemis/Artemis/Profiles/ProfileModel.cs
+++ b/Artemis/Artemis/Profiles/ProfileModel.cs
@@ -38,6 +38,7 @@ namespace Artemis.Profiles
public int Width { get; set; }
public int Height { get; set; }
public string LuaScript { get; set; }
+ public string LuaStorage { get; set; }
[JsonIgnore]
public string Slug => new string(Name.Where(ch => !_invalidFileNameChars.Contains(ch)).ToArray());
diff --git a/Artemis/Artemis/Properties/AssemblyInfo.cs b/Artemis/Artemis/Properties/AssemblyInfo.cs
index 44b0032cb..1019f22b2 100644
--- a/Artemis/Artemis/Properties/AssemblyInfo.cs
+++ b/Artemis/Artemis/Properties/AssemblyInfo.cs
@@ -53,7 +53,7 @@ using System.Windows;
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.9.0.0")]
-[assembly: AssemblyFileVersion("1.9.0.0")]
+[assembly: AssemblyVersion("1.10.0.0")]
+[assembly: AssemblyFileVersion("1.10.0.0")]
[assembly: InternalsVisibleTo("Artemis.Explorables")]
diff --git a/Artemis/Artemis/Resources/Keyboards/default-profiles.zip b/Artemis/Artemis/Resources/Keyboards/default-profiles.zip
index 298df243e..8b5ead4d6 100644
Binary files a/Artemis/Artemis/Resources/Keyboards/default-profiles.zip and b/Artemis/Artemis/Resources/Keyboards/default-profiles.zip differ
diff --git a/Artemis/Artemis/Services/CompatibilityService.cs b/Artemis/Artemis/Services/CompatibilityService.cs
new file mode 100644
index 000000000..0bd2d07e2
--- /dev/null
+++ b/Artemis/Artemis/Services/CompatibilityService.cs
@@ -0,0 +1,41 @@
+using System.IO;
+using System.Linq;
+using System.Threading;
+using Microsoft.Win32;
+using NLog;
+
+namespace Artemis.Services
+{
+ public static class CompatibilityService
+ {
+ private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
+
+ // Checks to see if RivaTuner Statistics Server is installed and if so places a profile disabling it for Artemis
+ public static void CheckRivaTuner()
+ {
+ // Find the installation path in the registry
+ var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\WOW6432Node\Unwinder\RTSS");
+ var value = key?.GetValue("InstallPath");
+ var installDir = Path.GetDirectoryName(value?.ToString());
+
+ if (installDir == null)
+ return;
+ var profilePath = Path.Combine(installDir, "ProfileTemplates\\Artemis.exe.cfg");
+ if (File.Exists(profilePath))
+ return;
+
+ File.WriteAllText(profilePath, "[Hooking]\r\nEnableHooking\t\t= 0");
+
+ // It's kill or be killed...
+ var rtssProcess = System.Diagnostics.Process.GetProcessesByName("RTSS").FirstOrDefault();
+ var rtssHookProcess = System.Diagnostics.Process.GetProcessesByName("RTSSHooksLoader64").FirstOrDefault();
+ rtssProcess?.Kill();
+ rtssHookProcess?.Kill();
+
+ // Funnily enough sleeping prevents the RTSS injection so that the process gets killed in time
+ Thread.Sleep(1000);
+
+ Logger.Info("Detected that RivaTuner Statistics Server is installed, inserted a profile to prevent crashes.");
+ }
+ }
+}
diff --git a/Artemis/Artemis/Services/WindowService.cs b/Artemis/Artemis/Services/WindowService.cs
index 4b419a1f7..60f195676 100644
--- a/Artemis/Artemis/Services/WindowService.cs
+++ b/Artemis/Artemis/Services/WindowService.cs
@@ -1,39 +1,41 @@
-using System.Dynamic;
-using Caliburn.Micro;
-using Ninject;
-using Ninject.Parameters;
-
-namespace Artemis.Services
-{
- public class WindowService
- {
- private readonly IKernel _kernel;
-
- public WindowService(IKernel kernel)
- {
- _kernel = kernel;
- }
-
- public T ShowWindow(string windowName, params IParameter[] param) where T : class
- {
- var windowManager = new WindowManager();
+using System.Dynamic;
+using Caliburn.Micro;
+using Ninject;
+using Ninject.Parameters;
+
+namespace Artemis.Services
+{
+ public class WindowService
+ {
+ private readonly IKernel _kernel;
+
+ public WindowService(IKernel kernel)
+ {
+ _kernel = kernel;
+ }
+
+ public T ShowWindow(string windowName, dynamic settings = null, params IParameter[] param) where T : class
+ {
+ var windowManager = new WindowManager();
var viewModel = _kernel.Get(param);
- dynamic settings = new ExpandoObject();
- settings.Title = windowName;
- windowManager.ShowWindow(viewModel, null, settings);
- return viewModel;
- }
-
- public T ShowDialog(string dialogName, params IParameter[] param) where T : class
- {
- var windowManager = new WindowManager();
- var viewModel = _kernel.Get(param);
-
- dynamic settings = new ExpandoObject();
- settings.Title = dialogName;
- windowManager.ShowDialog(viewModel, null, settings);
- return viewModel;
- }
- }
+ if (settings == null)
+ settings = new ExpandoObject();
+ settings.Title = windowName;
+ windowManager.ShowWindow(viewModel, null, settings);
+ return viewModel;
+ }
+
+ public T ShowDialog(string dialogName, dynamic settings = null, params IParameter[] param) where T : class
+ {
+ var windowManager = new WindowManager();
+ var viewModel = _kernel.Get(param);
+
+ if (settings == null)
+ settings = new ExpandoObject();
+ settings.Title = dialogName;
+ windowManager.ShowDialog(viewModel, null, settings);
+ return viewModel;
+ }
+ }
}
\ No newline at end of file
diff --git a/Artemis/Artemis/Settings/GeneralSettings.cs b/Artemis/Artemis/Settings/GeneralSettings.cs
index b304c114d..13240abee 100644
--- a/Artemis/Artemis/Settings/GeneralSettings.cs
+++ b/Artemis/Artemis/Settings/GeneralSettings.cs
@@ -5,9 +5,11 @@ using System.Windows;
using Artemis.DAL;
using Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing;
using Artemis.Utilities;
+using Artemis.Utilities.ActiveWindowDetection;
using Caliburn.Micro;
using MahApps.Metro;
using Newtonsoft.Json;
+using Newtonsoft.Json.Converters;
using Squirrel;
namespace Artemis.Settings
@@ -68,6 +70,11 @@ namespace Artemis.Settings
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
public string LogLevel { get; set; }
+ [DefaultValue(ActiveWindowDetectionType.Events)]
+ [JsonConverter(typeof(StringEnumConverter))]
+ [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
+ public ActiveWindowDetectionType ActiveWindowDetection { get; set; }
+
public Version LastRanVersion { get; set; }
public void Save()
@@ -75,6 +82,7 @@ namespace Artemis.Settings
SettingsProvider.Save(this);
Logging.SetupLogging(LogLevel);
+ ActiveWindowHelper.SetActiveWindowDetectionType(ActiveWindowDetection);
ApplyAutorun();
ApplyTheme();
ApplyGamestatePort();
diff --git a/Artemis/Artemis/Settings/OffsetSettings.cs b/Artemis/Artemis/Settings/OffsetSettings.cs
index 14a63bee0..ddc3bbf5d 100644
--- a/Artemis/Artemis/Settings/OffsetSettings.cs
+++ b/Artemis/Artemis/Settings/OffsetSettings.cs
@@ -8,6 +8,7 @@ namespace Artemis.Settings
{
public GamePointersCollection RocketLeague { get; set; }
public GamePointersCollection WorldOfWarcraft { get; set; }
+ public GamePointersCollection Terraria { get; set; }
public void Save()
{
diff --git a/Artemis/Artemis/Styles/ColorBox.xaml b/Artemis/Artemis/Styles/ColorBox.xaml
index 6c8f49fea..7431a2993 100644
--- a/Artemis/Artemis/Styles/ColorBox.xaml
+++ b/Artemis/Artemis/Styles/ColorBox.xaml
@@ -210,7 +210,7 @@
ItemsSource="{Binding AvailableBrushTypes, RelativeSource={RelativeSource TemplatedParent}}" HorizontalAlignment="Center">
-
+
diff --git a/Artemis/Artemis/Utilities/ActiveWindowDetection/ActiveWindowDetectionType.cs b/Artemis/Artemis/Utilities/ActiveWindowDetection/ActiveWindowDetectionType.cs
new file mode 100644
index 000000000..d567caade
--- /dev/null
+++ b/Artemis/Artemis/Utilities/ActiveWindowDetection/ActiveWindowDetectionType.cs
@@ -0,0 +1,9 @@
+namespace Artemis.Utilities.ActiveWindowDetection
+{
+ public enum ActiveWindowDetectionType
+ {
+ Disabled = -1,
+ Events = 0,
+ Timer = 1,
+ }
+}
diff --git a/Artemis/Artemis/Utilities/ActiveWindowDetection/ActiveWindowHelper.cs b/Artemis/Artemis/Utilities/ActiveWindowDetection/ActiveWindowHelper.cs
new file mode 100644
index 000000000..1edaa2f84
--- /dev/null
+++ b/Artemis/Artemis/Utilities/ActiveWindowDetection/ActiveWindowHelper.cs
@@ -0,0 +1,48 @@
+namespace Artemis.Utilities.ActiveWindowDetection
+{
+ public static class ActiveWindowHelper
+ {
+ #region Properties & Fields
+
+ private static ActiveWindowDetectionType _currentDetectionType = ActiveWindowDetectionType.Disabled;
+ private static IActiveWindowDetector _activeWindowDetector;
+
+ public static string ActiveWindowProcessName => _activeWindowDetector?.ActiveWindowProcessName ?? string.Empty;
+ public static string ActiveWindowWindowTitle => _activeWindowDetector?.ActiveWindowWindowTitle ?? string.Empty;
+ public static bool MainWindowActive => ActiveWindowProcessName.Contains("Artemis");
+
+ #endregion
+
+ #region Methods
+
+ public static void Dispose()
+ {
+ _activeWindowDetector?.Dispose();
+ }
+
+ public static void SetActiveWindowDetectionType(ActiveWindowDetectionType detectionType)
+ {
+ if (detectionType == _currentDetectionType) return;
+
+ _activeWindowDetector?.Dispose();
+
+ switch (detectionType)
+ {
+ case ActiveWindowDetectionType.Events:
+ _activeWindowDetector = new EventActiveWindowDetector();
+ break;
+ case ActiveWindowDetectionType.Timer:
+ _activeWindowDetector = new TimerActiveWindowDetector();
+ break;
+ case ActiveWindowDetectionType.Disabled:
+ _activeWindowDetector = null;
+ break;
+ }
+
+ _activeWindowDetector?.Initialize();
+ _currentDetectionType = detectionType;
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Utilities/ActiveWindowHelper.cs b/Artemis/Artemis/Utilities/ActiveWindowDetection/EventActiveWindowDetector.cs
similarity index 69%
rename from Artemis/Artemis/Utilities/ActiveWindowHelper.cs
rename to Artemis/Artemis/Utilities/ActiveWindowDetection/EventActiveWindowDetector.cs
index 2c9430ee9..3c25a678b 100644
--- a/Artemis/Artemis/Utilities/ActiveWindowHelper.cs
+++ b/Artemis/Artemis/Utilities/ActiveWindowDetection/EventActiveWindowDetector.cs
@@ -2,9 +2,9 @@
using System.Runtime.InteropServices;
using System.Text;
-namespace Artemis.Utilities
+namespace Artemis.Utilities.ActiveWindowDetection
{
- public static class ActiveWindowHelper
+ public class EventActiveWindowDetector : IActiveWindowDetector
{
#region DLL-Imports
@@ -14,7 +14,7 @@ namespace Artemis.Utilities
[DllImport("user32.dll")]
private static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc,
- WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);
+ WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);
[DllImport("user32.dll")]
private static extern bool UnhookWinEvent(IntPtr hWinEventHook);
@@ -41,47 +41,46 @@ namespace Artemis.Utilities
#region Properties & Fields
// DarthAffe 17.12.2016: We need to keep a reference to this or it might get collected by the garbage collector and cause some random crashes afterwards.
- private static WinEventDelegate _activeWindowChangedDelegate;
- private static IntPtr _activeWindowEventHook;
+ private WinEventDelegate _activeWindowChangedDelegate;
+ private IntPtr _activeWindowEventHook;
- private static WinEventDelegate _windowTitleChangedDelegate;
- private static IntPtr _windowTitleEventHook;
+ private WinEventDelegate _windowTitleChangedDelegate;
+ private IntPtr _windowTitleEventHook;
- private static WinEventDelegate _windowMinimizedChangedDelegate;
- private static IntPtr _windowMinimizedEventHook;
+ private WinEventDelegate _windowMinimizedChangedDelegate;
+ private IntPtr _windowMinimizedEventHook;
- private static IntPtr _activeWindow;
+ private IntPtr _activeWindow;
- public static string ActiveWindowProcessName { get; private set; } = string.Empty;
- public static string ActiveWindowWindowTitle { get; private set; } = string.Empty;
- public static bool MainWindowActive => ActiveWindowProcessName.Contains("Artemis");
+ public string ActiveWindowProcessName { get; private set; } = string.Empty;
+ public string ActiveWindowWindowTitle { get; private set; } = string.Empty;
#endregion
#region Methods
- private static void ActiveWindowChanged(IntPtr hWinEventHook, uint eventType,
- IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
+ private void ActiveWindowChanged(IntPtr hWinEventHook, uint eventType,
+ IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
UpdateForWindow(hwnd);
}
- private static void WindowTitleChanged(IntPtr hWinEventHook, uint eventType,
- IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
+ private void WindowTitleChanged(IntPtr hWinEventHook, uint eventType,
+ IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
if (_activeWindow == hwnd)
UpdateForWindow(hwnd);
}
- private static void WindowMinimizedChanged(IntPtr hWinEventHook, uint eventType,
- IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
+ private void WindowMinimizedChanged(IntPtr hWinEventHook, uint eventType,
+ IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
// DarthAffe 19.12.2016: We expect currently un-minimized windows to be active.
// DarthAffe 19.12.2016: The result of the API-function GetActiveWindow at this moment is 'idle' so we can't use this to validate this estimation.
UpdateForWindow(hwnd);
}
- private static void UpdateForWindow(IntPtr hwnd)
+ private void UpdateForWindow(IntPtr hwnd)
{
_activeWindow = hwnd;
@@ -89,13 +88,13 @@ namespace Artemis.Utilities
ActiveWindowWindowTitle = GetActiveWindowTitle(hwnd) ?? string.Empty;
}
- private static string GetActiveWindowProcessName(IntPtr hwnd)
+ private string GetActiveWindowProcessName(IntPtr hwnd)
{
try
{
uint pid;
GetWindowThreadProcessId(hwnd, out pid);
- return System.Diagnostics.Process.GetProcessById((int) pid).ProcessName;
+ return System.Diagnostics.Process.GetProcessById((int)pid).ProcessName;
}
catch
{
@@ -103,7 +102,7 @@ namespace Artemis.Utilities
}
}
- private static string GetActiveWindowTitle(IntPtr hwnd)
+ private string GetActiveWindowTitle(IntPtr hwnd)
{
try
{
@@ -116,7 +115,7 @@ namespace Artemis.Utilities
}
}
- public static void Initialize()
+ public void Initialize()
{
try
{
@@ -124,21 +123,21 @@ namespace Artemis.Utilities
{
_activeWindowChangedDelegate = ActiveWindowChanged;
_activeWindowEventHook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND,
- IntPtr.Zero, _activeWindowChangedDelegate, 0, 0, WINEVENT_OUTOFCONTEXT);
+ IntPtr.Zero, _activeWindowChangedDelegate, 0, 0, WINEVENT_OUTOFCONTEXT);
}
if (_windowTitleEventHook == IntPtr.Zero)
{
_windowTitleChangedDelegate = WindowTitleChanged;
_windowTitleEventHook = SetWinEventHook(EVENT_OBJECT_NAMECHANGE, EVENT_OBJECT_NAMECHANGE,
- IntPtr.Zero, _windowTitleChangedDelegate, 0, 0, WINEVENT_OUTOFCONTEXT);
+ IntPtr.Zero, _windowTitleChangedDelegate, 0, 0, WINEVENT_OUTOFCONTEXT);
}
if (_windowMinimizedEventHook == IntPtr.Zero)
{
_windowMinimizedChangedDelegate = WindowMinimizedChanged;
_windowMinimizedEventHook = SetWinEventHook(EVENT_SYSTEM_MINIMIZEEND, EVENT_SYSTEM_MINIMIZEEND,
- IntPtr.Zero, _windowMinimizedChangedDelegate, 0, 0, WINEVENT_OUTOFCONTEXT);
+ IntPtr.Zero, _windowMinimizedChangedDelegate, 0, 0, WINEVENT_OUTOFCONTEXT);
}
}
catch
@@ -147,7 +146,7 @@ namespace Artemis.Utilities
}
}
- public static void Dispose()
+ public void Dispose()
{
try
{
@@ -180,4 +179,4 @@ namespace Artemis.Utilities
#endregion
}
-}
\ No newline at end of file
+}
diff --git a/Artemis/Artemis/Utilities/ActiveWindowDetection/IActiveWindowDetector.cs b/Artemis/Artemis/Utilities/ActiveWindowDetection/IActiveWindowDetector.cs
new file mode 100644
index 000000000..400ecf4ed
--- /dev/null
+++ b/Artemis/Artemis/Utilities/ActiveWindowDetection/IActiveWindowDetector.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Artemis.Utilities.ActiveWindowDetection
+{
+ public interface IActiveWindowDetector : IDisposable
+ {
+ string ActiveWindowProcessName { get; }
+ string ActiveWindowWindowTitle { get; }
+
+ void Initialize();
+ }
+}
diff --git a/Artemis/Artemis/Utilities/ActiveWindowDetection/TimerActiveWindowDetector.cs b/Artemis/Artemis/Utilities/ActiveWindowDetection/TimerActiveWindowDetector.cs
new file mode 100644
index 000000000..b865a859c
--- /dev/null
+++ b/Artemis/Artemis/Utilities/ActiveWindowDetection/TimerActiveWindowDetector.cs
@@ -0,0 +1,91 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Timers;
+
+namespace Artemis.Utilities.ActiveWindowDetection
+{
+ public class TimerActiveWindowDetector : IActiveWindowDetector
+ {
+ #region DLL-Imports
+
+ [DllImport("user32.dll")]
+ static extern IntPtr GetForegroundWindow();
+
+ [DllImport("user32.dll")]
+ private static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
+
+ [DllImport("user32.dll")]
+ private static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, out uint processId);
+
+ #endregion
+
+ #region Constants
+
+ private const int TIMER_INTERVAL = 1000;
+ private const int MAX_TITLE_LENGTH = 256;
+
+ #endregion
+
+ #region Properties & Fields
+
+ private Timer _timer;
+
+ public string ActiveWindowProcessName { get; private set; }
+ public string ActiveWindowWindowTitle { get; private set; }
+
+ #endregion
+
+ #region Methods
+
+ private void TimerOnElapsed(object sender, ElapsedEventArgs elapsedEventArgs)
+ {
+ IntPtr activeWindow = GetForegroundWindow();
+ ActiveWindowProcessName = GetActiveWindowProcessName(activeWindow);
+ ActiveWindowWindowTitle = GetActiveWindowTitle(activeWindow);
+ }
+
+ private string GetActiveWindowProcessName(IntPtr hwnd)
+ {
+ try
+ {
+ uint pid;
+ GetWindowThreadProcessId(hwnd, out pid);
+ return System.Diagnostics.Process.GetProcessById((int)pid).ProcessName;
+ }
+ catch
+ {
+ return null;
+ }
+ }
+
+ private string GetActiveWindowTitle(IntPtr hwnd)
+ {
+ try
+ {
+ StringBuilder buffer = new StringBuilder(MAX_TITLE_LENGTH);
+ return GetWindowText(hwnd, buffer, MAX_TITLE_LENGTH) > 0 ? buffer.ToString() : null;
+ }
+ catch
+ {
+ return null;
+ }
+ }
+
+ public void Initialize()
+ {
+ _timer = new Timer(TIMER_INTERVAL) { AutoReset = true };
+ _timer.Elapsed += TimerOnElapsed;
+ _timer.Start();
+ }
+
+ public void Dispose()
+ {
+ _timer?.Stop();
+ _timer?.Dispose();
+ _timer = null;
+ }
+
+ #endregion
+ }
+}
diff --git a/Artemis/Artemis/Utilities/DataReaders/DllManager.cs b/Artemis/Artemis/Utilities/DataReaders/DllManager.cs
index e1f1802a9..e31be1b13 100644
--- a/Artemis/Artemis/Utilities/DataReaders/DllManager.cs
+++ b/Artemis/Artemis/Utilities/DataReaders/DllManager.cs
@@ -37,8 +37,11 @@ namespace Artemis.Utilities.DataReaders
try
{
// Change the registry key to point to the fake DLL
- var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Classes\CLSID\{a6519e67-7632-4375-afdf-caa889744403}\ServerBinary", true);
- key?.SetValue(null, DllPath + @"\LogitechLed.dll");
+ // Key doesn't exist yet on systems without LGS installed
+ var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Classes\CLSID\{a6519e67-7632-4375-afdf-caa889744403}\ServerBinary", true) ??
+ Registry.LocalMachine.CreateSubKey(@"SOFTWARE\Classes\CLSID\{a6519e67-7632-4375-afdf-caa889744403}\ServerBinary", true);
+
+ key.SetValue(null, DllPath + @"\LogitechLed.dll");
// Make sure the fake DLL is in place
if (!Directory.Exists(DllPath))
diff --git a/Artemis/Artemis/Utilities/Updater.cs b/Artemis/Artemis/Utilities/Updater.cs
index 115919d14..5e863e721 100644
--- a/Artemis/Artemis/Utilities/Updater.cs
+++ b/Artemis/Artemis/Utilities/Updater.cs
@@ -148,6 +148,8 @@ namespace Artemis.Utilities
offsetSettings.RocketLeague = pointers.FirstOrDefault(p => p.Game == "RocketLeague");
if (pointers.FirstOrDefault(p => p.Game == "WorldOfWarcraft") != null)
offsetSettings.WorldOfWarcraft = pointers.FirstOrDefault(p => p.Game == "WorldOfWarcraft");
+ if (pointers.FirstOrDefault(p => p.Game == "Terraria") != null)
+ offsetSettings.Terraria = pointers.FirstOrDefault(p => p.Game == "Terraria");
offsetSettings.Save();
}
diff --git a/Artemis/Artemis/ViewModels/Flyouts/FlyoutSettingsViewModel.cs b/Artemis/Artemis/ViewModels/Flyouts/FlyoutSettingsViewModel.cs
index a6169b985..88394d44b 100644
--- a/Artemis/Artemis/ViewModels/Flyouts/FlyoutSettingsViewModel.cs
+++ b/Artemis/Artemis/ViewModels/Flyouts/FlyoutSettingsViewModel.cs
@@ -8,6 +8,7 @@ using Artemis.Events;
using Artemis.Managers;
using Artemis.Services;
using Artemis.Settings;
+using Artemis.Utilities.ActiveWindowDetection;
using Caliburn.Micro;
using MahApps.Metro.Controls;
using NLog;
@@ -37,6 +38,8 @@ namespace Artemis.ViewModels.Flyouts
LogLevels = new BindableCollection();
LogLevels.AddRange(LogLevel.AllLoggingLevels.Select(l => l.Name));
+ ActiveWindowDetections = new BindableCollection(Enum.GetValues(typeof(ActiveWindowDetectionType)).Cast());
+
PropertyChanged += KeyboardUpdater;
mainManager.EnabledChanged += MainManagerEnabledChanged;
mainManager.ModuleManager.EffectChanged += EffectManagerEffectChanged;
@@ -96,6 +99,7 @@ namespace Artemis.ViewModels.Flyouts
public string VersionText => "Artemis " + Assembly.GetExecutingAssembly().GetName().Version;
public BindableCollection LogLevels { get; set; }
+ public BindableCollection ActiveWindowDetections { get; set; }
public string SelectedTheme
{
@@ -130,6 +134,17 @@ namespace Artemis.ViewModels.Flyouts
}
}
+ public ActiveWindowDetectionType SelectedActiveWindowDetection
+ {
+ get { return GeneralSettings.ActiveWindowDetection; }
+ set
+ {
+ if (value == GeneralSettings.ActiveWindowDetection) return;
+ GeneralSettings.ActiveWindowDetection = value;
+ NotifyOfPropertyChange(() => SelectedActiveWindowDetection);
+ }
+ }
+
public string SelectedKeyboardProvider
{
get { return _selectedKeyboardProvider; }
diff --git a/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs b/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs
index 3f6ee7588..b0d3b1daf 100644
--- a/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs
+++ b/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs
@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
-using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -12,7 +11,6 @@ using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Media;
using Artemis.DAL;
-using Artemis.DeviceProviders;
using Artemis.Events;
using Artemis.Managers;
using Artemis.Models;
@@ -21,10 +19,12 @@ using Artemis.Profiles;
using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Models;
using Artemis.Profiles.Layers.Types.Folder;
+using Artemis.Profiles.Lua.Modules.Gui;
using Artemis.Properties;
using Artemis.Services;
using Artemis.Styles.DropTargetAdorners;
using Artemis.Utilities;
+using Artemis.Utilities.ActiveWindowDetection;
using Caliburn.Micro;
using Castle.Components.DictionaryAdapter;
using GongSolutions.Wpf.DragDrop;
@@ -46,21 +46,20 @@ namespace Artemis.ViewModels
{
public sealed class ProfileEditorViewModel : Screen, IDropTarget
{
+ private readonly KeybindModel _copyKeybind;
private readonly DeviceManager _deviceManager;
private readonly MetroDialogService _dialogService;
private readonly LoopManager _loopManager;
private readonly ModuleModel _moduleModel;
- private readonly KeybindModel _copyKeybind;
+ private readonly KeybindModel _pasteKeybind;
private ImageSource _keyboardPreview;
private ObservableCollection _layers;
- private readonly KeybindModel _pasteKeybind;
private ObservableCollection _profileNames;
private bool _saving;
private LayerModel _selectedLayer;
private bool _showAll;
- public ProfileEditorViewModel(ProfileEditorModel profileEditorModel, DeviceManager deviceManager,
- LoopManager loopManager, ModuleModel moduleModel, MetroDialogService dialogService)
+ public ProfileEditorViewModel(ProfileEditorModel profileEditorModel, DeviceManager deviceManager, LoopManager loopManager, LuaManager luaManager, ModuleModel moduleModel, MetroDialogService dialogService)
{
_deviceManager = deviceManager;
_loopManager = loopManager;
@@ -72,6 +71,7 @@ namespace Artemis.ViewModels
ProfileNames = new ObservableCollection();
Layers = new ObservableCollection();
ProfileEditorModel = profileEditorModel;
+ LuaManager = luaManager;
ShowAll = true;
PropertyChanged += EditorStateHandler;
@@ -102,6 +102,11 @@ namespace Artemis.ViewModels
#region LUA
+ public void ClickedLuaButton(EditorButton button)
+ {
+ button.Invoke();
+ }
+
public void EditLua()
{
if (SelectedProfile == null)
@@ -123,6 +128,7 @@ namespace Artemis.ViewModels
#region Properties
public ProfileEditorModel ProfileEditorModel { get; }
+ public LuaManager LuaManager { get; }
public ObservableCollection ProfileNames
{
@@ -198,7 +204,7 @@ namespace Artemis.ViewModels
NotifyOfPropertyChange(() => LayerSelected);
}
}
-
+
public ProfileModel SelectedProfile => _moduleModel?.ProfileModel;
public bool ProfileSelected => SelectedProfile != null;
public bool LayerSelected => SelectedProfile != null && SelectedLayer != null;
@@ -325,7 +331,7 @@ namespace Artemis.ViewModels
public void LayerToClipboard()
{
- if (SelectedLayer == null || !ActiveWindowHelper.MainWindowActive)
+ if (SelectedLayer == null || !ActiveWindowHelper.MainWindowActive || !IsActive)
return;
// Probably not how the cool kids do it but leveraging on JsonConvert gives flawless serialization
@@ -334,30 +340,35 @@ namespace Artemis.ViewModels
public void ClipboardToLayer()
{
- if (!ActiveWindowHelper.MainWindowActive)
+ if (!ActiveWindowHelper.MainWindowActive || !IsActive)
return;
- GeneralHelpers.ExecuteSta(() =>
+ try
{
- var data = (string) Clipboard.GetData("layer");
- if (data == null)
- return;
-
- var layerModel = JsonConvert.DeserializeObject(data);
- if (layerModel == null)
- return;
-
- if (SelectedLayer != null)
+ GeneralHelpers.ExecuteSta(() =>
{
- SelectedLayer.InsertAfter(layerModel);
- }
- else
- {
- SelectedProfile.Layers.Add(layerModel);
- SelectedProfile.FixOrder();
- }
- Execute.OnUIThread(() => UpdateLayerList(layerModel));
- });
+ var data = (string) Clipboard.GetData("layer");
+ if (data == null)
+ return;
+
+ var layerModel = JsonConvert.DeserializeObject(data);
+ if (layerModel == null)
+ return;
+
+ if (SelectedLayer != null)
+ SelectedLayer.InsertAfter(layerModel);
+ else
+ {
+ SelectedProfile.Layers.Add(layerModel);
+ SelectedProfile.FixOrder();
+ }
+ Execute.OnUIThread(() => UpdateLayerList(layerModel));
+ });
+ }
+ catch (Exception)
+ {
+ // ignored
+ }
}
private void UpdateLayerList(LayerModel selectModel)
@@ -405,6 +416,9 @@ namespace Artemis.ViewModels
if (_saving || SelectedProfile == null || _deviceManager.ChangingKeyboard)
return;
+ SelectedProfile.Width = _deviceManager.ActiveKeyboard.Width;
+ SelectedProfile.Height = _deviceManager.ActiveKeyboard.Height;
+
_saving = true;
try
{
@@ -421,8 +435,7 @@ namespace Artemis.ViewModels
{
if (_deviceManager.ActiveKeyboard == null)
{
- _dialogService.ShowMessageBox("Cannot add profile.",
- "To add a profile, please select a keyboard in the options menu first.");
+ _dialogService.ShowMessageBox("Cannot add profile.", "To add a profile, please select a keyboard in the options menu first.");
return;
}
@@ -666,7 +679,7 @@ namespace Artemis.ViewModels
return;
var pos = GetScaledPosition(e);
- var hoverLayer = GetLayers().Where(l => l.MustDraw()).FirstOrDefault(l => l.Properties.PropertiesRect(1).Contains(pos.X, pos.Y));
+ var hoverLayer = GetHoverLayer(pos.X, pos.Y);
if (hoverLayer != null)
SelectedLayer = hoverLayer;
@@ -682,7 +695,7 @@ namespace Artemis.ViewModels
return;
var pos = GetScaledPosition(e);
- var hoverLayer = GetLayers().Where(l => l.MustDraw()).FirstOrDefault(l => l.Properties.PropertiesRect(1).Contains(pos.X, pos.Y));
+ var hoverLayer = GetHoverLayer(pos.X, pos.Y);
HandleDragging(e, pos.X, pos.Y, hoverLayer);
@@ -701,11 +714,10 @@ namespace Artemis.ViewModels
: Cursors.SizeAll;
}
else
- {
KeyboardPreviewCursor = Cursors.Hand;
- }
}
+
private Point GetScaledPosition(MouseEventArgs e)
{
var previewSettings = _deviceManager.ActiveKeyboard.PreviewSettings;
@@ -716,16 +728,25 @@ namespace Artemis.ViewModels
var heightScale = sourceImage.ActualHeight / _deviceManager.ActiveKeyboard.PreviewSettings.BackgroundRectangle.Height;
// Remove the preview settings' offset from the cursor postion
- pos.X = pos.X - (previewSettings.OverlayRectangle.X * widthScale);
- pos.Y = pos.Y - (previewSettings.OverlayRectangle.Y * heightScale);
+ pos.X = pos.X - previewSettings.OverlayRectangle.X * widthScale;
+ pos.Y = pos.Y - previewSettings.OverlayRectangle.Y * heightScale;
// Scale the X and Y position down to match the keyboard's physical size and thus the layer positions
- pos.X = pos.X * (SelectedProfile.Width / (previewSettings.OverlayRectangle.Width*widthScale));
+ pos.X = pos.X * (SelectedProfile.Width / (previewSettings.OverlayRectangle.Width * widthScale));
pos.Y = pos.Y * (SelectedProfile.Height / (previewSettings.OverlayRectangle.Height * heightScale));
-
+
return pos;
}
+ private LayerModel GetHoverLayer(double x, double y)
+ {
+ // Prefer the selected layer as the hover layer even if it's underneath something else
+ if (SelectedLayer != null && SelectedLayer.Properties.PropertiesRect(1).Contains(x, y))
+ return SelectedLayer;
+
+ return GetLayers().Where(l => l.MustDraw()).FirstOrDefault(l => l.Properties.PropertiesRect(1).Contains(x, y));
+ }
+
public Cursor KeyboardPreviewCursor
{
get { return _keyboardPreviewCursor; }
diff --git a/Artemis/Artemis/Views/Flyouts/FlyoutSettingsView.xaml b/Artemis/Artemis/Views/Flyouts/FlyoutSettingsView.xaml
index 467284257..a7b50d2e0 100644
--- a/Artemis/Artemis/Views/Flyouts/FlyoutSettingsView.xaml
+++ b/Artemis/Artemis/Views/Flyouts/FlyoutSettingsView.xaml
@@ -6,7 +6,7 @@
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
xmlns:cal="http://www.caliburnproject.org"
mc:Ignorable="d"
- d:DesignHeight="600" d:DesignWidth="300">
+ d:DesignHeight="600" d:DesignWidth="310">
@@ -25,6 +25,7 @@
+
@@ -94,30 +95,36 @@
-
-
+
-
+
-
\ No newline at end of file
diff --git a/Artemis/LightFX2Artemis/LightFX2Artemis.vcxproj b/Artemis/LightFX2Artemis/LightFX2Artemis.vcxproj
index 69d2d3d31..bf7f37fc3 100644
--- a/Artemis/LightFX2Artemis/LightFX2Artemis.vcxproj
+++ b/Artemis/LightFX2Artemis/LightFX2Artemis.vcxproj
@@ -22,7 +22,7 @@
{1A349CF5-2008-41E8-AC13-874CBBCDFA0A}
Win32Proj
LightFX2Artemis
- 8.1
+ 10.0.14393.0
diff --git a/Artemis/LogiLed2Artemis/LogiLed2Artemis.vcxproj b/Artemis/LogiLed2Artemis/LogiLed2Artemis.vcxproj
index e41b51302..203df9c55 100644
--- a/Artemis/LogiLed2Artemis/LogiLed2Artemis.vcxproj
+++ b/Artemis/LogiLed2Artemis/LogiLed2Artemis.vcxproj
@@ -23,6 +23,7 @@
Win32Proj
LogiLed2Artemis
LogiLed2Artemis
+ 10.0.14393.0
diff --git a/Artemis/Razer2Artemis/Razer2Artemis.vcxproj b/Artemis/Razer2Artemis/Razer2Artemis.vcxproj
index 320fd6888..8669c2925 100644
--- a/Artemis/Razer2Artemis/Razer2Artemis.vcxproj
+++ b/Artemis/Razer2Artemis/Razer2Artemis.vcxproj
@@ -21,7 +21,7 @@
{39711909-C1D5-46CE-A9EA-2D561692EA47}
Razer2Artemis
- 8.1
+ 10.0.14393.0