1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-31 17:53:32 +00:00

Merge pull request #355 from SpoinkyNL/development

1.10.0.0
This commit is contained in:
Robert Beekman 2017-05-06 23:48:48 +02:00 committed by GitHub
commit 2edbf093a7
65 changed files with 1872 additions and 774 deletions

View File

@ -384,6 +384,13 @@
<DependentUpon>AssettoCorsaView.xaml</DependentUpon> <DependentUpon>AssettoCorsaView.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Modules\Games\AssettoCorsa\AssettoCorsaViewModel.cs" /> <Compile Include="Modules\Games\AssettoCorsa\AssettoCorsaViewModel.cs" />
<Compile Include="Modules\Games\Terraria\TerrariaDataModel.cs" />
<Compile Include="Modules\Games\Terraria\TerrariaSettings.cs" />
<Compile Include="Modules\Games\Terraria\TerrariaModel.cs" />
<Compile Include="Modules\Games\Terraria\TerrariaView.xaml.cs">
<DependentUpon>TerrariaView.xaml</DependentUpon>
</Compile>
<Compile Include="Modules\Games\Terraria\TerrariaViewModel.cs" />
<Compile Include="Modules\General\GeneralProfile\PerformanceInfo.cs" /> <Compile Include="Modules\General\GeneralProfile\PerformanceInfo.cs" />
<Compile Include="Modules\Games\EurotruckSimulator2\Data\Ets2TelemetryData.cs" /> <Compile Include="Modules\Games\EurotruckSimulator2\Data\Ets2TelemetryData.cs" />
<Compile Include="Modules\Games\EurotruckSimulator2\Data\Ets2TelemetryDataReader.cs" /> <Compile Include="Modules\Games\EurotruckSimulator2\Data\Ets2TelemetryDataReader.cs" />
@ -561,15 +568,27 @@
<Compile Include="Profiles\Lua\Modules\Events\LuaKeyPressEventArgs.cs" /> <Compile Include="Profiles\Lua\Modules\Events\LuaKeyPressEventArgs.cs" />
<Compile Include="Profiles\Lua\Modules\Events\LuaDeviceDrawingEventArgs.cs" /> <Compile Include="Profiles\Lua\Modules\Events\LuaDeviceDrawingEventArgs.cs" />
<Compile Include="Profiles\Lua\Modules\Events\LuaDeviceUpdatingEventArgs.cs" /> <Compile Include="Profiles\Lua\Modules\Events\LuaDeviceUpdatingEventArgs.cs" />
<Compile Include="Profiles\Lua\Modules\Gui\EditorButton.cs" />
<Compile Include="Profiles\Lua\Modules\Gui\LuaButton.cs" />
<Compile Include="Profiles\Lua\Modules\Gui\LuaCheckBox.cs" />
<Compile Include="Profiles\Lua\Modules\Gui\LuaComboBox.cs" />
<Compile Include="Profiles\Lua\Modules\Gui\LuaLabel.cs" />
<Compile Include="Profiles\Lua\Modules\Gui\LuaTextBox.cs" />
<Compile Include="Profiles\Lua\Modules\Gui\LuaWindowView.xaml.cs">
<DependentUpon>LuaWindowView.xaml</DependentUpon>
</Compile>
<Compile Include="Profiles\Lua\Modules\Gui\LuaWindowViewModel.cs" />
<Compile Include="Profiles\Lua\Modules\LuaEventsModule.cs" /> <Compile Include="Profiles\Lua\Modules\LuaEventsModule.cs" />
<Compile Include="Profiles\Lua\Modules\LuaBrushesModule.cs" /> <Compile Include="Profiles\Lua\Modules\LuaBrushesModule.cs" />
<Compile Include="Profiles\Lua\LuaModule.cs" /> <Compile Include="Profiles\Lua\LuaModule.cs" />
<Compile Include="Profiles\Lua\Modules\Brushes\LuaSolidColorBrush.cs" /> <Compile Include="Profiles\Lua\Modules\Brushes\LuaSolidColorBrush.cs" />
<Compile Include="Profiles\Lua\Modules\LuaGuiModule.cs" />
<Compile Include="Profiles\Lua\Modules\LuaKeybindModule.cs" /> <Compile Include="Profiles\Lua\Modules\LuaKeybindModule.cs" />
<Compile Include="Profiles\Lua\Modules\LuaKeyboardModule.cs" /> <Compile Include="Profiles\Lua\Modules\LuaKeyboardModule.cs" />
<Compile Include="Profiles\Lua\Modules\LuaLayerModule.cs" /> <Compile Include="Profiles\Lua\Modules\LuaLayerModule.cs" />
<Compile Include="Profiles\Lua\Modules\LuaMouseModule.cs" /> <Compile Include="Profiles\Lua\Modules\LuaMouseModule.cs" />
<Compile Include="Profiles\Lua\Modules\LuaProfileModule.cs" /> <Compile Include="Profiles\Lua\Modules\LuaProfileModule.cs" />
<Compile Include="Profiles\Lua\Modules\LuaStorageModule.cs" />
<Compile Include="Profiles\Lua\Modules\Timer\LuaTimer.cs" /> <Compile Include="Profiles\Lua\Modules\Timer\LuaTimer.cs" />
<Compile Include="Profiles\Lua\Modules\LuaTimerModule.cs" /> <Compile Include="Profiles\Lua\Modules\LuaTimerModule.cs" />
<Compile Include="Profiles\Lua\Wrappers\LuaDrawWrapper.cs" /> <Compile Include="Profiles\Lua\Wrappers\LuaDrawWrapper.cs" />
@ -645,6 +664,7 @@
<DesignTime>True</DesignTime> <DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon> <DependentUpon>Resources.resx</DependentUpon>
</Compile> </Compile>
<Compile Include="Services\CompatibilityService.cs" />
<Compile Include="Services\DialogService.cs" /> <Compile Include="Services\DialogService.cs" />
<Compile Include="Services\MetroDialogService.cs" /> <Compile Include="Services\MetroDialogService.cs" />
<Compile Include="Services\WindowService.cs" /> <Compile Include="Services\WindowService.cs" />
@ -653,7 +673,11 @@
<Compile Include="Settings\OffsetSettings.cs" /> <Compile Include="Settings\OffsetSettings.cs" />
<Compile Include="Styles\DropTargetAdorners\DropTargetMetroHighlightAdorner.cs" /> <Compile Include="Styles\DropTargetAdorners\DropTargetMetroHighlightAdorner.cs" />
<Compile Include="Styles\DropTargetAdorners\DropTargetMetroInsertionAdorner.cs" /> <Compile Include="Styles\DropTargetAdorners\DropTargetMetroInsertionAdorner.cs" />
<Compile Include="Utilities\ActiveWindowHelper.cs" /> <Compile Include="Utilities\ActiveWindowDetection\ActiveWindowDetectionType.cs" />
<Compile Include="Utilities\ActiveWindowDetection\ActiveWindowHelper.cs" />
<Compile Include="Utilities\ActiveWindowDetection\EventActiveWindowDetector.cs" />
<Compile Include="Utilities\ActiveWindowDetection\IActiveWindowDetector.cs" />
<Compile Include="Utilities\ActiveWindowDetection\TimerActiveWindowDetector.cs" />
<Compile Include="Utilities\ColorHelpers.cs" /> <Compile Include="Utilities\ColorHelpers.cs" />
<Compile Include="Utilities\Converters\JsonConverters.cs" /> <Compile Include="Utilities\Converters\JsonConverters.cs" />
<Compile Include="Utilities\Converters\NinjectCustomConverter.cs" /> <Compile Include="Utilities\Converters\NinjectCustomConverter.cs" />
@ -856,6 +880,10 @@
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
<Page Include="Modules\Games\Terraria\TerrariaView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Modules\General\Bubbles\BubblesView.xaml"> <Page Include="Modules\General\Bubbles\BubblesView.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
@ -924,6 +952,10 @@
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
<Page Include="Profiles\Lua\Modules\Gui\LuaWindowView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Resources\Icons.xaml"> <Page Include="Resources\Icons.xaml">
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>

View File

@ -8,8 +8,10 @@ using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
using Artemis.DAL; using Artemis.DAL;
using Artemis.InjectionModules; using Artemis.InjectionModules;
using Artemis.Services;
using Artemis.Settings; using Artemis.Settings;
using Artemis.Utilities; using Artemis.Utilities;
using Artemis.Utilities.ActiveWindowDetection;
using Artemis.Utilities.Converters; using Artemis.Utilities.Converters;
using Artemis.Utilities.DataReaders; using Artemis.Utilities.DataReaders;
using Artemis.ViewModels; using Artemis.ViewModels;
@ -31,10 +33,11 @@ namespace Artemis
Logging.SetupLogging(SettingsProvider.Load<GeneralSettings>().LogLevel); Logging.SetupLogging(SettingsProvider.Load<GeneralSettings>().LogLevel);
// Restore DDLs before interacting with any SDKs // Restore DDLs before interacting with any SDKs
DllManager.RestoreLogitechDll(); DllManager.RestoreLogitechDll();
// Check compatibility before trying to boot further
CompatibilityService.CheckRivaTuner();
Initialize(); Initialize();
BindSpecialValues(); BindSpecialValues();
InputHook.Start();
AppDomain.CurrentDomain.UnhandledException += CurrentDomainOnUnhandledException; 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 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 e.GetPosition(input).X;
// Return 0 if no processing could be done // 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."); logger.Info("Artemis was run using the autorun shortcut, sleeping for 15 sec.");
Thread.Sleep(15000); Thread.Sleep(15000);
} }
_kernel = new StandardKernel(new BaseModules(), new ManagerModules()); _kernel = new StandardKernel(new BaseModules(), new ManagerModules());
_kernel.Bind<IWindowManager>().To<WindowManager>().InSingletonScope(); _kernel.Bind<IWindowManager>().To<WindowManager>().InSingletonScope();
@ -113,7 +117,7 @@ namespace Artemis
//TODO DarthAffe 17.12.2016: Is this the right location for this? //TODO DarthAffe 17.12.2016: Is this the right location for this?
//TODO Move to Mainmanager and make disposable //TODO Move to Mainmanager and make disposable
ActiveWindowHelper.Initialize(); ActiveWindowHelper.SetActiveWindowDetectionType(SettingsProvider.Load<GeneralSettings>().ActiveWindowDetection);
} }
protected override void OnExit(object sender, EventArgs e) protected override void OnExit(object sender, EventArgs e)
@ -144,6 +148,7 @@ namespace Artemis
protected override void OnStartup(object sender, StartupEventArgs e) protected override void OnStartup(object sender, StartupEventArgs e)
{ {
DisplayRootViewFor<ShellViewModel>(); DisplayRootViewFor<ShellViewModel>();
InputHook.Start();
} }
} }
} }

View File

@ -134,7 +134,7 @@ namespace Artemis.DAL
return null; return null;
return prof; return prof;
} }
catch (JsonSerializationException) catch (JsonException)
{ {
return null; return null;
} }

View File

@ -1,4 +1,5 @@
using System.Drawing; using System;
using System.Drawing;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Windows; using System.Windows;
@ -67,6 +68,8 @@ namespace Artemis.DeviceProviders.CoolerMaster
for (var y = 0; y < Height; y++) for (var y = 0; y < Height; y++)
{ {
var c = b.GetPixel(x, 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); matrix.KeyColor[y, x] = new KEY_COLOR(c.R, c.G, c.B);
} }
} }

View File

@ -42,9 +42,16 @@ namespace Artemis.DeviceProviders.CoolerMaster
CmSdk.SetControlDevice(DEVICE_INDEX.DEV_MMouse_L); CmSdk.SetControlDevice(DEVICE_INDEX.DEV_MMouse_L);
// Doesn't seem reliable but better than nothing I suppose // Doesn't seem reliable but better than nothing I suppose
CanUse = CmSdk.IsDevicePlug(); try
if (CanUse) {
CmSdk.EnableLedControl(true); CanUse = CmSdk.IsDevicePlug();
if (CanUse)
CmSdk.EnableLedControl(true);
}
catch (Exception)
{
CanUse = false;
}
Logger.Debug("Attempted to enable Mastermouse Pro L. CanUse: {0}", CanUse); Logger.Debug("Attempted to enable Mastermouse Pro L. CanUse: {0}", CanUse);
return CanUse; return CanUse;

View File

@ -38,10 +38,17 @@ namespace Artemis.DeviceProviders.CoolerMaster
CmSdk.SetControlDevice(DEVICE_INDEX.DEV_MMouse_S); CmSdk.SetControlDevice(DEVICE_INDEX.DEV_MMouse_S);
// Doesn't seem reliable but better than nothing I suppose // Doesn't seem reliable but better than nothing I suppose
CanUse = CmSdk.IsDevicePlug(); try
if (CanUse) {
CmSdk.EnableLedControl(true); CanUse = CmSdk.IsDevicePlug();
if (CanUse)
CmSdk.EnableLedControl(true);
}
catch (Exception)
{
CanUse = false;
}
Logger.Debug("Attempted to enable Mastermouse Pro S. CanUse: {0}", CanUse); Logger.Debug("Attempted to enable Mastermouse Pro S. CanUse: {0}", CanUse);
return CanUse; return CanUse;
} }

View File

@ -81,10 +81,10 @@ namespace Artemis.DeviceProviders.Corsair
PreviewSettings = new PreviewSettings(new Rect(15, 30, 751, 284), Resources.k65); PreviewSettings = new PreviewSettings(new Rect(15, 30, 751, 284), Resources.k65);
break; break;
case "STRAFE RGB": case "STRAFE RGB":
Height = 7; Height = 8;
Width = 22; Width = 22;
Slug = "corsair-strafe-rgb"; 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; break;
} }
@ -114,29 +114,8 @@ namespace Artemis.DeviceProviders.Corsair
/// <param name="bitmap"></param> /// <param name="bitmap"></param>
public override void DrawBitmap(Bitmap bitmap) public override void DrawBitmap(Bitmap bitmap)
{ {
_keyboardBrush.Image = bitmap;
// For STRAFE, stretch the image on row 2. _keyboard.Update();
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();
}
} }
public override KeyMatch? GetKeyPosition(Keys keyCode) public override KeyMatch? GetKeyPosition(Keys keyCode)

View File

@ -14,8 +14,7 @@ namespace Artemis.DeviceProviders.Logitech
DllManager.RestoreLogitechDll(); DllManager.RestoreLogitechDll();
// Check to see if VC++ 2012 x64 is installed. // Check to see if VC++ 2012 x64 is installed.
if (Registry.LocalMachine.OpenSubKey( if (Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Classes\Installer\Dependencies\{ca67548a-5ebe-413a-b50c-4b9ceb6d66c6}") == null)
@"SOFTWARE\Classes\Installer\Dependencies\{ca67548a-5ebe-413a-b50c-4b9ceb6d66c6}") == null)
{ {
CantEnableText = "Couldn't connect to your Logitech keyboard.\n" + 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" + "The Visual C++ 2012 Redistributable v11.0.61030.0 could not be found, which is required.\n" +

View File

@ -37,8 +37,11 @@ namespace Artemis.DeviceProviders.Razer
return false; return false;
// Some people have Synapse installed, but not a Chroma keyboard, deal with this // 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 blackWidowFound = Chroma.Instance.Query(Devices.Blackwidow).Connected;
var blackWidowTeFound = Chroma.Instance.Query(Devices.BlackwidowTe).Connected; var blackWidowTeFound = Chroma.Instance.Query(Devices.BlackwidowTe).Connected;
Chroma.Instance.Uninitialize();
return blackWidowFound || blackWidowTeFound; return blackWidowFound || blackWidowTeFound;
} }

View File

@ -6,6 +6,7 @@ using Artemis.Profiles.Layers.Abstract;
using Artemis.Profiles.Layers.Interfaces; using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Types.Audio.AudioCapturing; using Artemis.Profiles.Layers.Types.Audio.AudioCapturing;
using Artemis.Profiles.Lua; using Artemis.Profiles.Lua;
using Artemis.Profiles.Lua.Modules.Gui;
using Artemis.Services; using Artemis.Services;
using Artemis.Utilities.DataReaders; using Artemis.Utilities.DataReaders;
using Artemis.Utilities.GameState; using Artemis.Utilities.GameState;
@ -116,6 +117,8 @@ namespace Artemis.InjectionModules
.InheritedFrom<LuaModule>() .InheritedFrom<LuaModule>()
.BindAllBaseClasses()); .BindAllBaseClasses());
Bind<LuaWindowViewModel>().ToSelf();
#endregion #endregion
} }
} }

View File

@ -1,10 +1,12 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using Artemis.DeviceProviders; using Artemis.DeviceProviders;
using Artemis.Profiles; using Artemis.Profiles;
using Artemis.Profiles.Lua; using Artemis.Profiles.Lua;
using Artemis.Profiles.Lua.Modules; using Artemis.Profiles.Lua.Modules;
using Artemis.Profiles.Lua.Modules.Gui;
using Castle.Core.Internal; using Castle.Core.Internal;
using MoonSharp.Interpreter; using MoonSharp.Interpreter;
using Ninject; using Ninject;
@ -17,7 +19,6 @@ namespace Artemis.Managers
private readonly DeviceManager _deviceManager; private readonly DeviceManager _deviceManager;
private readonly IKernel _kernel; private readonly IKernel _kernel;
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly Script _luaScript;
private List<LuaModule> _luaModules; private List<LuaModule> _luaModules;
public LuaManager(IKernel kernel, ILogger logger, DeviceManager deviceManager) public LuaManager(IKernel kernel, ILogger logger, DeviceManager deviceManager)
@ -25,13 +26,17 @@ namespace Artemis.Managers
_kernel = kernel; _kernel = kernel;
_logger = logger; _logger = logger;
_deviceManager = deviceManager; _deviceManager = deviceManager;
_luaScript = new Script(CoreModules.Preset_SoftSandbox);
EditorButtons = new ObservableCollection<EditorButton>();
LuaScript = new Script(CoreModules.Preset_SoftSandbox);
} }
public ProfileModel ProfileModel { get; private set; } public ProfileModel ProfileModel { get; private set; }
public KeyboardProvider KeyboardProvider { get; private set; } public KeyboardProvider KeyboardProvider { get; private set; }
public LuaProfileModule ProfileModule { get; private set; } public LuaProfileModule ProfileModule { get; private set; }
public LuaEventsModule EventsModule { get; private set; } public LuaEventsModule EventsModule { get; private set; }
public Script LuaScript { get; }
public ObservableCollection<EditorButton> EditorButtons { get; set; }
public void SetupLua(ProfileModel profileModel) public void SetupLua(ProfileModel profileModel)
{ {
@ -52,11 +57,11 @@ namespace Artemis.Managers
EventsModule = (LuaEventsModule) _luaModules.First(m => m.ModuleName == "Events"); EventsModule = (LuaEventsModule) _luaModules.First(m => m.ModuleName == "Events");
// Setup new state // Setup new state
_luaScript.Options.DebugPrint = LuaPrint; LuaScript.Options.DebugPrint = LuaPrint;
// Insert each module into the script's globals // Insert each module with a ModuleName into the script's globals
foreach (var luaModule in _luaModules) foreach (var luaModule in _luaModules.Where(m => m.ModuleName != null))
_luaScript.Globals[luaModule.ModuleName] = luaModule; LuaScript.Globals[luaModule.ModuleName] = luaModule;
// If there is no LUA script, don't bother executing the string // If there is no LUA script, don't bother executing the string
if (ProfileModel.LuaScript.IsNullOrEmpty()) if (ProfileModel.LuaScript.IsNullOrEmpty())
@ -66,9 +71,9 @@ namespace Artemis.Managers
{ {
lock (EventsModule.InvokeLock) lock (EventsModule.InvokeLock)
{ {
lock (_luaScript) lock (LuaScript)
{ {
_luaScript.DoString(ProfileModel.LuaScript); LuaScript.DoString(ProfileModel.LuaScript);
} }
} }
} }
@ -97,12 +102,12 @@ namespace Artemis.Managers
try try
{ {
_luaScript.Globals.Clear(); LuaScript.Globals.Clear();
_luaScript.Registry.Clear(); LuaScript.Registry.Clear();
_luaScript.Registry.RegisterConstants(); LuaScript.Registry.RegisterConstants();
_luaScript.Registry.RegisterCoreModules(CoreModules.Preset_SoftSandbox); LuaScript.Registry.RegisterCoreModules(CoreModules.Preset_SoftSandbox);
_luaScript.Globals.RegisterConstants(); LuaScript.Globals.RegisterConstants();
_luaScript.Globals.RegisterCoreModules(CoreModules.Preset_SoftSandbox); LuaScript.Globals.RegisterCoreModules(CoreModules.Preset_SoftSandbox);
} }
catch (NullReferenceException) catch (NullReferenceException)
{ {
@ -112,15 +117,15 @@ namespace Artemis.Managers
if (EventsModule != null) if (EventsModule != null)
lock (EventsModule.InvokeLock) lock (EventsModule.InvokeLock)
{ {
lock (_luaScript) lock (LuaScript)
{ {
_luaScript.DoString(""); LuaScript.DoString("");
} }
} }
else else
lock (_luaScript) lock (LuaScript)
{ {
_luaScript.DoString(""); LuaScript.DoString("");
} }
} }
@ -138,12 +143,12 @@ namespace Artemis.Managers
{ {
lock (EventsModule.InvokeLock) lock (EventsModule.InvokeLock)
{ {
lock (_luaScript) lock (LuaScript)
{ {
if (args != null) if (args != null)
_luaScript.Call(function, args); LuaScript.Call(function, args);
else else
_luaScript.Call(function); LuaScript.Call(function);
} }
} }
} }

View File

@ -108,6 +108,7 @@ namespace Artemis.Managers
public async void EnableProgram() public async void EnableProgram()
{ {
Logger.Debug("Enabling program"); Logger.Debug("Enabling program");
ProgramEnabled = true; ProgramEnabled = true;
await LoopManager.StartAsync(); await LoopManager.StartAsync();
@ -121,9 +122,12 @@ namespace Artemis.Managers
public void DisableProgram() public void DisableProgram()
{ {
Logger.Debug("Disabling program"); Logger.Debug("Disabling program");
foreach (var overlayModule in ModuleManager.OverlayModules) foreach (var overlayModule in ModuleManager.OverlayModules)
{
if (overlayModule.Settings.IsEnabled) if (overlayModule.Settings.IsEnabled)
overlayModule.Dispose(); overlayModule.Dispose();
}
LoopManager.Stop(); LoopManager.Stop();
ProgramEnabled = false; ProgramEnabled = false;
RaiseEnabledChangedEvent(new EnabledChangedEventArgs(ProgramEnabled)); RaiseEnabledChangedEvent(new EnabledChangedEventArgs(ProgramEnabled));
@ -178,4 +182,4 @@ namespace Artemis.Managers
handler?.Invoke(this, e); handler?.Invoke(this, e);
} }
} }
} }

View File

@ -5,6 +5,7 @@ using Artemis.DAL;
using Artemis.Modules.Abstract; using Artemis.Modules.Abstract;
using Artemis.Settings; using Artemis.Settings;
using Artemis.Utilities; using Artemis.Utilities;
using Artemis.Utilities.ActiveWindowDetection;
using Ninject.Extensions.Logging; using Ninject.Extensions.Logging;
namespace Artemis.Managers namespace Artemis.Managers

View File

@ -27,8 +27,7 @@ namespace Artemis.Models
private FileSystemWatcher _watcher; private FileSystemWatcher _watcher;
private ModuleModel _luaModule; private ModuleModel _luaModule;
public ProfileEditorModel(WindowService windowService, MetroDialogService dialogService, public ProfileEditorModel(WindowService windowService, MetroDialogService dialogService, DeviceManager deviceManager, LuaManager luaManager)
DeviceManager deviceManager, LuaManager luaManager)
{ {
_windowService = windowService; _windowService = windowService;
_dialogService = dialogService; _dialogService = dialogService;
@ -50,7 +49,7 @@ namespace Artemis.Models
new ConstructorArgument("dataModel", dataModel), new ConstructorArgument("dataModel", dataModel),
new ConstructorArgument("layer", layer) new ConstructorArgument("layer", layer)
}; };
_windowService.ShowDialog<LayerEditorViewModel>("Artemis | Edit layer", args); _windowService.ShowDialog<LayerEditorViewModel>("Artemis | Edit layer", null, args);
// If the layer was a folder, but isn't anymore, assign it's children to it's parent. // 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()) if (layer.LayerType is FolderType || !layer.Children.Any())
@ -345,7 +344,8 @@ namespace Artemis.Models
private void DisposeLuaWatcher() private void DisposeLuaWatcher()
{ {
if (_watcher == null) return; if (_watcher == null)
return;
_watcher.Changed -= LuaFileChanged; _watcher.Changed -= LuaFileChanged;
_watcher.Dispose(); _watcher.Dispose();
_watcher = null; _watcher = null;
@ -360,8 +360,6 @@ namespace Artemis.Models
#region Rendering #region Rendering
#endregion #endregion
} }
} }

View File

@ -22,7 +22,7 @@
<!-- Header --> <!-- Header -->
<Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" FontSize="20" HorizontalAlignment="Left"> <Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" FontSize="20" HorizontalAlignment="Left">
<Label.Content> <Label.Content>
<AccessText TextWrapping="Wrap" Text="By default shows RPM on the F-keys, gear on the other keys and track flags on the numpad." /> <AccessText TextWrapping="Wrap" Text="By default shows RPM on bottom half of the keyboard, engine stats on the top half and DRS on the numpad" />
</Label.Content> </Label.Content>
</Label> </Label>

View File

@ -29,7 +29,6 @@ namespace Artemis.Modules.Games.GtaV
public override void Enable() public override void Enable()
{ {
var process = System.Diagnostics.Process.GetProcessesByName("GTA5").First();
DllManager.PlaceLogitechDll(); DllManager.PlaceLogitechDll();
_pipeServer.PipeMessage += PipeServerOnPipeMessage; _pipeServer.PipeMessage += PipeServerOnPipeMessage;
base.Enable(); base.Enable();

View File

@ -36,7 +36,7 @@ namespace Artemis.Modules.Games.RocketLeague
{ {
if (!SettingsProvider.Load<GeneralSettings>().EnablePointersUpdate) if (!SettingsProvider.Load<GeneralSettings>().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; return;
} }

View File

@ -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; }
}
}

View File

@ -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<TerrariaSettings>();
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<GamePointer>
// {
// 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<OffsetSettings>().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));
}
}
}

View File

@ -0,0 +1,8 @@
using Artemis.Modules.Abstract;
namespace Artemis.Modules.Games.Terraria
{
public class TerrariaSettings : ModuleSettings
{
}
}

View File

@ -0,0 +1,48 @@
<UserControl x:Class="Artemis.Modules.Games.Terraria.TerrariaView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Artemis.Modules.Games.Terraria"
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
xmlns:cal="http://www.caliburnproject.org"
mc:Ignorable="d" d:DesignWidth="714.667" d:DesignHeight="384.667" >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<!-- Header -->
<Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" FontSize="20" HorizontalAlignment="Left">
<Label.Content>
<AccessText TextWrapping="Wrap" Text="By default does nothing! (default profiles coming soon)" />
</Label.Content>
</Label>
<!-- Sub header -->
<TextBlock x:Name="VersionText" Grid.Row="1" Grid.Column="0" VerticalAlignment="Bottom" TextWrapping="Wrap" HorizontalAlignment="Left" FontFamily="Segoe UI Semibold" TextAlignment="Justify" Margin="5,0,0,10" />
<!-- Enable -->
<StackPanel Grid.Row="1" Grid.Column="1" HorizontalAlignment="Right" Orientation="Horizontal">
<Label Content="Enable module" HorizontalAlignment="Right" Margin="0,0,0,3" />
<controls:ToggleSwitchButton IsChecked="{Binding Path=IsModuleEnabled, Mode=OneWay}" cal:Message.Attach="[Event Click] = [Action ToggleModule]"
Style="{StaticResource MahApps.Metro.Styles.ToggleSwitchButton.Win10}" ToolTip="Note: You can't enable an module when Artemis is disabled" />
</StackPanel>
<!-- Profile editor -->
<ContentControl Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" x:Name="ProfileEditor" />
<!-- Buttons -->
<StackPanel Grid.Column="0" Grid.Row="3" Orientation="Horizontal" VerticalAlignment="Bottom">
<Button x:Name="ResetSettings" Content="Reset effect" VerticalAlignment="Top" Width="100" Style="{DynamicResource SquareButtonStyle}" />
<Button x:Name="SaveSettings" Content="Save changes" VerticalAlignment="Top" Width="100" Margin="10,0,0,0" Style="{DynamicResource SquareButtonStyle}" />
</StackPanel>
</Grid>
</UserControl>

View File

@ -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
{
/// <summary>
/// Interaction logic for TerrariaView.xaml
/// </summary>
public partial class TerrariaView : UserControl
{
public TerrariaView()
{
InitializeComponent();
}
}
}

View File

@ -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<GeneralSettings>().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<OffsetSettings>().Terraria?.GameVersion;
VersionText = $"Requires patch {version}. When a new patch is released Artemis downloads new pointers for the latest version (unless disabled in settings).";
}
}
}

View File

@ -11,6 +11,7 @@ using Artemis.Events;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Modules.Abstract; using Artemis.Modules.Abstract;
using Artemis.Utilities; using Artemis.Utilities;
using Artemis.Utilities.ActiveWindowDetection;
using CSCore.CoreAudioAPI; using CSCore.CoreAudioAPI;
using Newtonsoft.Json; using Newtonsoft.Json;
using SpotifyAPI.Local; using SpotifyAPI.Local;

View File

@ -1,12 +1,6 @@
<UserControl x:Class="Artemis.Modules.General.GeneralProfile.GeneralProfileView" <UserControl x:Class="Artemis.Modules.General.GeneralProfile.GeneralProfileView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:cal="http://www.caliburnproject.org" xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls" mc:Ignorable="d" d:DesignHeight="476.986" d:DesignWidth="538.772">
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:cal="http://www.caliburnproject.org"
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
mc:Ignorable="d"
d:DesignHeight="476.986" d:DesignWidth="538.772">
<Grid> <Grid>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />

View File

@ -63,9 +63,15 @@ namespace Artemis.Profiles.Layers.Models
switch (ToggleType) switch (ToggleType)
{ {
case ToggleType.Enable: case ToggleType.Enable:
// Apply RenderAllowed only if this is the first keybind
if (index == 0)
layerModel.RenderAllowed = false;
action = () => layerModel.RenderAllowed = true; action = () => layerModel.RenderAllowed = true;
break; break;
case ToggleType.Disable: case ToggleType.Disable:
// Apply RenderAllowed only if this is the first keybind
if (index == 0)
layerModel.RenderAllowed = false;
action = () => layerModel.RenderAllowed = false; action = () => layerModel.RenderAllowed = false;
break; break;
case ToggleType.Toggle: case ToggleType.Toggle:

View File

@ -1,261 +1,261 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Windows; using System.Windows;
using System.Windows.Media; using System.Windows.Media;
using Artemis.Modules.Abstract; using Artemis.Modules.Abstract;
using Artemis.Profiles.Layers.Abstract; using Artemis.Profiles.Layers.Abstract;
using Artemis.Profiles.Layers.Animations; using Artemis.Profiles.Layers.Animations;
using Artemis.Profiles.Layers.Conditions; using Artemis.Profiles.Layers.Conditions;
using Artemis.Profiles.Layers.Interfaces; using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Types.Keyboard; using Artemis.Profiles.Layers.Types.Keyboard;
using Artemis.Utilities; using Artemis.Utilities;
using Artemis.Utilities.ParentChild; using Artemis.Utilities.ParentChild;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace Artemis.Profiles.Layers.Models namespace Artemis.Profiles.Layers.Models
{ {
public class LayerModel : IChildItem<LayerModel>, IChildItem<ProfileModel> public class LayerModel : IChildItem<LayerModel>, IChildItem<ProfileModel>
{ {
public LayerModel() public LayerModel()
{ {
Children = new ChildItemCollection<LayerModel, LayerModel>(this); Children = new ChildItemCollection<LayerModel, LayerModel>(this);
TweenModel = new TweenModel(this); TweenModel = new TweenModel(this);
RenderAllowed = true; RenderAllowed = true;
var model = Properties as KeyboardPropertiesModel; var model = Properties as KeyboardPropertiesModel;
if (model != null) if (model != null)
GifImage = new GifImage(model.GifFile, Properties.AnimationSpeed); GifImage = new GifImage(model.GifFile, Properties.AnimationSpeed);
} }
[JsonIgnore] [JsonIgnore]
public ImageSource LayerImage => LayerType.DrawThumbnail(this); public ImageSource LayerImage => LayerType.DrawThumbnail(this);
[JsonIgnore] [JsonIgnore]
public TweenModel TweenModel { get; set; } public TweenModel TweenModel { get; set; }
/// <summary> /// <summary>
/// Checks whether this layers conditions are met. /// Checks whether this layers conditions are met.
/// If they are met and this layer is an event, this also triggers that event. /// If they are met and this layer is an event, this also triggers that event.
/// </summary> /// </summary>
/// <param name="dataModel"></param> /// <param name="dataModel"></param>
/// <returns></returns> /// <returns></returns>
public bool AreConditionsMet(ModuleDataModel dataModel) public bool AreConditionsMet(ModuleDataModel dataModel)
{ {
// Conditions are not even checked if the layer isn't enabled // Conditions are not even checked if the layer isn't enabled
return Enabled && LayerCondition.ConditionsMet(this, dataModel); return Enabled && LayerCondition.ConditionsMet(this, dataModel);
} }
/// <summary> /// <summary>
/// Update the layer /// Update the layer
/// </summary> /// </summary>
/// <param name="dataModel"></param> /// <param name="dataModel"></param>
/// <param name="preview"></param> /// <param name="preview"></param>
/// <param name="updateAnimations"></param> /// <param name="updateAnimations"></param>
public void Update(ModuleDataModel dataModel, bool preview, bool updateAnimations) public void Update(ModuleDataModel dataModel, bool preview, bool updateAnimations)
{ {
if (LayerType == null) if (LayerType == null)
return; return;
LayerType.Update(this, dataModel, preview); LayerType.Update(this, dataModel, preview);
LayerAnimation?.Update(this, updateAnimations); LayerAnimation?.Update(this, updateAnimations);
if (!preview) if (!preview)
TweenModel.Update(); TweenModel.Update();
LastRender = DateTime.Now; LastRender = DateTime.Now;
} }
/// <summary> /// <summary>
/// Applies the saved properties to the current properties /// Applies the saved properties to the current properties
/// </summary> /// </summary>
/// <param name="advanced">Include advanced properties (opacity, brush)</param> /// <param name="advanced">Include advanced properties (opacity, brush)</param>
public void ApplyProperties(bool advanced) public void ApplyProperties(bool advanced)
{ {
X = Properties.X; X = Properties.X;
Y = Properties.Y; Y = Properties.Y;
Width = Properties.Width; Width = Properties.Width;
Height = Properties.Height; Height = Properties.Height;
if (!advanced) if (!advanced)
return; return;
Opacity = Properties.Opacity; Opacity = Properties.Opacity;
Brush = Properties.Brush; Brush = Properties.Brush;
} }
/// <summary> /// <summary>
/// Draw the layer using the provided context /// Draw the layer using the provided context
/// </summary> /// </summary>
/// <param name="dataModel"></param> /// <param name="dataModel"></param>
/// <param name="c"></param> /// <param name="c"></param>
/// <param name="preview"></param> /// <param name="preview"></param>
/// <param name="updateAnimations"></param> /// <param name="updateAnimations"></param>
public void Draw(ModuleDataModel dataModel, DrawingContext c, bool preview, bool updateAnimations) public void Draw(ModuleDataModel dataModel, DrawingContext c, bool preview, bool updateAnimations)
{ {
if (Brush == null || !preview && !RenderAllowed) if (Brush == null || !preview && !RenderAllowed)
return; return;
LayerType.Draw(this, c); LayerType.Draw(this, c);
} }
/// <summary> /// <summary>
/// Tells the current layer type to setup the layer's LayerProperties /// Tells the current layer type to setup the layer's LayerProperties
/// </summary> /// </summary>
public void SetupProperties() public void SetupProperties()
{ {
LayerType.SetupProperties(this); LayerType.SetupProperties(this);
// If the type is an event, set it up // If the type is an event, set it up
if (IsEvent && EventProperties == null) if (IsEvent && EventProperties == null)
EventProperties = new KeyboardEventPropertiesModel EventProperties = new KeyboardEventPropertiesModel
{ {
ExpirationType = ExpirationType.Time, ExpirationType = ExpirationType.Time,
Length = new TimeSpan(0, 0, 1), Length = new TimeSpan(0, 0, 1),
TriggerDelay = new TimeSpan(0) TriggerDelay = new TimeSpan(0)
}; };
} }
/// <summary> /// <summary>
/// Ensures all child layers have a unique order /// Ensures all child layers have a unique order
/// </summary> /// </summary>
public void FixOrder() public void FixOrder()
{ {
Children.Sort(l => l.Order); Children.Sort(l => l.Order);
for (var i = 0; i < Children.Count; i++) for (var i = 0; i < Children.Count; i++)
Children[i].Order = i; Children[i].Order = i;
} }
/// <summary> /// <summary>
/// Returns whether the layer meets the requirements to be drawn in the profile editor /// Returns whether the layer meets the requirements to be drawn in the profile editor
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public bool MustDraw() public bool MustDraw()
{ {
// If any of the parents are disabled, this layer must not be drawn // If any of the parents are disabled, this layer must not be drawn
var parent = Parent; var parent = Parent;
while (parent != null) while (parent != null)
{ {
if (!parent.Enabled) if (!parent.Enabled)
return false; return false;
parent = parent.Parent; parent = parent.Parent;
} }
return Enabled && LayerType.ShowInEdtor; return Enabled && LayerType.ShowInEdtor;
} }
/// <summary> /// <summary>
/// Returns every descendant of this layer /// Returns every descendant of this layer
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public IEnumerable<LayerModel> GetLayers() public IEnumerable<LayerModel> GetLayers()
{ {
var layers = new List<LayerModel>(); var layers = new List<LayerModel>();
foreach (var layerModel in Children.OrderBy(c => c.Order)) foreach (var layerModel in Children.OrderBy(c => c.Order))
{ {
layers.Add(layerModel); layers.Add(layerModel);
layers.AddRange(layerModel.GetLayers()); layers.AddRange(layerModel.GetLayers());
} }
return layers; return layers;
} }
/// <summary> /// <summary>
/// Creates a new Keyboard layer with default settings /// Creates a new Keyboard layer with default settings
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public static LayerModel CreateLayer() public static LayerModel CreateLayer()
{ {
return new LayerModel return new LayerModel
{ {
Name = "New layer", Name = "New layer",
Enabled = true, Enabled = true,
Order = -1, Order = -1,
LayerType = new KeyboardType(), LayerType = new KeyboardType(),
LayerCondition = new DataModelCondition(), LayerCondition = new DataModelCondition(),
LayerAnimation = new NoneAnimation(), LayerAnimation = new NoneAnimation(),
Properties = new KeyboardPropertiesModel Properties = new KeyboardPropertiesModel
{ {
Brush = new SolidColorBrush(ColorHelpers.GetRandomRainbowMediaColor()), Brush = new SolidColorBrush(ColorHelpers.GetRandomRainbowMediaColor()),
Height = 1, Height = 1,
Width = 1, Width = 1,
X = 0, X = 0,
Y = 0, Y = 0,
Opacity = 1, Opacity = 1,
HeightEaseTime = 0, HeightEaseTime = 0,
HeightEase = "Linear", HeightEase = "Linear",
WidthEaseTime = 0, WidthEaseTime = 0,
WidthEase = "Linear", WidthEase = "Linear",
OpacityEaseTime = 0, OpacityEaseTime = 0,
OpacityEase = "Linear" OpacityEase = "Linear"
} }
}; };
} }
/// <summary> /// <summary>
/// Insert this layer before the given layer /// Insert this layer before the given layer
/// </summary> /// </summary>
/// <param name="source"></param> /// <param name="source"></param>
public void InsertBefore(LayerModel source) public void InsertBefore(LayerModel source)
{ {
source.Order = Order; source.Order = Order;
Insert(source); Insert(source);
} }
/// <summary> /// <summary>
/// Insert this layer after the given layer /// Insert this layer after the given layer
/// </summary> /// </summary>
/// <param name="source"></param> /// <param name="source"></param>
public void InsertAfter(LayerModel source) public void InsertAfter(LayerModel source)
{ {
source.Order = Order + 1; source.Order = Order + 1;
Insert(source); Insert(source);
} }
/// <summary> /// <summary>
/// Insert the layer as a sibling /// Insert the layer as a sibling
/// </summary> /// </summary>
/// <param name="source"></param> /// <param name="source"></param>
private void Insert(LayerModel source) private void Insert(LayerModel source)
{ {
if (Parent != null) if (Parent != null)
{ {
foreach (var child in Parent.Children.OrderBy(c => c.Order)) foreach (var child in Parent.Children.OrderBy(c => c.Order))
if (child.Order >= source.Order) if (child.Order >= source.Order)
child.Order++; child.Order++;
Parent.Children.Add(source); Parent.Children.Add(source);
} }
else if (Profile != null) else if (Profile != null)
{ {
foreach (var layer in Profile.Layers.OrderBy(l => l.Order)) foreach (var layer in Profile.Layers.OrderBy(l => l.Order))
if (layer.Order >= source.Order) if (layer.Order >= source.Order)
layer.Order++; layer.Order++;
Profile.Layers.Add(source); Profile.Layers.Add(source);
} }
} }
public Rect LayerRect(int scale = 4) public Rect LayerRect(int scale = 4)
{ {
var width = Width; var width = Width;
var height = Height; var height = Height;
if (width < 0) if (width < 0)
width = 0; width = 0;
if (height < 0) if (height < 0)
height = 0; height = 0;
return new Rect(X * scale, Y * scale, width * scale, height * scale); return new Rect(X * scale, Y * scale, width * scale, height * scale);
} }
// TODO: Make this and ProfileModel's GetRenderLayers the same through inheritance // TODO: Make this and ProfileModel's GetRenderLayers the same through inheritance
/// <summary> /// <summary>
/// Generates a flat list containing all layers that must be rendered on the keyboard, /// 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 /// the first mouse layer to be rendered and the first headset layer to be rendered
/// </summary> /// </summary>
/// <param name="dataModel">Instance of said game data model</param> /// <param name="dataModel">Instance of said game data model</param>
/// <param name="keyboardOnly">Whether or not to ignore anything but keyboards</param> /// <param name="keyboardOnly">Whether or not to ignore anything but keyboards</param>
/// <param name="ignoreConditions"></param> /// <param name="ignoreConditions"></param>
/// <returns>A flat list containing all layers that must be rendered</returns> /// <returns>A flat list containing all layers that must be rendered</returns>
public List<LayerModel> GetRenderLayers(ModuleDataModel dataModel, bool keyboardOnly, bool ignoreConditions = false) public List<LayerModel> GetRenderLayers(ModuleDataModel dataModel, bool keyboardOnly, bool ignoreConditions = false)
{ {
var layers = new List<LayerModel>(); var layers = new List<LayerModel>();
foreach (var layerModel in Children.OrderByDescending(l => l.Order)) 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)); layers.AddRange(layerModel.GetRenderLayers(dataModel, keyboardOnly, ignoreConditions));
} }
return layers; return layers;
} }
public void SetupCondition() public void SetupCondition()
{ {
if (IsEvent && !(LayerCondition is EventCondition)) if (IsEvent && !(LayerCondition is EventCondition))
LayerCondition = new EventCondition(); LayerCondition = new EventCondition();
else if (!IsEvent && !(LayerCondition is DataModelCondition)) else if (!IsEvent && !(LayerCondition is DataModelCondition))
LayerCondition = new DataModelCondition(); LayerCondition = new DataModelCondition();
} }
public void SetupKeybinds() public void SetupKeybinds()
{ {
RenderAllowed = true; RenderAllowed = true;
// Clean up old keybinds // Clean up old keybinds
RemoveKeybinds(); RemoveKeybinds();
for (var index = 0; index < Properties.LayerKeybindModels.Count; index++) for (var index = 0; index < Properties.LayerKeybindModels.Count; index++)
{ {
var keybindModel = Properties.LayerKeybindModels[index]; var keybindModel = Properties.LayerKeybindModels[index];
keybindModel.Register(this, index); keybindModel.Register(this, index);
} }
} }
public void RemoveKeybinds() public void RemoveKeybinds()
{ {
foreach (var keybindModel in Properties.LayerKeybindModels) foreach (var keybindModel in Properties.LayerKeybindModels)
keybindModel.Unregister(); keybindModel.Unregister();
} }
#region Properties #region Properties
#region Layer type properties #region Layer type properties
public ILayerType LayerType { get; set; } public ILayerType LayerType { get; set; }
public ILayerCondition LayerCondition { get; set; } public ILayerCondition LayerCondition { get; set; }
public ILayerAnimation LayerAnimation { get; set; } public ILayerAnimation LayerAnimation { get; set; }
#endregion #endregion
#region Generic properties #region Generic properties
public string Name { get; set; } public string Name { get; set; }
public int Order { get; set; } public int Order { get; set; }
public bool Enabled { get; set; } public bool Enabled { get; set; }
public bool RenderAllowed { get; set; } public bool RenderAllowed { get; set; }
public bool Expanded { get; set; } public bool Expanded { get; set; }
public bool IsEvent { get; set; } public bool IsEvent { get; set; }
public LayerPropertiesModel Properties { get; set; } public LayerPropertiesModel Properties { get; set; }
public EventPropertiesModel EventProperties { get; set; } public EventPropertiesModel EventProperties { get; set; }
#endregion #endregion
#region Relational properties #region Relational properties
public ChildItemCollection<LayerModel, LayerModel> Children { get; } public ChildItemCollection<LayerModel, LayerModel> Children { get; }
[JsonIgnore] [JsonIgnore]
public LayerModel Parent { get; internal set; } public LayerModel Parent { get; internal set; }
[JsonIgnore] [JsonIgnore]
public ProfileModel Profile { get; internal set; } public ProfileModel Profile { get; internal set; }
#endregion #endregion
#region Render properties #region Render properties
[JsonIgnore] private Brush _brush; [JsonIgnore] private Brush _brush;
[JsonIgnore] [JsonIgnore]
public double X { get; set; } public double X { get; set; }
[JsonIgnore] [JsonIgnore]
public double Y { get; set; } public double Y { get; set; }
[JsonIgnore] [JsonIgnore]
public double Width { get; set; } public double Width { get; set; }
[JsonIgnore] [JsonIgnore]
public double Height { get; set; } public double Height { get; set; }
[JsonIgnore] [JsonIgnore]
public double Opacity { get; set; } public double Opacity { get; set; }
[JsonIgnore] [JsonIgnore]
public Brush Brush public Brush Brush
{ {
get { return _brush; } get { return _brush; }
set set
{ {
if (value == null) if (value == null)
{ {
_brush = null; _brush = null;
return; return;
} }
if (value.IsFrozen) if (value.IsFrozen)
{ {
_brush = value; _brush = value;
return; return;
} }
// Clone the brush off of the UI thread and freeze it // Clone the brush off of the UI thread and freeze it
var cloned = value.Dispatcher.Invoke(value.CloneCurrentValue); var cloned = value.Dispatcher.Invoke(value.CloneCurrentValue);
cloned.Freeze(); cloned.Freeze();
_brush = cloned; _brush = cloned;
} }
} }
[JsonIgnore] [JsonIgnore]
public double AnimationProgress { get; set; } public double AnimationProgress { get; set; }
[JsonIgnore] [JsonIgnore]
public GifImage GifImage { get; set; } public GifImage GifImage { get; set; }
[JsonIgnore] [JsonIgnore]
public DateTime LastRender { get; set; } public DateTime LastRender { get; set; }
#endregion #endregion
#endregion #endregion
#region IChildItem<Parent> Members #region IChildItem<Parent> Members
LayerModel IChildItem<LayerModel>.Parent LayerModel IChildItem<LayerModel>.Parent
{ {
get { return Parent; } get { return Parent; }
set { Parent = value; } set { Parent = value; }
} }
ProfileModel IChildItem<ProfileModel>.Parent ProfileModel IChildItem<ProfileModel>.Parent
{ {
get { return Profile; } get { return Profile; }
set { Profile = value; } set { Profile = value; }
} }
#endregion #endregion
/// <inheritdoc /> /// <inheritdoc />
public override string ToString() public override string ToString()
{ {
return $"{nameof(Name)}: {Name}, {nameof(Order)}: {Order}, {nameof(X)}: {X}, {nameof(Y)}: {Y}, {nameof(Width)}: {Width}, {nameof(Height)}: {Height}"; return $"{nameof(Name)}: {Name}, {nameof(Order)}: {Order}, {nameof(X)}: {X}, {nameof(Y)}: {Y}, {nameof(Width)}: {Width}, {nameof(Height)}: {Height}";
} }
} }
} }

View File

@ -1,95 +1,95 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Windows; using System.Windows;
using System.Windows.Media; using System.Windows.Media;
using Artemis.Utilities.Converters; using Artemis.Utilities.Converters;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace Artemis.Profiles.Layers.Models namespace Artemis.Profiles.Layers.Models
{ {
public abstract class LayerPropertiesModel public abstract class LayerPropertiesModel
{ {
private Brush _brush; private Brush _brush;
public LayerPropertiesModel(LayerPropertiesModel source = null) public LayerPropertiesModel(LayerPropertiesModel source = null)
{ {
if (source == null) if (source == null)
return; return;
// Clone the source's properties onto the new properties model (useful when changing property type) // Clone the source's properties onto the new properties model (useful when changing property type)
X = source.X; X = source.X;
Y = source.Y; Y = source.Y;
Width = source.Width; Width = source.Width;
Height = source.Height; Height = source.Height;
Contain = source.Contain; Contain = source.Contain;
Opacity = source.Opacity; Opacity = source.Opacity;
AnimationSpeed = source.AnimationSpeed; AnimationSpeed = source.AnimationSpeed;
Conditions = source.Conditions; Conditions = source.Conditions;
LayerKeybindModels = source.LayerKeybindModels; LayerKeybindModels = source.LayerKeybindModels;
ConditionType = source.ConditionType; ConditionType = source.ConditionType;
DynamicProperties = source.DynamicProperties; DynamicProperties = source.DynamicProperties;
Brush = source.Brush; Brush = source.Brush;
HeightEase = source.HeightEase; HeightEase = source.HeightEase;
WidthEase = source.WidthEase; WidthEase = source.WidthEase;
OpacityEase = source.OpacityEase; OpacityEase = source.OpacityEase;
HeightEaseTime = source.HeightEaseTime; HeightEaseTime = source.HeightEaseTime;
WidthEaseTime = source.WidthEaseTime; WidthEaseTime = source.WidthEaseTime;
OpacityEaseTime = source.OpacityEaseTime; OpacityEaseTime = source.OpacityEaseTime;
} }
public double X { get; set; } public double X { get; set; }
public double Y { get; set; } public double Y { get; set; }
public double Width { get; set; } public double Width { get; set; }
public double Height { get; set; } public double Height { get; set; }
public bool Contain { get; set; } public bool Contain { get; set; }
public double Opacity { get; set; } public double Opacity { get; set; }
public double AnimationSpeed { get; set; } public double AnimationSpeed { get; set; }
public double OpacityEaseTime { get; set; } public double OpacityEaseTime { get; set; }
public double HeightEaseTime { get; set; } public double HeightEaseTime { get; set; }
public double WidthEaseTime { get; set; } public double WidthEaseTime { get; set; }
public string WidthEase { set; get; } public string WidthEase { set; get; }
public string HeightEase { get; set; } public string HeightEase { get; set; }
public string OpacityEase { get; set; } public string OpacityEase { get; set; }
public ConditionType ConditionType { get; set; } public ConditionType ConditionType { get; set; }
public List<LayerConditionModel> Conditions { get; set; } = new List<LayerConditionModel>(); public List<LayerConditionModel> Conditions { get; set; } = new List<LayerConditionModel>();
public List<LayerKeybindModel> LayerKeybindModels { get; set; } = new List<LayerKeybindModel>(); public List<LayerKeybindModel> LayerKeybindModels { get; set; } = new List<LayerKeybindModel>();
public List<DynamicPropertiesModel> DynamicProperties { get; set; } = new List<DynamicPropertiesModel>(); public List<DynamicPropertiesModel> DynamicProperties { get; set; } = new List<DynamicPropertiesModel>();
[JsonConverter(typeof(BrushJsonConverter))] [JsonConverter(typeof(BrushJsonConverter))]
public Brush Brush public Brush Brush
{ {
get { return _brush; } get { return _brush; }
set set
{ {
if (value == null) if (value == null)
{ {
_brush = null; _brush = null;
return; return;
} }
if (value.IsFrozen) if (value.IsFrozen)
{ {
_brush = value; _brush = value;
return; return;
} }
// Clone the brush off of the UI thread and freeze it // Clone the brush off of the UI thread and freeze it
var cloned = value.Dispatcher.Invoke(value.CloneCurrentValue); var cloned = value.Dispatcher.Invoke(value.CloneCurrentValue);
cloned.Freeze(); cloned.Freeze();
_brush = cloned; _brush = cloned;
} }
} }
public Rect PropertiesRect(int scale = 4) public Rect PropertiesRect(int scale = 4)
{ {
return new Rect(X*scale, Y*scale, Width*scale, Height*scale); return new Rect(X*scale, Y*scale, Width*scale, Height*scale);
} }
} }
public enum ConditionType public enum ConditionType
{ {
[Description("All met")] AllMet, [Description("All met")] AllMet,
[Description("Any met")] AnyMet, [Description("Any met")] AnyMet,
[Description("None met")] NoneMet [Description("None met")] NoneMet
} }
} }

View File

@ -2,6 +2,7 @@
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Windows.Forms; using System.Windows.Forms;
using System.Windows.Media; using System.Windows.Media;
using Microsoft.Win32;
using SharpDX.Direct3D9; using SharpDX.Direct3D9;
namespace Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing namespace Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing
@ -15,6 +16,14 @@ namespace Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing
Width = Screen.PrimaryScreen.Bounds.Width; Width = Screen.PrimaryScreen.Bounds.Width;
Height = Screen.PrimaryScreen.Bounds.Height; 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) var presentParams = new PresentParameters(Width, Height)
{ {
Windowed = true, Windowed = true,
@ -24,7 +33,7 @@ namespace Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing
_device = new Device(new Direct3D(), 0, DeviceType.Hardware, IntPtr.Zero, _device = new Device(new Direct3D(), 0, DeviceType.Hardware, IntPtr.Zero,
CreateFlags.SoftwareVertexProcessing, presentParams); CreateFlags.SoftwareVertexProcessing, presentParams);
_surface = Surface.CreateOffscreenPlain(_device, Width, Height, Format.A8R8G8B8, Pool.Scratch); _surface = Surface.CreateOffscreenPlain(_device, Width, Height, Format.A8R8G8B8, Pool.Scratch);
_buffer = new byte[Width*Height*4]; _buffer = new byte[Width * Height * 4];
} }
#endregion #endregion
@ -43,6 +52,19 @@ namespace Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing
#region Methods #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() public byte[] CaptureScreen()
{ {
_device.GetFrontBufferData(0, _surface); _device.GetFrontBufferData(0, _surface);

View File

@ -97,18 +97,23 @@ namespace Artemis.Profiles.Layers.Types.Audio.AudioCapturing
} }
} }
private LineSpectrum _lineSpectrum;
public LineSpectrum GetLineSpectrum(int barCount, ScalingStrategy scalingStrategy) public LineSpectrum GetLineSpectrum(int barCount, ScalingStrategy scalingStrategy)
{ {
if (_spectrumProvider == null) if (_spectrumProvider == null || barCount <= 0)
return null; return null;
return new LineSpectrum(FftSize)
{ if (_lineSpectrum == null)
SpectrumProvider = _spectrumProvider, _lineSpectrum = new LineSpectrum(FftSize)
UseAverage = true, {
BarCount = barCount, SpectrumProvider = _spectrumProvider,
IsXLogScale = true, UseAverage = true,
ScalingStrategy = scalingStrategy BarCount = barCount,
}; IsXLogScale = true,
ScalingStrategy = scalingStrategy
};
return _lineSpectrum;
} }
/// <summary> /// <summary>
@ -148,13 +153,13 @@ namespace Artemis.Profiles.Layers.Types.Audio.AudioCapturing
if (Type == MmDeviceType.Input) if (Type == MmDeviceType.Input)
{ {
_soundIn = Device != null _soundIn = Device != null
? new WasapiCapture {Device = Device} ? new WasapiCapture { Device = Device }
: new WasapiCapture(); : new WasapiCapture();
} }
else else
{ {
_soundIn = Device != null _soundIn = Device != null
? new WasapiLoopbackCapture {Device = Device} ? new WasapiLoopbackCapture { Device = Device }
: new WasapiLoopbackCapture(); : new WasapiLoopbackCapture();
} }
@ -182,6 +187,7 @@ namespace Artemis.Profiles.Layers.Types.Audio.AudioCapturing
} }
}; };
_lineSpectrum = null;
_singleSpectrum = new SingleSpectrum(FftSize, _spectrumProvider); _singleSpectrum = new SingleSpectrum(FftSize, _spectrumProvider);
_mayStop = false; _mayStop = false;

View File

@ -1,4 +1,5 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Windows; using System.Windows;
using System.Windows.Media; using System.Windows.Media;
@ -26,6 +27,7 @@ namespace Artemis.Profiles.Layers.Types.Audio
private List<double> _lineValues; private List<double> _lineValues;
private AudioPropertiesModel _properties; private AudioPropertiesModel _properties;
private bool _subscribed; private bool _subscribed;
private DateTime _lastRender;
public AudioType(AudioCaptureManager audioCaptureManager) public AudioType(AudioCaptureManager audioCaptureManager)
{ {
@ -123,8 +125,7 @@ namespace Artemis.Profiles.Layers.Types.Audio
SubscribeToAudioChange(); SubscribeToAudioChange();
if (_audioCapture == null || newProperties.Device != _properties.Device || if (_audioCapture == null || newProperties.Device != _properties.Device || newProperties.DeviceType != _properties.DeviceType)
newProperties.DeviceType != _properties.DeviceType)
{ {
var device = GetMmDevice(); var device = GetMmDevice();
if (device != null) if (device != null)
@ -153,17 +154,19 @@ namespace Artemis.Profiles.Layers.Types.Audio
currentHeight = layerModel.Width; 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; _lines = currentLines;
_lineSpectrum = _audioCapture.GetLineSpectrum(_lines, ScalingStrategy.Decibel); _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) if (newLineValues != null)
{
_lineValues = newLineValues; _lineValues = newLineValues;
_lastRender = DateTime.Now;
}
} }
public void SetupProperties(LayerModel layerModel) public void SetupProperties(LayerModel layerModel)

View File

@ -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; }
}
}

View File

@ -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<EventArgs> Click;
protected virtual void OnClick(LuaButton button)
{
Click?.Invoke(button, null);
}
}
}

View File

@ -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<EventArgs> Click;
protected virtual void OnClick(LuaCheckBox checkBox)
{
Click?.Invoke(checkBox, null);
}
}
}

View File

@ -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<string> values, double x, double y, double? width, double? height)
{
_luaManager = luaManager;
ComboBox = new ComboBox {ItemsSource = new ObservableCollection<string>(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<string>) ComboBox.ItemsSource;
collection.Clear();
foreach (var value in values)
collection.Add(value);
}
public void AddValue(string value)
{
((ObservableCollection<string>) ComboBox.ItemsSource).Add(value);
}
public void RemoveValue(string value)
{
var collection = (ObservableCollection<string>) 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<EventArgs> SelectionChanged;
protected virtual void OnSelectionChanged(LuaComboBox comboBox)
{
SelectionChanged?.Invoke(comboBox, null);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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<EventArgs> TextChanged;
protected virtual void OnTextChanged(LuaTextBox button)
{
TextChanged?.Invoke(button, null);
}
}
}

View File

@ -0,0 +1,8 @@
<controls:MetroWindow x:Class="Artemis.Profiles.Lua.Modules.Gui.LuaWindowView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Artemis.Profiles.Lua.Modules.Gui"
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls" mc:Ignorable="d" Title="LuaWindowView" Height="300" Width="300" WindowStartupLocation="CenterScreen"
GlowBrush="{DynamicResource AccentColorBrush}">
<Grid>
<ItemsControl ItemsSource="{Binding Path=Content}" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto" />
</Grid>
</controls:MetroWindow>

View File

@ -0,0 +1,15 @@
using MahApps.Metro.Controls;
namespace Artemis.Profiles.Lua.Modules.Gui
{
/// <summary>
/// Interaction logic for LuaWindowView.xaml
/// </summary>
public partial class LuaWindowView : MetroWindow
{
public LuaWindowView()
{
InitializeComponent();
}
}
}

View File

@ -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<UIElement> {Canvas};
}
public Canvas Canvas { get; set; }
public List<UIElement> 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<string> 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);
}
}
}

View File

@ -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) lock (InvokeLock)
{ {

View File

@ -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<LuaWindowViewModel> _windows;
public LuaGuiModule(LuaManager luaManager, WindowService windowService) : base(luaManager)
{
_windowService = windowService;
_windows = new List<LuaWindowViewModel>();
}
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<LuaWindowViewModel>("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());
}
}
}

View File

@ -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<LuaGlobalSettings>();
// 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();
}
}
}

View File

@ -38,6 +38,7 @@ namespace Artemis.Profiles
public int Width { get; set; } public int Width { get; set; }
public int Height { get; set; } public int Height { get; set; }
public string LuaScript { get; set; } public string LuaScript { get; set; }
public string LuaStorage { get; set; }
[JsonIgnore] [JsonIgnore]
public string Slug => new string(Name.Where(ch => !_invalidFileNameChars.Contains(ch)).ToArray()); public string Slug => new string(Name.Where(ch => !_invalidFileNameChars.Contains(ch)).ToArray());

View File

@ -53,7 +53,7 @@ using System.Windows;
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.9.0.0")] [assembly: AssemblyVersion("1.10.0.0")]
[assembly: AssemblyFileVersion("1.9.0.0")] [assembly: AssemblyFileVersion("1.10.0.0")]
[assembly: InternalsVisibleTo("Artemis.Explorables")] [assembly: InternalsVisibleTo("Artemis.Explorables")]

View File

@ -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.");
}
}
}

View File

@ -1,39 +1,41 @@
using System.Dynamic; using System.Dynamic;
using Caliburn.Micro; using Caliburn.Micro;
using Ninject; using Ninject;
using Ninject.Parameters; using Ninject.Parameters;
namespace Artemis.Services namespace Artemis.Services
{ {
public class WindowService public class WindowService
{ {
private readonly IKernel _kernel; private readonly IKernel _kernel;
public WindowService(IKernel kernel) public WindowService(IKernel kernel)
{ {
_kernel = kernel; _kernel = kernel;
} }
public T ShowWindow<T>(string windowName, params IParameter[] param) where T : class public T ShowWindow<T>(string windowName, dynamic settings = null, params IParameter[] param) where T : class
{ {
var windowManager = new WindowManager(); var windowManager = new WindowManager();
var viewModel = _kernel.Get<T>(param); var viewModel = _kernel.Get<T>(param);
dynamic settings = new ExpandoObject(); if (settings == null)
settings.Title = windowName; settings = new ExpandoObject();
windowManager.ShowWindow(viewModel, null, settings); settings.Title = windowName;
return viewModel; windowManager.ShowWindow(viewModel, null, settings);
} return viewModel;
}
public T ShowDialog<T>(string dialogName, params IParameter[] param) where T : class
{ public T ShowDialog<T>(string dialogName, dynamic settings = null, params IParameter[] param) where T : class
var windowManager = new WindowManager(); {
var viewModel = _kernel.Get<T>(param); var windowManager = new WindowManager();
var viewModel = _kernel.Get<T>(param);
dynamic settings = new ExpandoObject();
settings.Title = dialogName; if (settings == null)
windowManager.ShowDialog(viewModel, null, settings); settings = new ExpandoObject();
return viewModel; settings.Title = dialogName;
} windowManager.ShowDialog(viewModel, null, settings);
} return viewModel;
}
}
} }

View File

@ -5,9 +5,11 @@ using System.Windows;
using Artemis.DAL; using Artemis.DAL;
using Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing; using Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing;
using Artemis.Utilities; using Artemis.Utilities;
using Artemis.Utilities.ActiveWindowDetection;
using Caliburn.Micro; using Caliburn.Micro;
using MahApps.Metro; using MahApps.Metro;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Squirrel; using Squirrel;
namespace Artemis.Settings namespace Artemis.Settings
@ -68,6 +70,11 @@ namespace Artemis.Settings
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)] [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
public string LogLevel { get; set; } 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 Version LastRanVersion { get; set; }
public void Save() public void Save()
@ -75,6 +82,7 @@ namespace Artemis.Settings
SettingsProvider.Save(this); SettingsProvider.Save(this);
Logging.SetupLogging(LogLevel); Logging.SetupLogging(LogLevel);
ActiveWindowHelper.SetActiveWindowDetectionType(ActiveWindowDetection);
ApplyAutorun(); ApplyAutorun();
ApplyTheme(); ApplyTheme();
ApplyGamestatePort(); ApplyGamestatePort();

View File

@ -8,6 +8,7 @@ namespace Artemis.Settings
{ {
public GamePointersCollection RocketLeague { get; set; } public GamePointersCollection RocketLeague { get; set; }
public GamePointersCollection WorldOfWarcraft { get; set; } public GamePointersCollection WorldOfWarcraft { get; set; }
public GamePointersCollection Terraria { get; set; }
public void Save() public void Save()
{ {

View File

@ -210,7 +210,7 @@
ItemsSource="{Binding AvailableBrushTypes, RelativeSource={RelativeSource TemplatedParent}}" HorizontalAlignment="Center"> ItemsSource="{Binding AvailableBrushTypes, RelativeSource={RelativeSource TemplatedParent}}" HorizontalAlignment="Center">
<ListBox.ItemsPanel> <ListBox.ItemsPanel>
<ItemsPanelTemplate> <ItemsPanelTemplate>
<UniformGrid Rows="1" Columns="4" /> <UniformGrid Rows="1" />
</ItemsPanelTemplate> </ItemsPanelTemplate>
</ListBox.ItemsPanel> </ListBox.ItemsPanel>
<ListBox.ItemContainerStyle> <ListBox.ItemContainerStyle>

View File

@ -0,0 +1,9 @@
namespace Artemis.Utilities.ActiveWindowDetection
{
public enum ActiveWindowDetectionType
{
Disabled = -1,
Events = 0,
Timer = 1,
}
}

View File

@ -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
}
}

View File

@ -2,9 +2,9 @@
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
namespace Artemis.Utilities namespace Artemis.Utilities.ActiveWindowDetection
{ {
public static class ActiveWindowHelper public class EventActiveWindowDetector : IActiveWindowDetector
{ {
#region DLL-Imports #region DLL-Imports
@ -14,7 +14,7 @@ namespace Artemis.Utilities
[DllImport("user32.dll")] [DllImport("user32.dll")]
private static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc, 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")] [DllImport("user32.dll")]
private static extern bool UnhookWinEvent(IntPtr hWinEventHook); private static extern bool UnhookWinEvent(IntPtr hWinEventHook);
@ -41,47 +41,46 @@ namespace Artemis.Utilities
#region Properties & Fields #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. // 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 WinEventDelegate _activeWindowChangedDelegate;
private static IntPtr _activeWindowEventHook; private IntPtr _activeWindowEventHook;
private static WinEventDelegate _windowTitleChangedDelegate; private WinEventDelegate _windowTitleChangedDelegate;
private static IntPtr _windowTitleEventHook; private IntPtr _windowTitleEventHook;
private static WinEventDelegate _windowMinimizedChangedDelegate; private WinEventDelegate _windowMinimizedChangedDelegate;
private static IntPtr _windowMinimizedEventHook; private IntPtr _windowMinimizedEventHook;
private static IntPtr _activeWindow; private IntPtr _activeWindow;
public static string ActiveWindowProcessName { get; private set; } = string.Empty; public string ActiveWindowProcessName { get; private set; } = string.Empty;
public static string ActiveWindowWindowTitle { get; private set; } = string.Empty; public string ActiveWindowWindowTitle { get; private set; } = string.Empty;
public static bool MainWindowActive => ActiveWindowProcessName.Contains("Artemis");
#endregion #endregion
#region Methods #region Methods
private static void ActiveWindowChanged(IntPtr hWinEventHook, uint eventType, private void ActiveWindowChanged(IntPtr hWinEventHook, uint eventType,
IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime) IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{ {
UpdateForWindow(hwnd); UpdateForWindow(hwnd);
} }
private static void WindowTitleChanged(IntPtr hWinEventHook, uint eventType, private void WindowTitleChanged(IntPtr hWinEventHook, uint eventType,
IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime) IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{ {
if (_activeWindow == hwnd) if (_activeWindow == hwnd)
UpdateForWindow(hwnd); UpdateForWindow(hwnd);
} }
private static void WindowMinimizedChanged(IntPtr hWinEventHook, uint eventType, private void WindowMinimizedChanged(IntPtr hWinEventHook, uint eventType,
IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime) 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: 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. // 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); UpdateForWindow(hwnd);
} }
private static void UpdateForWindow(IntPtr hwnd) private void UpdateForWindow(IntPtr hwnd)
{ {
_activeWindow = hwnd; _activeWindow = hwnd;
@ -89,13 +88,13 @@ namespace Artemis.Utilities
ActiveWindowWindowTitle = GetActiveWindowTitle(hwnd) ?? string.Empty; ActiveWindowWindowTitle = GetActiveWindowTitle(hwnd) ?? string.Empty;
} }
private static string GetActiveWindowProcessName(IntPtr hwnd) private string GetActiveWindowProcessName(IntPtr hwnd)
{ {
try try
{ {
uint pid; uint pid;
GetWindowThreadProcessId(hwnd, out pid); GetWindowThreadProcessId(hwnd, out pid);
return System.Diagnostics.Process.GetProcessById((int) pid).ProcessName; return System.Diagnostics.Process.GetProcessById((int)pid).ProcessName;
} }
catch catch
{ {
@ -103,7 +102,7 @@ namespace Artemis.Utilities
} }
} }
private static string GetActiveWindowTitle(IntPtr hwnd) private string GetActiveWindowTitle(IntPtr hwnd)
{ {
try try
{ {
@ -116,7 +115,7 @@ namespace Artemis.Utilities
} }
} }
public static void Initialize() public void Initialize()
{ {
try try
{ {
@ -124,21 +123,21 @@ namespace Artemis.Utilities
{ {
_activeWindowChangedDelegate = ActiveWindowChanged; _activeWindowChangedDelegate = ActiveWindowChanged;
_activeWindowEventHook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, _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) if (_windowTitleEventHook == IntPtr.Zero)
{ {
_windowTitleChangedDelegate = WindowTitleChanged; _windowTitleChangedDelegate = WindowTitleChanged;
_windowTitleEventHook = SetWinEventHook(EVENT_OBJECT_NAMECHANGE, EVENT_OBJECT_NAMECHANGE, _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) if (_windowMinimizedEventHook == IntPtr.Zero)
{ {
_windowMinimizedChangedDelegate = WindowMinimizedChanged; _windowMinimizedChangedDelegate = WindowMinimizedChanged;
_windowMinimizedEventHook = SetWinEventHook(EVENT_SYSTEM_MINIMIZEEND, EVENT_SYSTEM_MINIMIZEEND, _windowMinimizedEventHook = SetWinEventHook(EVENT_SYSTEM_MINIMIZEEND, EVENT_SYSTEM_MINIMIZEEND,
IntPtr.Zero, _windowMinimizedChangedDelegate, 0, 0, WINEVENT_OUTOFCONTEXT); IntPtr.Zero, _windowMinimizedChangedDelegate, 0, 0, WINEVENT_OUTOFCONTEXT);
} }
} }
catch catch
@ -147,7 +146,7 @@ namespace Artemis.Utilities
} }
} }
public static void Dispose() public void Dispose()
{ {
try try
{ {
@ -180,4 +179,4 @@ namespace Artemis.Utilities
#endregion #endregion
} }
} }

View File

@ -0,0 +1,12 @@
using System;
namespace Artemis.Utilities.ActiveWindowDetection
{
public interface IActiveWindowDetector : IDisposable
{
string ActiveWindowProcessName { get; }
string ActiveWindowWindowTitle { get; }
void Initialize();
}
}

View File

@ -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
}
}

View File

@ -37,8 +37,11 @@ namespace Artemis.Utilities.DataReaders
try try
{ {
// Change the registry key to point to the fake DLL // 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 doesn't exist yet on systems without LGS installed
key?.SetValue(null, DllPath + @"\LogitechLed.dll"); 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 // Make sure the fake DLL is in place
if (!Directory.Exists(DllPath)) if (!Directory.Exists(DllPath))

View File

@ -148,6 +148,8 @@ namespace Artemis.Utilities
offsetSettings.RocketLeague = pointers.FirstOrDefault(p => p.Game == "RocketLeague"); offsetSettings.RocketLeague = pointers.FirstOrDefault(p => p.Game == "RocketLeague");
if (pointers.FirstOrDefault(p => p.Game == "WorldOfWarcraft") != null) if (pointers.FirstOrDefault(p => p.Game == "WorldOfWarcraft") != null)
offsetSettings.WorldOfWarcraft = pointers.FirstOrDefault(p => p.Game == "WorldOfWarcraft"); 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(); offsetSettings.Save();
} }

View File

@ -8,6 +8,7 @@ using Artemis.Events;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Services; using Artemis.Services;
using Artemis.Settings; using Artemis.Settings;
using Artemis.Utilities.ActiveWindowDetection;
using Caliburn.Micro; using Caliburn.Micro;
using MahApps.Metro.Controls; using MahApps.Metro.Controls;
using NLog; using NLog;
@ -37,6 +38,8 @@ namespace Artemis.ViewModels.Flyouts
LogLevels = new BindableCollection<string>(); LogLevels = new BindableCollection<string>();
LogLevels.AddRange(LogLevel.AllLoggingLevels.Select(l => l.Name)); LogLevels.AddRange(LogLevel.AllLoggingLevels.Select(l => l.Name));
ActiveWindowDetections = new BindableCollection<ActiveWindowDetectionType>(Enum.GetValues(typeof(ActiveWindowDetectionType)).Cast<ActiveWindowDetectionType>());
PropertyChanged += KeyboardUpdater; PropertyChanged += KeyboardUpdater;
mainManager.EnabledChanged += MainManagerEnabledChanged; mainManager.EnabledChanged += MainManagerEnabledChanged;
mainManager.ModuleManager.EffectChanged += EffectManagerEffectChanged; mainManager.ModuleManager.EffectChanged += EffectManagerEffectChanged;
@ -96,6 +99,7 @@ namespace Artemis.ViewModels.Flyouts
public string VersionText => "Artemis " + Assembly.GetExecutingAssembly().GetName().Version; public string VersionText => "Artemis " + Assembly.GetExecutingAssembly().GetName().Version;
public BindableCollection<string> LogLevels { get; set; } public BindableCollection<string> LogLevels { get; set; }
public BindableCollection<ActiveWindowDetectionType> ActiveWindowDetections { get; set; }
public string SelectedTheme 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 public string SelectedKeyboardProvider
{ {
get { return _selectedKeyboardProvider; } get { return _selectedKeyboardProvider; }

View File

@ -2,7 +2,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -12,7 +11,6 @@ using System.Windows.Forms;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using Artemis.DAL; using Artemis.DAL;
using Artemis.DeviceProviders;
using Artemis.Events; using Artemis.Events;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models; using Artemis.Models;
@ -21,10 +19,12 @@ using Artemis.Profiles;
using Artemis.Profiles.Layers.Interfaces; using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Models; using Artemis.Profiles.Layers.Models;
using Artemis.Profiles.Layers.Types.Folder; using Artemis.Profiles.Layers.Types.Folder;
using Artemis.Profiles.Lua.Modules.Gui;
using Artemis.Properties; using Artemis.Properties;
using Artemis.Services; using Artemis.Services;
using Artemis.Styles.DropTargetAdorners; using Artemis.Styles.DropTargetAdorners;
using Artemis.Utilities; using Artemis.Utilities;
using Artemis.Utilities.ActiveWindowDetection;
using Caliburn.Micro; using Caliburn.Micro;
using Castle.Components.DictionaryAdapter; using Castle.Components.DictionaryAdapter;
using GongSolutions.Wpf.DragDrop; using GongSolutions.Wpf.DragDrop;
@ -46,21 +46,20 @@ namespace Artemis.ViewModels
{ {
public sealed class ProfileEditorViewModel : Screen, IDropTarget public sealed class ProfileEditorViewModel : Screen, IDropTarget
{ {
private readonly KeybindModel _copyKeybind;
private readonly DeviceManager _deviceManager; private readonly DeviceManager _deviceManager;
private readonly MetroDialogService _dialogService; private readonly MetroDialogService _dialogService;
private readonly LoopManager _loopManager; private readonly LoopManager _loopManager;
private readonly ModuleModel _moduleModel; private readonly ModuleModel _moduleModel;
private readonly KeybindModel _copyKeybind; private readonly KeybindModel _pasteKeybind;
private ImageSource _keyboardPreview; private ImageSource _keyboardPreview;
private ObservableCollection<LayerModel> _layers; private ObservableCollection<LayerModel> _layers;
private readonly KeybindModel _pasteKeybind;
private ObservableCollection<string> _profileNames; private ObservableCollection<string> _profileNames;
private bool _saving; private bool _saving;
private LayerModel _selectedLayer; private LayerModel _selectedLayer;
private bool _showAll; private bool _showAll;
public ProfileEditorViewModel(ProfileEditorModel profileEditorModel, DeviceManager deviceManager, public ProfileEditorViewModel(ProfileEditorModel profileEditorModel, DeviceManager deviceManager, LoopManager loopManager, LuaManager luaManager, ModuleModel moduleModel, MetroDialogService dialogService)
LoopManager loopManager, ModuleModel moduleModel, MetroDialogService dialogService)
{ {
_deviceManager = deviceManager; _deviceManager = deviceManager;
_loopManager = loopManager; _loopManager = loopManager;
@ -72,6 +71,7 @@ namespace Artemis.ViewModels
ProfileNames = new ObservableCollection<string>(); ProfileNames = new ObservableCollection<string>();
Layers = new ObservableCollection<LayerModel>(); Layers = new ObservableCollection<LayerModel>();
ProfileEditorModel = profileEditorModel; ProfileEditorModel = profileEditorModel;
LuaManager = luaManager;
ShowAll = true; ShowAll = true;
PropertyChanged += EditorStateHandler; PropertyChanged += EditorStateHandler;
@ -102,6 +102,11 @@ namespace Artemis.ViewModels
#region LUA #region LUA
public void ClickedLuaButton(EditorButton button)
{
button.Invoke();
}
public void EditLua() public void EditLua()
{ {
if (SelectedProfile == null) if (SelectedProfile == null)
@ -123,6 +128,7 @@ namespace Artemis.ViewModels
#region Properties #region Properties
public ProfileEditorModel ProfileEditorModel { get; } public ProfileEditorModel ProfileEditorModel { get; }
public LuaManager LuaManager { get; }
public ObservableCollection<string> ProfileNames public ObservableCollection<string> ProfileNames
{ {
@ -198,7 +204,7 @@ namespace Artemis.ViewModels
NotifyOfPropertyChange(() => LayerSelected); NotifyOfPropertyChange(() => LayerSelected);
} }
} }
public ProfileModel SelectedProfile => _moduleModel?.ProfileModel; public ProfileModel SelectedProfile => _moduleModel?.ProfileModel;
public bool ProfileSelected => SelectedProfile != null; public bool ProfileSelected => SelectedProfile != null;
public bool LayerSelected => SelectedProfile != null && SelectedLayer != null; public bool LayerSelected => SelectedProfile != null && SelectedLayer != null;
@ -325,7 +331,7 @@ namespace Artemis.ViewModels
public void LayerToClipboard() public void LayerToClipboard()
{ {
if (SelectedLayer == null || !ActiveWindowHelper.MainWindowActive) if (SelectedLayer == null || !ActiveWindowHelper.MainWindowActive || !IsActive)
return; return;
// Probably not how the cool kids do it but leveraging on JsonConvert gives flawless serialization // 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() public void ClipboardToLayer()
{ {
if (!ActiveWindowHelper.MainWindowActive) if (!ActiveWindowHelper.MainWindowActive || !IsActive)
return; return;
GeneralHelpers.ExecuteSta(() => try
{ {
var data = (string) Clipboard.GetData("layer"); GeneralHelpers.ExecuteSta(() =>
if (data == null)
return;
var layerModel = JsonConvert.DeserializeObject<LayerModel>(data);
if (layerModel == null)
return;
if (SelectedLayer != null)
{ {
SelectedLayer.InsertAfter(layerModel); var data = (string) Clipboard.GetData("layer");
} if (data == null)
else return;
{
SelectedProfile.Layers.Add(layerModel); var layerModel = JsonConvert.DeserializeObject<LayerModel>(data);
SelectedProfile.FixOrder(); if (layerModel == null)
} return;
Execute.OnUIThread(() => UpdateLayerList(layerModel));
}); 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) private void UpdateLayerList(LayerModel selectModel)
@ -405,6 +416,9 @@ namespace Artemis.ViewModels
if (_saving || SelectedProfile == null || _deviceManager.ChangingKeyboard) if (_saving || SelectedProfile == null || _deviceManager.ChangingKeyboard)
return; return;
SelectedProfile.Width = _deviceManager.ActiveKeyboard.Width;
SelectedProfile.Height = _deviceManager.ActiveKeyboard.Height;
_saving = true; _saving = true;
try try
{ {
@ -421,8 +435,7 @@ namespace Artemis.ViewModels
{ {
if (_deviceManager.ActiveKeyboard == null) if (_deviceManager.ActiveKeyboard == null)
{ {
_dialogService.ShowMessageBox("Cannot add profile.", _dialogService.ShowMessageBox("Cannot add profile.", "To add a profile, please select a keyboard in the options menu first.");
"To add a profile, please select a keyboard in the options menu first.");
return; return;
} }
@ -666,7 +679,7 @@ namespace Artemis.ViewModels
return; return;
var pos = GetScaledPosition(e); 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) if (hoverLayer != null)
SelectedLayer = hoverLayer; SelectedLayer = hoverLayer;
@ -682,7 +695,7 @@ namespace Artemis.ViewModels
return; return;
var pos = GetScaledPosition(e); 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); HandleDragging(e, pos.X, pos.Y, hoverLayer);
@ -701,11 +714,10 @@ namespace Artemis.ViewModels
: Cursors.SizeAll; : Cursors.SizeAll;
} }
else else
{
KeyboardPreviewCursor = Cursors.Hand; KeyboardPreviewCursor = Cursors.Hand;
}
} }
private Point GetScaledPosition(MouseEventArgs e) private Point GetScaledPosition(MouseEventArgs e)
{ {
var previewSettings = _deviceManager.ActiveKeyboard.PreviewSettings; var previewSettings = _deviceManager.ActiveKeyboard.PreviewSettings;
@ -716,16 +728,25 @@ namespace Artemis.ViewModels
var heightScale = sourceImage.ActualHeight / _deviceManager.ActiveKeyboard.PreviewSettings.BackgroundRectangle.Height; var heightScale = sourceImage.ActualHeight / _deviceManager.ActiveKeyboard.PreviewSettings.BackgroundRectangle.Height;
// Remove the preview settings' offset from the cursor postion // Remove the preview settings' offset from the cursor postion
pos.X = pos.X - (previewSettings.OverlayRectangle.X * widthScale); pos.X = pos.X - previewSettings.OverlayRectangle.X * widthScale;
pos.Y = pos.Y - (previewSettings.OverlayRectangle.Y * heightScale); 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 // 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)); pos.Y = pos.Y * (SelectedProfile.Height / (previewSettings.OverlayRectangle.Height * heightScale));
return pos; 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 public Cursor KeyboardPreviewCursor
{ {
get { return _keyboardPreviewCursor; } get { return _keyboardPreviewCursor; }

View File

@ -6,7 +6,7 @@
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls" xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
xmlns:cal="http://www.caliburnproject.org" xmlns:cal="http://www.caliburnproject.org"
mc:Ignorable="d" mc:Ignorable="d"
d:DesignHeight="600" d:DesignWidth="300"> d:DesignHeight="600" d:DesignWidth="310">
<Grid> <Grid>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
@ -25,6 +25,7 @@
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" /> <RowDefinition Height="*" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
@ -94,30 +95,36 @@
<controls:NumericUpDown Grid.Row="8" Grid.Column="1" Margin="10" VerticalAlignment="Center" <controls:NumericUpDown Grid.Row="8" Grid.Column="1" Margin="10" VerticalAlignment="Center"
HorizontalAlignment="Right" Width="140" Minimum="1" Maximum="60" HorizontalAlignment="Right" Width="140" Minimum="1" Maximum="60"
Value="{Binding Path=GeneralSettings.ScreenCaptureFPS, Mode=TwoWay}" /> Value="{Binding Path=GeneralSettings.ScreenCaptureFPS, Mode=TwoWay}" />
<!-- Logging -->
<Label Grid.Row="9" Grid.Column="0" Margin="5" VerticalAlignment="Center" HorizontalAlignment="Left" <Label Grid.Row="9" Grid.Column="0" Margin="5" VerticalAlignment="Center" HorizontalAlignment="Left"
Content="Log level:" /> Content="Active window detection" />
<ComboBox Grid.Row="9" Grid.Column="1" x:Name="LogLevels" Margin="10" VerticalAlignment="Center" <ComboBox Grid.Row="9" Grid.Column="1" x:Name="ActiveWindowDetections" Margin="10" VerticalAlignment="Center"
HorizontalAlignment="Right" HorizontalAlignment="Right"
Width="140" /> Width="140" />
<Button Grid.Row="10" Grid.Column="0" Margin="10" x:Name="ShowLogs" Content="Show logs"
<!-- Logging -->
<Label Grid.Row="10" Grid.Column="0" Margin="5" VerticalAlignment="Center" HorizontalAlignment="Left"
Content="Log level:" />
<ComboBox Grid.Row="10" Grid.Column="1" x:Name="LogLevels" Margin="10" VerticalAlignment="Center"
HorizontalAlignment="Right"
Width="140" />
<Button Grid.Row="11" Grid.Column="0" Margin="10" x:Name="ShowLogs" Content="Show logs"
VerticalAlignment="Center" Width="100" HorizontalAlignment="Left" VerticalAlignment="Center" Width="100" HorizontalAlignment="Left"
Style="{DynamicResource SquareButtonStyle}" /> Style="{DynamicResource SquareButtonStyle}" />
<Button Grid.Row="10" Grid.Column="1" Margin="10" x:Name="ShowDebug" Content="Show debugger" <Button Grid.Row="11" Grid.Column="1" Margin="10" x:Name="ShowDebug" Content="Show debugger"
VerticalAlignment="Center" Width="100" HorizontalAlignment="Right" VerticalAlignment="Center" Width="100" HorizontalAlignment="Right"
Style="{DynamicResource SquareButtonStyle}" /> Style="{DynamicResource SquareButtonStyle}" />
<!-- Buttons --> <!-- Buttons -->
<Button Grid.Row="11" Grid.Column="0" Margin="10" x:Name="ResetSettings" Content="Reset settings" <Button Grid.Row="12" Grid.Column="0" Margin="10" x:Name="ResetSettings" Content="Reset settings"
VerticalAlignment="Center" HorizontalAlignment="Left" Width="100" VerticalAlignment="Center" HorizontalAlignment="Left" Width="100"
Style="{DynamicResource SquareButtonStyle}" /> Style="{DynamicResource SquareButtonStyle}" />
<Button Grid.Row="11" Grid.Column="1" Margin="11" x:Name="SaveSettings" Content="Save changes" <Button Grid.Row="12" Grid.Column="1" Margin="11" x:Name="SaveSettings" Content="Save changes"
VerticalAlignment="Center" HorizontalAlignment="Right" Width="100" VerticalAlignment="Center" HorizontalAlignment="Right" Width="100"
Style="{DynamicResource SquareButtonStyle}" /> Style="{DynamicResource SquareButtonStyle}" />
<!-- Version --> <!-- Version -->
<Grid Grid.Row="12" Grid.Column="0" Grid.ColumnSpan="2" Margin="10" VerticalAlignment="Bottom"> <Grid Grid.Row="13" Grid.Column="0" Grid.ColumnSpan="2" Margin="10" VerticalAlignment="Bottom">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />

View File

@ -1,16 +1,8 @@
<UserControl x:Class="Artemis.Views.ProfileEditorView" <UserControl x:Class="Artemis.Views.ProfileEditorView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:cal="http://www.caliburnproject.org"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:itemBehaviours="clr-namespace:Artemis.ItemBehaviours"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:dragDrop="clr-namespace:GongSolutions.Wpf.DragDrop;assembly=GongSolutions.Wpf.DragDrop" xmlns:converters="clr-namespace:Artemis.Utilities.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls" mc:Ignorable="d" d:DesignHeight="400" d:DesignWidth="1060">
xmlns:cal="http://www.caliburnproject.org"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:itemBehaviours="clr-namespace:Artemis.ItemBehaviours"
xmlns:dragDrop="clr-namespace:GongSolutions.Wpf.DragDrop;assembly=GongSolutions.Wpf.DragDrop"
xmlns:converters="clr-namespace:Artemis.Utilities.Converters"
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
mc:Ignorable="d"
d:DesignHeight="400" d:DesignWidth="1060">
<UserControl.Resources> <UserControl.Resources>
<converters:LayerOrderConverter x:Key="LayerOrderConverter" /> <converters:LayerOrderConverter x:Key="LayerOrderConverter" />
</UserControl.Resources> </UserControl.Resources>
@ -22,7 +14,8 @@
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="40" /> <RowDefinition Height="40" />
<RowDefinition Height="*" /> <RowDefinition Height="*" />
<RowDefinition Height="60" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<!-- Preview --> <!-- Preview -->
@ -32,7 +25,9 @@
<Border.Effect> <Border.Effect>
<DropShadowEffect x:Name="ShadowEffect" ShadowDepth="0" Color="{DynamicResource HighlightColor}" Opacity="1" BlurRadius="25" /> <DropShadowEffect x:Name="ShadowEffect" ShadowDepth="0" Color="{DynamicResource HighlightColor}" Opacity="1" BlurRadius="25" />
</Border.Effect> </Border.Effect>
<Image Source="{Binding Path=KeyboardPreview}" MinHeight="10" MinWidth="10" Stretch="Uniform" Cursor="{Binding Path=KeyboardPreviewCursor}" IsEnabled="{Binding Path=EditorEnabled, Mode=OneWay}" cal:Message.Attach=" <Image Source="{Binding Path=KeyboardPreview}" MinHeight="10" MinWidth="10" Stretch="Uniform" Cursor="{Binding Path=KeyboardPreviewCursor}"
IsEnabled="{Binding Path=EditorEnabled, Mode=OneWay}"
cal:Message.Attach="
[Event MouseMove] = [Action MouseMoveKeyboardPreview($eventArgs)]; [Event MouseMove] = [Action MouseMoveKeyboardPreview($eventArgs)];
[Event MouseDown] = [Action MouseDownKeyboardPreview($eventArgs)]; [Event MouseDown] = [Action MouseDownKeyboardPreview($eventArgs)];
[Event MouseUp] = [Action MouseUpKeyboardPreview($eventArgs)]" /> [Event MouseUp] = [Action MouseUpKeyboardPreview($eventArgs)]" />
@ -43,8 +38,8 @@
<StackPanel Orientation="Horizontal" Margin="0,5,0,0"> <StackPanel Orientation="Horizontal" Margin="0,5,0,0">
<Label Content="Active profile" /> <Label Content="Active profile" />
<ComboBox Width="220" VerticalAlignment="Top" x:Name="ProfileNames" Margin="5,0,0,0" /> <ComboBox Width="220" VerticalAlignment="Top" x:Name="ProfileNames" Margin="5,0,0,0" />
<Button x:Name="AddProfile" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}" <Button x:Name="AddProfile" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}" Width="26" Height="26" HorizontalAlignment="Right" Margin="10,0,0,0"
Width="26" Height="26" HorizontalAlignment="Right" Margin="10,0,0,0" ToolTip="Add profile"> ToolTip="Add profile">
<Button.Content> <Button.Content>
<Rectangle Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" Width="12" Height="12"> <Rectangle Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" Width="12" Height="12">
<Rectangle.OpacityMask> <Rectangle.OpacityMask>
@ -53,9 +48,8 @@
</Rectangle> </Rectangle>
</Button.Content> </Button.Content>
</Button> </Button>
<Button x:Name="RenameProfile" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}" <Button x:Name="RenameProfile" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}" Width="26" Height="26" HorizontalAlignment="Right" Margin="10,0,0,0"
Width="26" Height="26" HorizontalAlignment="Right" Margin="10,0,0,0" ToolTip="Rename profile" ToolTip="Rename profile" IsEnabled="{Binding Path=EditorEnabled, Mode=OneWay}">
IsEnabled="{Binding Path=EditorEnabled, Mode=OneWay}">
<Button.Content> <Button.Content>
<Rectangle Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" Width="12" Height="12"> <Rectangle Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" Width="12" Height="12">
<Rectangle.OpacityMask> <Rectangle.OpacityMask>
@ -74,7 +68,8 @@
</Rectangle> </Rectangle>
</Button.Content> </Button.Content>
</Button> </Button>
<Button x:Name="DeleteProfile" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}" Width="26" Height="26" HorizontalAlignment="Right" Margin="10,0,0,0" ToolTip="Delete profile" IsEnabled="{Binding Path=EditorEnabled, Mode=OneWay}"> <Button x:Name="DeleteProfile" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}" Width="26" Height="26" HorizontalAlignment="Right" Margin="10,0,0,0"
ToolTip="Delete profile" IsEnabled="{Binding Path=EditorEnabled, Mode=OneWay}">
<Button.Content> <Button.Content>
<Rectangle Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" Width="12" Height="12"> <Rectangle Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" Width="12" Height="12">
<Rectangle.OpacityMask> <Rectangle.OpacityMask>
@ -84,17 +79,12 @@
</Button.Content> </Button.Content>
</Button> </Button>
</StackPanel> </StackPanel>
<TextBlock VerticalAlignment="Top" Foreground="{DynamicResource HighlightBrush}" HorizontalAlignment="Left" Margin="5,5,0,0" Text="Note: To edit a default profile, duplicate it first." FontWeight="Bold" />
</StackPanel> </StackPanel>
<StackPanel Grid.Column="0" Grid.Row="2" Orientation="Horizontal" Margin="0,5,0,0" HorizontalAlignment="Right"> <StackPanel Grid.Column="0" Grid.Row="2" Orientation="Horizontal" Margin="0,5,0,0" HorizontalAlignment="Right">
<Button x:Name="ImportProfile" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}" <Button x:Name="ImportProfile" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}" Height="26" HorizontalAlignment="Right">
Height="26" HorizontalAlignment="Right">
<Button.Content> <Button.Content>
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<Rectangle <Rectangle Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" Width="12" Height="12" Margin="3,0">
Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}"
Width="12" Height="12" Margin="3,0">
<Rectangle.OpacityMask> <Rectangle.OpacityMask>
<VisualBrush Visual="{StaticResource appbar_cabinet_in}" Stretch="Fill" /> <VisualBrush Visual="{StaticResource appbar_cabinet_in}" Stretch="Fill" />
</Rectangle.OpacityMask> </Rectangle.OpacityMask>
@ -103,13 +93,11 @@
</StackPanel> </StackPanel>
</Button.Content> </Button.Content>
</Button> </Button>
<Button x:Name="ExportProfile" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}" <Button x:Name="ExportProfile" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}" Height="26" HorizontalAlignment="Right" Margin="10,0,0,0"
Height="26" HorizontalAlignment="Right" Margin="10,0,0,0" IsEnabled="{Binding ProfileSelected}"> IsEnabled="{Binding ProfileSelected}">
<Button.Content> <Button.Content>
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<Rectangle <Rectangle Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" Width="12" Height="12" Margin="3,0">
Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}"
Width="12" Height="12" Margin="3,0">
<Rectangle.OpacityMask> <Rectangle.OpacityMask>
<VisualBrush Visual="{StaticResource appbar_cabinet_out}" Stretch="Fill" /> <VisualBrush Visual="{StaticResource appbar_cabinet_out}" Stretch="Fill" />
</Rectangle.OpacityMask> </Rectangle.OpacityMask>
@ -118,14 +106,11 @@
</StackPanel> </StackPanel>
</Button.Content> </Button.Content>
</Button> </Button>
<Button x:Name="EditLua" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}" Height="26" <Button x:Name="EditLua" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}" Height="26" HorizontalAlignment="Right" Margin="10,0,0,0"
HorizontalAlignment="Right" Margin="10,0,0,0" IsEnabled="{Binding Path=EditorEnabled, Mode=OneWay}" IsEnabled="{Binding Path=EditorEnabled, Mode=OneWay}" Visibility="{Binding Path=LuaButtonVisible, Converter={StaticResource BoolToVis} }">
Visibility="{Binding Path=LuaButtonVisible, Converter={StaticResource BoolToVis} }">
<Button.Content> <Button.Content>
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<Rectangle <Rectangle Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" Width="12" Height="12" Margin="3,0">
Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}"
Width="12" Height="12" Margin="3,0">
<Rectangle.OpacityMask> <Rectangle.OpacityMask>
<VisualBrush Visual="{StaticResource appbar_code_xml}" Stretch="Fill" /> <VisualBrush Visual="{StaticResource appbar_code_xml}" Stretch="Fill" />
</Rectangle.OpacityMask> </Rectangle.OpacityMask>
@ -154,8 +139,7 @@
ItemsSource="{Binding Path=Layers, Converter={StaticResource LayerOrderConverter}, ConverterParameter=Order}" IsEnabled="{Binding Path=EditorEnabled, Mode=OneWay}" ItemsSource="{Binding Path=Layers, Converter={StaticResource LayerOrderConverter}, ConverterParameter=Order}" IsEnabled="{Binding Path=EditorEnabled, Mode=OneWay}"
cal:Message.Attach="[Event MouseDoubleClick] = [Action EditLayerFromDoubleClick]"> cal:Message.Attach="[Event MouseDoubleClick] = [Action EditLayerFromDoubleClick]">
<i:Interaction.Behaviors> <i:Interaction.Behaviors>
<itemBehaviours:BindableSelectedItemBehavior <itemBehaviours:BindableSelectedItemBehavior SelectedItem="{Binding SelectedLayer, Mode=TwoWay}" />
SelectedItem="{Binding SelectedLayer, Mode=TwoWay}" />
</i:Interaction.Behaviors> </i:Interaction.Behaviors>
<TreeView.Resources> <TreeView.Resources>
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseDark.xaml" /> <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseDark.xaml" />
@ -185,9 +169,8 @@
</TreeView> </TreeView>
</Border> </Border>
<StackPanel Grid.Column="1" Grid.Row="2" Orientation="Horizontal" Margin="0,5,0,0" HorizontalAlignment="Right"> <StackPanel Grid.Column="1" Grid.Row="2" Orientation="Horizontal" Margin="0,5,0,0" HorizontalAlignment="Right">
<Button x:Name="AddLayer" VerticalAlignment="Top" <Button x:Name="AddLayer" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}" IsEnabled="{Binding Path=EditorEnabled, Mode=OneWay}" Width="26" Height="26"
Style="{DynamicResource SquareButtonStyle}" IsEnabled="{Binding Path=EditorEnabled, Mode=OneWay}" ToolTip="Add layer" HorizontalAlignment="Left">
Width="26" Height="26" ToolTip="Add layer" HorizontalAlignment="Left">
<Button.Content> <Button.Content>
<Rectangle Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" Width="12" Height="12"> <Rectangle Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" Width="12" Height="12">
<Rectangle.OpacityMask> <Rectangle.OpacityMask>
@ -196,9 +179,8 @@
</Rectangle> </Rectangle>
</Button.Content> </Button.Content>
</Button> </Button>
<Button x:Name="AddFolder" VerticalAlignment="Top" <Button x:Name="AddFolder" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}" IsEnabled="{Binding Path=EditorEnabled, Mode=OneWay}" Width="26" Height="26"
Style="{DynamicResource SquareButtonStyle}" IsEnabled="{Binding Path=EditorEnabled, Mode=OneWay}" ToolTip="Add folder" HorizontalAlignment="Left" Margin="10,0,0,0">
Width="26" Height="26" ToolTip="Add folder" HorizontalAlignment="Left" Margin="10,0,0,0">
<Button.Content> <Button.Content>
<Rectangle Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" Width="12" Height="12"> <Rectangle Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" Width="12" Height="12">
<Rectangle.OpacityMask> <Rectangle.OpacityMask>
@ -207,8 +189,7 @@
</Rectangle> </Rectangle>
</Button.Content> </Button.Content>
</Button> </Button>
<Button x:Name="EditLayer" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}" <Button x:Name="EditLayer" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}" Width="26" Height="26" HorizontalAlignment="Right" Margin="10,0,0,0" ToolTip="Edit layer"
Width="26" Height="26" HorizontalAlignment="Right" Margin="10,0,0,0" ToolTip="Edit layer"
IsEnabled="{Binding Path=LayerSelected}"> IsEnabled="{Binding Path=LayerSelected}">
<Button.Content> <Button.Content>
<Rectangle Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" Width="12" Height="12"> <Rectangle Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" Width="12" Height="12">
@ -218,9 +199,8 @@
</Rectangle> </Rectangle>
</Button.Content> </Button.Content>
</Button> </Button>
<Button x:Name="CloneLayer" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}" <Button x:Name="CloneLayer" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}" Width="26" Height="26" HorizontalAlignment="Right" Margin="10,0,0,0"
Width="26" Height="26" HorizontalAlignment="Right" Margin="10,0,0,0" ToolTip="Duplicate layer" ToolTip="Duplicate layer" IsEnabled="{Binding Path=LayerSelected}">
IsEnabled="{Binding Path=LayerSelected}">
<Button.Content> <Button.Content>
<Rectangle Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" Width="12" Height="12"> <Rectangle Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" Width="12" Height="12">
<Rectangle.OpacityMask> <Rectangle.OpacityMask>
@ -229,9 +209,8 @@
</Rectangle> </Rectangle>
</Button.Content> </Button.Content>
</Button> </Button>
<Button x:Name="RemoveLayer" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}" <Button x:Name="RemoveLayer" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}" Width="26" Height="26" HorizontalAlignment="Right" Margin="10,0,0,0"
Width="26" Height="26" HorizontalAlignment="Right" Margin="10,0,0,0" ToolTip="Delete layer" ToolTip="Delete layer" IsEnabled="{Binding Path=LayerSelected}">
IsEnabled="{Binding Path=LayerSelected}">
<Button.Content> <Button.Content>
<Rectangle Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" Width="12" Height="12"> <Rectangle Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" Width="12" Height="12">
<Rectangle.OpacityMask> <Rectangle.OpacityMask>
@ -241,5 +220,21 @@
</Button.Content> </Button.Content>
</Button> </Button>
</StackPanel> </StackPanel>
<TextBlock VerticalAlignment="Top" Grid.Column="0" Grid.Row="3" Foreground="{DynamicResource HighlightBrush}" Margin="0,5" HorizontalAlignment="Left"
Text="Note: To edit a default profile, duplicate it first." FontWeight="Bold" />
<ItemsControl ItemsSource="{Binding Path=LuaManager.EditorButtons}" Grid.Column="1" Grid.Row="3" Margin="0,5" HorizontalAlignment="Right">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding Text}" cal:Message.Attach="ClickedLuaButton($dataContext)" Style="{DynamicResource SquareButtonStyle}" Height="26" Margin="5,0,0,0" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid> </Grid>
</UserControl> </UserControl>

View File

@ -22,7 +22,7 @@
<ProjectGuid>{1A349CF5-2008-41E8-AC13-874CBBCDFA0A}</ProjectGuid> <ProjectGuid>{1A349CF5-2008-41E8-AC13-874CBBCDFA0A}</ProjectGuid>
<Keyword>Win32Proj</Keyword> <Keyword>Win32Proj</Keyword>
<RootNamespace>LightFX2Artemis</RootNamespace> <RootNamespace>LightFX2Artemis</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion> <WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

View File

@ -23,6 +23,7 @@
<Keyword>Win32Proj</Keyword> <Keyword>Win32Proj</Keyword>
<RootNamespace>LogiLed2Artemis</RootNamespace> <RootNamespace>LogiLed2Artemis</RootNamespace>
<ProjectName>LogiLed2Artemis</ProjectName> <ProjectName>LogiLed2Artemis</ProjectName>
<WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

View File

@ -21,7 +21,7 @@
<PropertyGroup Label="Globals"> <PropertyGroup Label="Globals">
<ProjectGuid>{39711909-C1D5-46CE-A9EA-2D561692EA47}</ProjectGuid> <ProjectGuid>{39711909-C1D5-46CE-A9EA-2D561692EA47}</ProjectGuid>
<RootNamespace>Razer2Artemis</RootNamespace> <RootNamespace>Razer2Artemis</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion> <WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">