1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-31 09:43:46 +00:00

Disabled The Division module (broken)

Disabled LightFX module (unfinished)
Added keybind event triggers
Fixed condition dropdown width
Adjusted layer properties window height
Improved GTA V DLL placement
This commit is contained in:
SpoinkyNL 2017-03-18 23:36:51 +01:00
parent 87a30b8936
commit ec490155fd
23 changed files with 475 additions and 437 deletions

View File

@ -1,7 +1,7 @@
using System; using System;
using System.Windows; using System.Windows;
using System.Windows.Threading; using System.Windows.Threading;
using Artemis.Utilities.Keyboard; using Artemis.Utilities;
using NLog; using NLog;
using WpfExceptionViewer; using WpfExceptionViewer;
@ -28,7 +28,7 @@ namespace Artemis
private void Application_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) private void Application_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{ {
// Get rid of the keyboard hook in case of a crash, otherwise input freezes up system wide until Artemis is gone // Get rid of the keyboard hook in case of a crash, otherwise input freezes up system wide until Artemis is gone
KeyboardHook.Stop(); InputHook.Stop();
if (DoHandle) if (DoHandle)
{ {

View File

@ -663,7 +663,7 @@
<Compile Include="Utilities\GeneralHelpers.cs" /> <Compile Include="Utilities\GeneralHelpers.cs" />
<Compile Include="Utilities\GifImage.cs" /> <Compile Include="Utilities\GifImage.cs" />
<Compile Include="Utilities\ImageUtilities.cs" /> <Compile Include="Utilities\ImageUtilities.cs" />
<Compile Include="Utilities\Keyboard\KeyboardHook.cs" /> <Compile Include="Utilities\InputHook.cs" />
<Compile Include="Utilities\Logging.cs" /> <Compile Include="Utilities\Logging.cs" />
<Compile Include="Utilities\DataReaders\PipeServer.cs" /> <Compile Include="Utilities\DataReaders\PipeServer.cs" />
<Compile Include="Utilities\Markdown\Markdown.cs" /> <Compile Include="Utilities\Markdown\Markdown.cs" />

View File

@ -12,7 +12,6 @@ using Artemis.Settings;
using Artemis.Utilities; using Artemis.Utilities;
using Artemis.Utilities.Converters; using Artemis.Utilities.Converters;
using Artemis.Utilities.DataReaders; using Artemis.Utilities.DataReaders;
using Artemis.Utilities.Keyboard;
using Artemis.ViewModels; using Artemis.ViewModels;
using Caliburn.Micro; using Caliburn.Micro;
using Newtonsoft.Json; using Newtonsoft.Json;
@ -35,7 +34,7 @@ namespace Artemis
Initialize(); Initialize();
BindSpecialValues(); BindSpecialValues();
KeyboardHook.Start(); InputHook.Start();
AppDomain.CurrentDomain.UnhandledException += CurrentDomainOnUnhandledException; AppDomain.CurrentDomain.UnhandledException += CurrentDomainOnUnhandledException;
} }
@ -43,7 +42,7 @@ namespace Artemis
private void CurrentDomainOnUnhandledException(object sender, UnhandledExceptionEventArgs unhandledExceptionEventArgs) private void CurrentDomainOnUnhandledException(object sender, UnhandledExceptionEventArgs unhandledExceptionEventArgs)
{ {
// Get rid of the keyboard hook in case of a crash, otherwise input freezes up system wide until Artemis is gone // Get rid of the keyboard hook in case of a crash, otherwise input freezes up system wide until Artemis is gone
KeyboardHook.Stop(); InputHook.Stop();
} }
private void BindSpecialValues() private void BindSpecialValues()

View File

@ -21,8 +21,7 @@ namespace Artemis.DAL
{ {
private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
public static readonly string ProfileFolder = public static readonly string ProfileFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Artemis\profiles";
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Artemis\profiles";
private static bool _installedDefaults; private static bool _installedDefaults;

View File

@ -10,6 +10,9 @@ namespace Artemis.DeviceProviders.Logitech
{ {
public override bool CanEnable() public override bool CanEnable()
{ {
// Just to be sure, restore the Logitech DLL registry key
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)
@ -22,17 +25,6 @@ namespace Artemis.DeviceProviders.Logitech
return false; return false;
} }
if (DllManager.DllPlaced())
{
CantEnableText =
"Artemis couldn't enable your Logitech keyboard, because the required files are not in place.\n\n" +
"This happens when you run The Division or GTA and shut down Artemis before shutting down The Division\n" +
"Artemis tries to fix this automatically on startup but because the files may have been in use it failed.\n\n" +
"To try again, restart Artemis or check out the FAQ.";
return false;
}
int majorNum = 0, minorNum = 0, buildNum = 0; int majorNum = 0, minorNum = 0, buildNum = 0;
LogitechGSDK.LogiLedInit(); LogitechGSDK.LogiLedInit();
@ -73,4 +65,4 @@ namespace Artemis.DeviceProviders.Logitech
LogitechGSDK.LogiLedSetLightingFromBitmap(OrionUtilities.BitmapToByteArray(bitmap)); LogitechGSDK.LogiLedSetLightingFromBitmap(OrionUtilities.BitmapToByteArray(bitmap));
} }
} }
} }

View File

@ -1,10 +1,9 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Windows.Forms; using System.Windows.Forms;
using System.Windows.Input; using System.Windows.Input;
using Artemis.Models; using Artemis.Models;
using Artemis.Utilities.Keyboard; using Artemis.Utilities;
using MahApps.Metro.Controls; using MahApps.Metro.Controls;
using KeyEventArgs = System.Windows.Forms.KeyEventArgs; using KeyEventArgs = System.Windows.Forms.KeyEventArgs;
using MouseEventArgs = System.Windows.Forms.MouseEventArgs; using MouseEventArgs = System.Windows.Forms.MouseEventArgs;
@ -17,12 +16,12 @@ namespace Artemis.Managers
static KeybindManager() static KeybindManager()
{ {
KeyboardHook.KeyDownCallback += args => ProcessKey(args, PressType.Down); InputHook.KeyDownCallback += args => ProcessKey(args, PressType.Down);
KeyboardHook.KeyUpCallback += args => ProcessKey(args, PressType.Up); InputHook.KeyUpCallback += args => ProcessKey(args, PressType.Up);
KeyboardHook.MouseDownCallback += args => ProcessMouse(args, PressType.Down); InputHook.MouseDownCallback += args => ProcessMouse(args, PressType.Down);
KeyboardHook.MouseUpCallback += args => ProcessMouse(args, PressType.Up); InputHook.MouseUpCallback += args => ProcessMouse(args, PressType.Up);
} }
private static void ProcessKey(KeyEventArgs keyEventArgs, PressType pressType) private static void ProcessKey(KeyEventArgs keyEventArgs, PressType pressType)
{ {
// Don't trigger if the key itself is a modifier // Don't trigger if the key itself is a modifier
@ -38,7 +37,7 @@ namespace Artemis.Managers
var hotKey = new HotKey(KeyInterop.KeyFromVirtualKey(keyEventArgs.KeyValue), modifiers); var hotKey = new HotKey(KeyInterop.KeyFromVirtualKey(keyEventArgs.KeyValue), modifiers);
foreach (var keybindModel in KeybindModels) foreach (var keybindModel in KeybindModels)
keybindModel.InvokeIfMatched(hotKey, pressType); keybindModel.InvokeIfMatched(hotKey, pressType);
} }
private static void ProcessMouse(MouseEventArgs mouseEventArgs, PressType pressType) private static void ProcessMouse(MouseEventArgs mouseEventArgs, PressType pressType)
@ -79,15 +78,19 @@ namespace Artemis.Managers
if (alt) if (alt)
modifiers = ModifierKeys.Alt; modifiers = ModifierKeys.Alt;
if (control) if (control)
{
if (modifiers == ModifierKeys.None) if (modifiers == ModifierKeys.None)
modifiers = ModifierKeys.Control; modifiers = ModifierKeys.Control;
else else
modifiers |= ModifierKeys.Control; modifiers |= ModifierKeys.Control;
}
if (shift) if (shift)
{
if (modifiers == ModifierKeys.None) if (modifiers == ModifierKeys.None)
modifiers = ModifierKeys.Shift; modifiers = ModifierKeys.Shift;
else else
modifiers |= ModifierKeys.Shift; modifiers |= ModifierKeys.Shift;
}
return modifiers; return modifiers;
} }

View File

@ -1,4 +1,5 @@
using System.Threading; using System.Linq;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Media; using System.Windows.Media;
using Artemis.DAL; using Artemis.DAL;
@ -13,8 +14,7 @@ namespace Artemis.Modules.Games.GtaV
{ {
private readonly PipeServer _pipeServer; private readonly PipeServer _pipeServer;
public GtaVModel(DeviceManager deviceManager, LuaManager luaManager, PipeServer pipeServer) public GtaVModel(DeviceManager deviceManager, LuaManager luaManager, PipeServer pipeServer) : base(deviceManager, luaManager)
: base(deviceManager, luaManager)
{ {
_pipeServer = pipeServer; _pipeServer = pipeServer;
@ -29,6 +29,7 @@ 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

@ -1,55 +1,55 @@
using System; //using System;
using System.IO; //using System.IO;
using Artemis.DAL; //using Artemis.DAL;
using Artemis.Managers; //using Artemis.Managers;
using Artemis.Modules.Abstract; //using Artemis.Modules.Abstract;
using Artemis.Utilities.DataReaders; //using Artemis.Utilities.DataReaders;
using Newtonsoft.Json; //using Newtonsoft.Json;
//
namespace Artemis.Modules.Games.LightFx //namespace Artemis.Modules.Games.LightFx
{ //{
public class LightFxModel : ModuleModel // public class LightFxModel : ModuleModel
{ // {
public LightFxModel(DeviceManager deviceManager, LuaManager luaManager, PipeServer pipeServer) // public LightFxModel(DeviceManager deviceManager, LuaManager luaManager, PipeServer pipeServer)
: base(deviceManager, luaManager) // : base(deviceManager, luaManager)
{ // {
Settings = SettingsProvider.Load<LightFxSettings>(); // Settings = SettingsProvider.Load<LightFxSettings>();
DataModel = new LightFxDataModel(); // DataModel = new LightFxDataModel();
ProcessNames.Add("LoL"); // ProcessNames.Add("LoL");
//
// This model can enable itself by changing its process name to the currently running Light FX game. // // This model can enable itself by changing its process name to the currently running Light FX game.
pipeServer.PipeMessage += PipeServerOnPipeMessage; // pipeServer.PipeMessage += PipeServerOnPipeMessage;
} // }
//
public override string Name => "LightFX"; // public override string Name => "LightFX";
public override bool IsOverlay => false; // public override bool IsOverlay => false;
public override bool IsBoundToProcess => true; // public override bool IsBoundToProcess => true;
//
private void PipeServerOnPipeMessage(string msg) // private void PipeServerOnPipeMessage(string msg)
{ // {
// Ensure it's Light FX JSON // // Ensure it's Light FX JSON
if (!msg.Contains("lightFxState")) // if (!msg.Contains("lightFxState"))
return; // return;
//
// Deserialize and data // // Deserialize and data
try // try
{ // {
JsonConvert.PopulateObject(msg, DataModel); // JsonConvert.PopulateObject(msg, DataModel);
} // }
catch (Exception ex) // catch (Exception ex)
{ // {
Logger?.Error(ex, "Failed to deserialize LightFX JSON"); // Logger?.Error(ex, "Failed to deserialize LightFX JSON");
throw; // throw;
} // }
//
// Setup process name // // Setup process name
var processName = Path.GetFileNameWithoutExtension(((LightFxDataModel) DataModel).LightFxState.game); // var processName = Path.GetFileNameWithoutExtension(((LightFxDataModel) DataModel).LightFxState.game);
if (!ProcessNames.Contains(processName)) // if (!ProcessNames.Contains(processName))
ProcessNames.Add(processName); // ProcessNames.Add(processName);
} // }
//
public override void Update() // public override void Update()
{ // {
} // }
} // }
} //}

View File

@ -1,17 +1,17 @@
using Artemis.Managers; //using Artemis.Managers;
using Artemis.Modules.Abstract; //using Artemis.Modules.Abstract;
using Ninject; //using Ninject;
//
namespace Artemis.Modules.Games.LightFx //namespace Artemis.Modules.Games.LightFx
{ //{
public sealed class LightFxViewModel : ModuleViewModel // public sealed class LightFxViewModel : ModuleViewModel
{ // {
public LightFxViewModel(MainManager mainManager, [Named(nameof(LightFxModel))] ModuleModel moduleModel, // public LightFxViewModel(MainManager mainManager, [Named(nameof(LightFxModel))] ModuleModel moduleModel,
IKernel kernel) : base(mainManager, moduleModel, kernel) // IKernel kernel) : base(mainManager, moduleModel, kernel)
{ // {
DisplayName = "Light FX"; // DisplayName = "Light FX";
} // }
//
public override bool UsesProfileEditor => true; // public override bool UsesProfileEditor => true;
} // }
} //}

View File

@ -1,138 +1,143 @@
using System.Collections.Generic; //using System.Collections.Generic;
using System.Threading; //using System.Linq;
using System.Threading.Tasks; //using System.Threading;
using Artemis.DAL; //using System.Threading.Tasks;
using Artemis.Managers; //using Artemis.DAL;
using Artemis.Modules.Abstract; //using Artemis.DeviceProviders.Logitech.Utilities;
using Artemis.Utilities; //using Artemis.Managers;
using Artemis.Utilities.DataReaders; //using Artemis.Modules.Abstract;
//using Artemis.Utilities;
namespace Artemis.Modules.Games.TheDivision //using Artemis.Utilities.DataReaders;
{ //
public class TheDivisionModel : ModuleModel //namespace Artemis.Modules.Games.TheDivision
{ //{
private readonly PipeServer _pipeServer; // public class TheDivisionModel : ModuleModel
private StickyValue<bool> _stickyAmmo; // {
private StickyValue<bool> _stickyHp; // private readonly PipeServer _pipeServer;
// private StickyValue<bool> _stickyAmmo;
public TheDivisionModel(DeviceManager deviceManager, LuaManager luaManager, PipeServer pipeServer) // private StickyValue<bool> _stickyHp;
: base(deviceManager, luaManager) //
{ // public TheDivisionModel(DeviceManager deviceManager, LuaManager luaManager, PipeServer pipeServer)
_pipeServer = pipeServer; // : base(deviceManager, luaManager)
// {
Settings = SettingsProvider.Load<TheDivisionSettings>(); // _pipeServer = pipeServer;
DataModel = new TheDivisionDataModel(); //
ProcessNames.Add("TheDivision"); // Settings = SettingsProvider.Load<TheDivisionSettings>();
} // DataModel = new TheDivisionDataModel();
// ProcessNames.Add("TheDivision");
public override string Name => "TheDivision"; // }
public override bool IsOverlay => false; //
public override bool IsBoundToProcess => true; // public override string Name => "TheDivision";
// public override bool IsOverlay => false;
public override void Dispose() // public override bool IsBoundToProcess => true;
{ //
base.Dispose(); // public override void Dispose()
// {
// Delay restoring the DLL to allow The Division to release it // base.Dispose();
Task.Factory.StartNew(() => //
{ // // Delay restoring the DLL to allow The Division to release it
Thread.Sleep(2000); // Task.Factory.StartNew(() =>
DllManager.RestoreLogitechDll(); // {
}); // Thread.Sleep(2000);
// DllManager.RestoreLogitechDll();
_stickyAmmo?.Dispose(); // });
_stickyHp?.Dispose(); //
_pipeServer.PipeMessage -= PipeServerOnPipeMessage; // _stickyAmmo?.Dispose();
} // _stickyHp?.Dispose();
// _pipeServer.PipeMessage -= PipeServerOnPipeMessage;
public override void Enable() // }
{ //
_stickyAmmo = new StickyValue<bool>(200); // public override void Enable()
_stickyHp = new StickyValue<bool>(200); // {
// _stickyAmmo = new StickyValue<bool>(200);
DllManager.PlaceLogitechDll(); // _stickyHp = new StickyValue<bool>(200);
//
_pipeServer.PipeMessage += PipeServerOnPipeMessage; // var process = System.Diagnostics.Process.GetProcessesByName("TheDivision").First();
// DllManager.PlaceLogitechDll();
base.Enable(); //
} // _pipeServer.PipeMessage += PipeServerOnPipeMessage;
//
private void PipeServerOnPipeMessage(string reply) // base.Enable();
{ // }
if (!IsInitialized) //
return; // private void PipeServerOnPipeMessage(string reply)
// {
// Convert the given string to a list of ints // if (!IsInitialized)
var stringParts = reply.Split(' '); // return;
if (stringParts[0] != "1") //
return; // // Convert the given string to a list of ints
// var stringParts = reply.Split(' ');
// Parse into a list of ints and interpertrate // if (stringParts[0] != "1")
var parts = new int[stringParts.Length]; // return;
for (var i = 0; i < stringParts.Length; i++) //
parts[i] = int.Parse(stringParts[i]); // // Parse into a list of ints and interpertrate
// var parts = new int[stringParts.Length];
InterpertrateDivisionKey(parts); // for (var i = 0; i < stringParts.Length; i++)
} // parts[i] = int.Parse(stringParts[i]);
//
// Parses Division key data to game data // InterpertrateDivisionKey(parts);
private void InterpertrateDivisionKey(IReadOnlyList<int> parts) // }
{ //
var gameDataModel = (TheDivisionDataModel) DataModel; // // Parses Division key data to game data
var keyCode = parts[1]; // private void InterpertrateDivisionKey(IReadOnlyList<int> parts)
var rPer = parts[2]; // {
var gPer = parts[3]; // var gameDataModel = (TheDivisionDataModel) DataModel;
var bPer = parts[4]; // var keyCode = parts[1];
// var rPer = parts[2];
// F1 to F4 indicate the player and his party. Blinks red on damage taken // var gPer = parts[3];
if (keyCode >= 59 && keyCode <= 62) // var bPer = parts[4];
{ //
var playerId = keyCode - 58; // var keyEnum = (KeyboardNames) keyCode;
//
PlayerState newState; // // F1 to F4 indicate the player and his party. Blinks red on damage taken
if (gPer > 10) // if (keyCode >= 59 && keyCode <= 62)
newState = PlayerState.Online; // {
else if (rPer > 10) // var playerId = keyCode - 58;
newState = PlayerState.Hit; //
else // PlayerState newState;
newState = PlayerState.Offline; // if (gPer > 10)
// newState = PlayerState.Online;
if (playerId == 1) // else if (rPer > 10)
gameDataModel.LowHp = newState == PlayerState.Hit; // newState = PlayerState.Hit;
else if (playerId == 2) // else
gameDataModel.PartyMember1 = newState; // newState = PlayerState.Offline;
else if (playerId == 3) //
gameDataModel.PartyMember2 = newState; // if (playerId == 1)
else if (playerId == 4) // gameDataModel.LowHp = newState == PlayerState.Hit;
gameDataModel.PartyMember3 = newState; // else if (playerId == 2)
} // gameDataModel.PartyMember1 = newState;
// R blinks white when low on ammo // else if (playerId == 3)
else if (keyCode == 19) // gameDataModel.PartyMember2 = newState;
{ // else if (playerId == 4)
_stickyAmmo.Value = rPer == 100 && gPer > 1 && bPer > 1; // gameDataModel.PartyMember3 = newState;
gameDataModel.LowAmmo = _stickyAmmo.Value; // }
} // // R blinks white when low on ammo
// G turns white when holding a grenade, turns off when out of grenades // else if (keyCode == 19)
else if (keyCode == 34) // {
{ // _stickyAmmo.Value = rPer == 100 && gPer > 1 && bPer > 1;
if (rPer == 100 && gPer < 10 && bPer < 10) // gameDataModel.LowAmmo = _stickyAmmo.Value;
gameDataModel.GrenadeState = GrenadeState.HasGrenade; // }
else if (rPer == 100 && gPer > 10 && bPer > 10) // // G turns white when holding a grenade, turns off when out of grenades
gameDataModel.GrenadeState = GrenadeState.GrenadeEquipped; // else if (keyCode == 34)
else // {
gameDataModel.GrenadeState = GrenadeState.HasNoGrenade; // if (rPer == 100 && gPer < 10 && bPer < 10)
} // gameDataModel.GrenadeState = GrenadeState.HasGrenade;
// V blinks on low HP // else if (rPer == 100 && gPer > 10 && bPer > 10)
else if (keyCode == 47) // gameDataModel.GrenadeState = GrenadeState.GrenadeEquipped;
{ // else
_stickyHp.Value = rPer == 100 && gPer > 1 && bPer > 1; // gameDataModel.GrenadeState = GrenadeState.HasNoGrenade;
gameDataModel.LowHp = _stickyHp.Value; // }
} // // V blinks on low HP
} // else if (keyCode == 47)
// {
public override void Update() // _stickyHp.Value = rPer == 100 && gPer > 1 && bPer > 1;
{ // gameDataModel.LowHp = _stickyHp.Value;
// DataModel updating is done whenever a pipe message is received // }
} // }
} //
} // public override void Update()
// {
// // DataModel updating is done whenever a pipe message is received
// }
// }
//}

View File

@ -1,17 +1,17 @@
using Artemis.Managers; //using Artemis.Managers;
using Artemis.Modules.Abstract; //using Artemis.Modules.Abstract;
using Ninject; //using Ninject;
//
namespace Artemis.Modules.Games.TheDivision //namespace Artemis.Modules.Games.TheDivision
{ //{
public sealed class TheDivisionViewModel : ModuleViewModel // public sealed class TheDivisionViewModel : ModuleViewModel
{ // {
public TheDivisionViewModel(MainManager mainManager, [Named(nameof(TheDivisionModel))] ModuleModel moduleModel, // public TheDivisionViewModel(MainManager mainManager, [Named(nameof(TheDivisionModel))] ModuleModel moduleModel,
IKernel kernel) : base(mainManager, moduleModel, kernel) // IKernel kernel) : base(mainManager, moduleModel, kernel)
{ // {
DisplayName = "The Division"; // DisplayName = "The Division";
} // }
//
public override bool UsesProfileEditor => true; // public override bool UsesProfileEditor => true;
} // }
} //}

View File

@ -2,34 +2,48 @@
using System.Windows.Media; using System.Windows.Media;
using Artemis.Profiles.Layers.Interfaces; using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Models; using Artemis.Profiles.Layers.Models;
using Betwixt;
namespace Artemis.Profiles.Layers.Animations namespace Artemis.Profiles.Layers.Animations
{ {
public class PulseAnimation : ILayerAnimation public class PulseAnimation : ILayerAnimation
{ {
private bool _increase = true;
private Tweener<float> _opacityTweener = new Tweener<float>(0, 1000, 1000, Ease.Quad.InOut, LerpFuncFloat);
public string Name => "Pulse"; public string Name => "Pulse";
public void Update(LayerModel layerModel, bool updateAnimations) public void Update(LayerModel layerModel, bool updateAnimations)
{ {
// TODO: Generic implementation // TODO: Generic implementation
// Reset animation progress if layer wasn't drawn for 100ms // Reset animation progress if layer wasn't drawn for 100ms
if ((new TimeSpan(0, 0, 0, 0, 100) < DateTime.Now - layerModel.LastRender) && updateAnimations) if (new TimeSpan(0, 0, 0, 0, 100) < DateTime.Now - layerModel.LastRender && updateAnimations || MustExpire(layerModel))
layerModel.AnimationProgress = 0; {
_opacityTweener = new Tweener<float>(0, 1000, 1000, Ease.Quad.InOut, LerpFuncFloat);
_increase = true;
}
var progress = layerModel.AnimationProgress; // Update animation progress
if (!updateAnimations)
return;
if (MustExpire(layerModel)) if (!_opacityTweener.Running && _increase)
progress = 0; {
progress = progress + layerModel.Properties.AnimationSpeed/2; _opacityTweener = new Tweener<float>(1000, 0, 1000, Ease.Quad.InOut, LerpFuncFloat);
_increase = false;
}
// If not previewing, store the animation progress in the actual model for the next frame _opacityTweener.Update(40);
if (updateAnimations)
layerModel.AnimationProgress = progress; if (_increase)
layerModel.AnimationProgress = _opacityTweener.Value / 1000;
else
layerModel.AnimationProgress = 1 + (1 - _opacityTweener.Value / 1000);
} }
public void Draw(LayerModel layerModel, DrawingContext c, int drawScale) public void Draw(LayerModel layerModel, DrawingContext c, int drawScale)
{ {
if (layerModel.Brush == null) if (layerModel.Brush == null || _opacityTweener == null)
return; return;
// Set up variables for this frame // Set up variables for this frame
@ -41,7 +55,7 @@ namespace Artemis.Profiles.Layers.Animations
// Can't meddle with the original brush because it's frozen. // Can't meddle with the original brush because it's frozen.
var brush = layerModel.Brush.Clone(); var brush = layerModel.Brush.Clone();
brush.Opacity = (Math.Sin(layerModel.AnimationProgress*Math.PI) + 1)*(layerModel.Opacity/2); brush.Opacity = _opacityTweener.Value / 1000;
layerModel.Brush = brush; layerModel.Brush = brush;
c.PushClip(new RectangleGeometry(clip)); c.PushClip(new RectangleGeometry(clip));
@ -49,6 +63,11 @@ namespace Artemis.Profiles.Layers.Animations
c.Pop(); c.Pop();
} }
public bool MustExpire(LayerModel layer) => layer.AnimationProgress > 2; public bool MustExpire(LayerModel layer) => layer.AnimationProgress >= 2;
private static float LerpFuncFloat(float start, float end, float percent)
{
return start + (end - start) * percent;
}
} }
} }

View File

@ -12,6 +12,15 @@ namespace Artemis.Profiles.Layers.Conditions
lock (layerModel.Properties.Conditions) lock (layerModel.Properties.Conditions)
{ {
var checkConditions = layerModel.Properties.Conditions.Where(c => c.Field != null).ToList(); var checkConditions = layerModel.Properties.Conditions.Where(c => c.Field != null).ToList();
// Don't trigger constantly when there are no conditions
if (!checkConditions.Any())
{
layerModel.EventProperties.Update(layerModel, false);
return layerModel.EventProperties.MustDraw;
}
// Determine whether conditions are met
var conditionsMet = false; var conditionsMet = false;
switch (layerModel.Properties.ConditionType) switch (layerModel.Properties.ConditionType)
{ {
@ -26,11 +35,14 @@ namespace Artemis.Profiles.Layers.Conditions
break; break;
} }
// Update the event properties
layerModel.EventProperties.Update(layerModel, conditionsMet); layerModel.EventProperties.Update(layerModel, conditionsMet);
// If conditions are met trigger the event, this won't do anything if the event isn't ready to be triggered yet
if (conditionsMet) if (conditionsMet)
layerModel.EventProperties.TriggerEvent(layerModel); layerModel.EventProperties.TriggerEvent(layerModel);
// Return the event's MustDraw
return layerModel.EventProperties.MustDraw; return layerModel.EventProperties.MustDraw;
} }
} }

View File

@ -1,4 +1,5 @@
using System; using System;
using System.Timers;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace Artemis.Profiles.Layers.Models namespace Artemis.Profiles.Layers.Models
@ -10,7 +11,7 @@ namespace Artemis.Profiles.Layers.Models
public TimeSpan TriggerDelay { get; set; } public TimeSpan TriggerDelay { get; set; }
[JsonIgnore] [JsonIgnore]
public bool CanTrigger { get; set; } public bool CanTrigger { get; set; } = true;
[JsonIgnore] [JsonIgnore]
public DateTime EventTriggerTime { get; set; } public DateTime EventTriggerTime { get; set; }
@ -18,30 +19,46 @@ namespace Artemis.Profiles.Layers.Models
[JsonIgnore] [JsonIgnore]
public bool MustDraw { get; set; } public bool MustDraw { get; set; }
public DateTime EventCanTriggerTime { get; set; }
/// <summary> /// <summary>
/// Resets the event's properties and triggers it /// If possible, triggers the event
/// </summary> /// </summary>
public virtual void TriggerEvent(LayerModel layer) public virtual void TriggerEvent(LayerModel layer)
{ {
if (!CanTrigger) if (!CanTrigger)
return; return;
// Don't allow any more triggering regardless of what happens next
CanTrigger = false;
// If there is a trigger delay, stop here and await that delay
if (TriggerDelay > TimeSpan.Zero) if (TriggerDelay > TimeSpan.Zero)
{ {
if (EventCanTriggerTime == DateTime.MinValue) var timer = new Timer(TriggerDelay.TotalMilliseconds) {AutoReset = false};
EventCanTriggerTime = DateTime.Now; timer.Elapsed += (sender, args) =>
{
HardTrigger(layer);
timer.Dispose();
};
timer.Start();
if (DateTime.Now - EventCanTriggerTime < TriggerDelay) return;
return;
EventCanTriggerTime = DateTime.MinValue;
} }
CanTrigger = false; // Trigger the event
HardTrigger(layer);
}
/// <summary>
/// Instantly trigger the event regardless of current state
/// </summary>
/// <param name="layer"></param>
public void HardTrigger(LayerModel layer)
{
MustDraw = true; MustDraw = true;
CanTrigger = false;
EventTriggerTime = DateTime.Now; EventTriggerTime = DateTime.Now;
// Reset the animation in case it didn't finish before
layer.AnimationProgress = 0.0; layer.AnimationProgress = 0.0;
} }
@ -60,7 +77,7 @@ namespace Artemis.Profiles.Layers.Models
return DateTime.Now - EventTriggerTime > Length; return DateTime.Now - EventTriggerTime > Length;
} }
if (ExpirationType == ExpirationType.Animation) if (ExpirationType == ExpirationType.Animation)
return (layer.LayerAnimation == null) || layer.LayerAnimation.MustExpire(layer); return layer.LayerAnimation == null || layer.LayerAnimation.MustExpire(layer);
return true; return true;
} }
@ -68,24 +85,17 @@ namespace Artemis.Profiles.Layers.Models
// Called every frame, if parent conditions met. // Called every frame, if parent conditions met.
public void Update(LayerModel layerModel, bool conditionsMet) public void Update(LayerModel layerModel, bool conditionsMet)
{ {
if (EventCanTriggerTime > DateTime.MinValue && (DateTime.Now - EventCanTriggerTime > TriggerDelay)) // If the event isn't finished yet just keep going
{ if (MustDraw && !MustStop(layerModel))
CanTrigger = true;
TriggerEvent(layerModel);
return; return;
}
if (MustDraw && MustStop(layerModel)) // Otherwise make sure MustDraw is false
MustDraw = false; MustDraw = false;
// If the conditions aren't met and the event has finished it can be triggered again
if (!conditionsMet) if (!conditionsMet)
CanTrigger = true; CanTrigger = true;
} }
protected bool DelayExpired()
{
return EventCanTriggerTime > DateTime.MinValue && DateTime.Now - EventCanTriggerTime >= TriggerDelay;
}
} }
public enum ExpirationType public enum ExpirationType
@ -93,4 +103,4 @@ namespace Artemis.Profiles.Layers.Models
Time, Time,
Animation Animation
} }
} }

View File

@ -7,7 +7,7 @@ namespace Artemis.Profiles.Layers.Models
{ {
public override void TriggerEvent(LayerModel layer) public override void TriggerEvent(LayerModel layer)
{ {
if (CanTrigger && DelayExpired()) if (CanTrigger)
{ {
if (layer.GifImage != null) if (layer.GifImage != null)
layer.GifImage.CurrentFrame = 0; layer.GifImage.CurrentFrame = 0;
@ -18,12 +18,10 @@ namespace Artemis.Profiles.Layers.Models
public override bool MustStop(LayerModel layer) public override bool MustStop(LayerModel layer)
{ {
if (ExpirationType != ExpirationType.Animation) if (layer.LayerType is KeyboardGifType && ExpirationType == ExpirationType.Animation)
return base.MustStop(layer);
if (layer.LayerType is KeyboardGifType)
return layer.GifImage?.CurrentFrame >= layer.GifImage?.FrameCount - 1; return layer.GifImage?.CurrentFrame >= layer.GifImage?.FrameCount - 1;
return (layer.LayerAnimation == null) || layer.LayerAnimation.MustExpire(layer);
return base.MustStop(layer);
} }
} }
} }

View File

@ -2,6 +2,7 @@
using System.Windows.Forms; using System.Windows.Forms;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models; using Artemis.Models;
using Artemis.Profiles.Layers.Conditions;
using MahApps.Metro.Controls; using MahApps.Metro.Controls;
namespace Artemis.Profiles.Layers.Models namespace Artemis.Profiles.Layers.Models
@ -33,39 +34,30 @@ namespace Artemis.Profiles.Layers.Models
{ {
Unregister(); Unregister();
// Bind EnableHeldDown or DisableHeldDOwn if (layerModel.IsEvent)
if (ToggleType == ToggleType.EnableHeldDown || ToggleType == ToggleType.DisableHeldDown) RegisterEvent(layerModel, index);
else if (ToggleType == ToggleType.EnableHeldDown || ToggleType == ToggleType.DisableHeldDown)
RegisterToggle(layerModel, index);
else
RegisterRegular(layerModel, index);
}
private void RegisterEvent(LayerModel layerModel, int index)
{
Action action = () =>
{ {
Action downAction = null; layerModel.EventProperties.TriggerEvent(layerModel);
Action upAction = null; };
switch (ToggleType) // Either bind HotKey or mouse buttons depending on what isn't null
{ if (HotKey != null)
case ToggleType.EnableHeldDown: _downKeybind = new KeybindModel($"{layerModel.GetHashCode()}-{layerModel.Name}-{index}-down", HotKey, PressType.Down, action);
downAction = () => layerModel.RenderAllowed = true; else if (MouseButtons != null)
upAction = () => layerModel.RenderAllowed = false; _downKeybind = new KeybindModel($"{layerModel.GetHashCode()}-{layerModel.Name}-{index}-down", MouseButtons.Value, PressType.Down, action);
break; KeybindManager.AddOrUpdate(_downKeybind);
case ToggleType.DisableHeldDown: }
downAction = () => layerModel.RenderAllowed = false;
upAction = () => layerModel.RenderAllowed = true;
break;
}
// Either bind HotKey or mouse buttons depending on what isn't null
if (HotKey != null)
{
_downKeybind = new KeybindModel($"{layerModel.GetHashCode()}-{layerModel.Name}-{index}-down", HotKey, PressType.Down, downAction);
_upKeybind = new KeybindModel($"{layerModel.GetHashCode()}-{layerModel.Name}-{index}-up", HotKey, PressType.Up, upAction);
}
else if (MouseButtons != null)
{
_downKeybind = new KeybindModel($"{layerModel.GetHashCode()}-{layerModel.Name}-{index}-down", MouseButtons.Value, PressType.Down, downAction);
_upKeybind = new KeybindModel($"{layerModel.GetHashCode()}-{layerModel.Name}-{index}-up", MouseButtons.Value, PressType.Up, upAction);
}
KeybindManager.AddOrUpdate(_downKeybind);
KeybindManager.AddOrUpdate(_upKeybind);
return;
}
private void RegisterRegular(LayerModel layerModel, int index)
{
// Bind Enable, Disable or Toggle // Bind Enable, Disable or Toggle
Action action = null; Action action = null;
switch (ToggleType) switch (ToggleType)
@ -88,6 +80,38 @@ namespace Artemis.Profiles.Layers.Models
_downKeybind = new KeybindModel($"{layerModel.GetHashCode()}-{layerModel.Name}-{index}-down", MouseButtons.Value, PressType.Down, action); _downKeybind = new KeybindModel($"{layerModel.GetHashCode()}-{layerModel.Name}-{index}-down", MouseButtons.Value, PressType.Down, action);
KeybindManager.AddOrUpdate(_downKeybind); KeybindManager.AddOrUpdate(_downKeybind);
} }
private void RegisterToggle(LayerModel layerModel, int index)
{
Action downAction = null;
Action upAction = null;
switch (ToggleType)
{
case ToggleType.EnableHeldDown:
downAction = () => layerModel.RenderAllowed = true;
upAction = () => layerModel.RenderAllowed = false;
break;
case ToggleType.DisableHeldDown:
downAction = () => layerModel.RenderAllowed = false;
upAction = () => layerModel.RenderAllowed = true;
break;
}
// Either bind HotKey or mouse buttons depending on what isn't null
if (HotKey != null)
{
_downKeybind = new KeybindModel($"{layerModel.GetHashCode()}-{layerModel.Name}-{index}-down", HotKey, PressType.Down, downAction);
_upKeybind = new KeybindModel($"{layerModel.GetHashCode()}-{layerModel.Name}-{index}-up", HotKey, PressType.Up, upAction);
}
else if (MouseButtons != null)
{
_downKeybind = new KeybindModel($"{layerModel.GetHashCode()}-{layerModel.Name}-{index}-down", MouseButtons.Value, PressType.Down, downAction);
_upKeybind = new KeybindModel($"{layerModel.GetHashCode()}-{layerModel.Name}-{index}-up", MouseButtons.Value, PressType.Up, upAction);
}
KeybindManager.AddOrUpdate(_downKeybind);
KeybindManager.AddOrUpdate(_upKeybind);
return;
}
} }
public enum ToggleType public enum ToggleType

View File

@ -12,7 +12,6 @@ using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Models; using Artemis.Profiles.Layers.Models;
using Artemis.Properties; using Artemis.Properties;
using Artemis.Utilities; using Artemis.Utilities;
using Artemis.Utilities.Keyboard;
using Artemis.ViewModels; using Artemis.ViewModels;
using Artemis.ViewModels.Profiles; using Artemis.ViewModels.Profiles;
@ -30,7 +29,7 @@ namespace Artemis.Profiles.Layers.Types.KeyPress
_deviceManager = deviceManager; _deviceManager = deviceManager;
_keyPressLayers = new List<LayerModel>(); _keyPressLayers = new List<LayerModel>();
KeyboardHook.KeyDownCallback += KeyboardHookOnKeyDownCallback; InputHook.KeyDownCallback += KeyboardHookOnKeyDownCallback;
} }
public RadialGradientBrush TempBrush { get; set; } public RadialGradientBrush TempBrush { get; set; }

View File

@ -5,7 +5,7 @@ using Artemis.Events;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Profiles.Lua.Modules.Events; using Artemis.Profiles.Lua.Modules.Events;
using Artemis.Profiles.Lua.Wrappers; using Artemis.Profiles.Lua.Wrappers;
using Artemis.Utilities.Keyboard; using Artemis.Utilities;
using MoonSharp.Interpreter; using MoonSharp.Interpreter;
using NLog; using NLog;
@ -23,7 +23,7 @@ namespace Artemis.Profiles.Lua.Modules
_profileModel = luaManager.ProfileModel; _profileModel = luaManager.ProfileModel;
_profileModel.OnDeviceUpdatedEvent += OnDeviceUpdatedEvent; _profileModel.OnDeviceUpdatedEvent += OnDeviceUpdatedEvent;
_profileModel.OnDeviceDrawnEvent += OnDeviceDrawnEvent; _profileModel.OnDeviceDrawnEvent += OnDeviceDrawnEvent;
KeyboardHook.KeyDownCallback += KeyboardHookOnKeyDownCallback; InputHook.KeyDownCallback += KeyboardHookOnKeyDownCallback;
} }
public override string ModuleName => "Events"; public override string ModuleName => "Events";
@ -118,7 +118,7 @@ namespace Artemis.Profiles.Lua.Modules
{ {
_profileModel.OnDeviceUpdatedEvent -= OnDeviceUpdatedEvent; _profileModel.OnDeviceUpdatedEvent -= OnDeviceUpdatedEvent;
_profileModel.OnDeviceDrawnEvent -= OnDeviceDrawnEvent; _profileModel.OnDeviceDrawnEvent -= OnDeviceDrawnEvent;
KeyboardHook.KeyDownCallback -= KeyboardHookOnKeyDownCallback; InputHook.KeyDownCallback -= KeyboardHookOnKeyDownCallback;
} }
#endregion #endregion

View File

@ -29,59 +29,22 @@ namespace Artemis.Utilities.DataReaders
#region Logitech #region Logitech
private const string LogitechPath = @"C:\Program Files\Logitech Gaming Software\SDK\LED\x64\"; private static readonly string LogitechPath = @"C:\Program Files\Logitech Gaming Software\SDK\LED\x64\";
private static readonly string DllPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Artemis\dll";
public static bool RestoreLogitechDll()
{
if (!DllPlaced())
return false;
try
{
// Get rid of our own DLL
File.Delete(LogitechPath + @"\LogitechLed.dll");
// Restore the backup
if (File.Exists(LogitechPath + @"\LogitechLed.dll.bak"))
File.Copy(LogitechPath + @"\LogitechLed.dll.bak", LogitechPath + @"\LogitechLed.dll");
File.Delete(LogitechPath + @"\artemis.txt");
return true;
}
catch (Exception)
{
return false;
}
}
public static void PlaceLogitechDll() public static void PlaceLogitechDll()
{ {
if (DllPlaced())
return;
try try
{ {
// Create directory structure, just in case // Change the registry key to point to the fake DLL
Directory.CreateDirectory(LogitechPath + @""); var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Classes\CLSID\{a6519e67-7632-4375-afdf-caa889744403}\ServerBinary", true);
key?.SetValue(null, DllPath + @"\LogitechLed.dll");
// Backup the existing DLL
if (File.Exists(LogitechPath + @"\LogitechLed.dll")) // Make sure the fake DLL is in place
{ if (!Directory.Exists(DllPath))
if (!File.Exists(LogitechPath + @"\LogitechLed.dll.bak")) Directory.CreateDirectory(DllPath);
File.Move(LogitechPath + @"\LogitechLed.dll", LogitechPath + @"\LogitechLed.dll.bak"); if (!File.Exists(DllPath + @"\LogitechLed.dll"))
} File.WriteAllBytes(DllPath + @"\LogitechLED.dll", Resources.LogitechLED);
// Copy our own DLL in place
File.WriteAllBytes(LogitechPath + @"\LogitechLED.dll", Resources.LogitechLED);
// A token to show the file is placed
File.Create(LogitechPath + @"\artemis.txt");
// If the user doesn't have a Logitech device, the CLSID will be missing
// and we should create it ourselves.
if (!RegistryKeyPlaced())
PlaceRegistryKey();
} }
catch (Exception e) catch (Exception e)
{ {
@ -89,32 +52,13 @@ namespace Artemis.Utilities.DataReaders
} }
} }
public static bool DllPlaced() public static void RestoreLogitechDll()
{ {
if (!Directory.Exists(LogitechPath + @"")) // Change the registry key to point to the real DLL
return false; var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Classes\CLSID\{a6519e67-7632-4375-afdf-caa889744403}\ServerBinary", true);
if (!RegistryKeyPlaced())
return false;
return File.Exists(LogitechPath + @"\artemis.txt");
}
private static bool RegistryKeyPlaced()
{
var key = Registry
.LocalMachine.OpenSubKey(
@"SOFTWARE\Classes\CLSID\{a6519e67-7632-4375-afdf-caa889744403}\ServerBinary");
return key != null;
}
private static void PlaceRegistryKey()
{
var key = Registry
.LocalMachine.OpenSubKey(
@"SOFTWARE\Classes\CLSID\{a6519e67-7632-4375-afdf-caa889744403}\ServerBinary", true);
key?.SetValue(null, LogitechPath + @"\LogitechLed.dll"); key?.SetValue(null, LogitechPath + @"\LogitechLed.dll");
} }
#endregion #endregion
} }
} }

View File

@ -4,9 +4,9 @@ using System.Windows.Forms;
using Gma.System.MouseKeyHook; using Gma.System.MouseKeyHook;
using NLog; using NLog;
namespace Artemis.Utilities.Keyboard namespace Artemis.Utilities
{ {
public static class KeyboardHook public static class InputHook
{ {
public delegate void KeyCallbackHandler(KeyEventArgs e); public delegate void KeyCallbackHandler(KeyEventArgs e);

View File

@ -9,6 +9,7 @@ namespace Artemis.ViewModels.Profiles
public sealed class LayerKeybindViewModel : Screen public sealed class LayerKeybindViewModel : Screen
{ {
private readonly LayerEditorViewModel _editorViewModel; private readonly LayerEditorViewModel _editorViewModel;
private bool _canToggleType;
private HotKey _hotKey; private HotKey _hotKey;
private MouseButtons _mouseButtons; private MouseButtons _mouseButtons;
@ -20,30 +21,20 @@ namespace Artemis.ViewModels.Profiles
LayerKeybindModel = layerKeybindModel; LayerKeybindModel = layerKeybindModel;
PropertyChanged += MapViewToModel; PropertyChanged += MapViewToModel;
editorViewModel.PropertyChanged += EditorViewModelOnPropertyChanged;
MapModelToView(); MapModelToView();
} }
private void MapViewToModel(object sender, PropertyChangedEventArgs e) public bool CanToggleType
{ {
if (e.PropertyName == "MouseButtonsVisible" || e.PropertyName == "HotkeyVisible") get { return _canToggleType; }
return; set
{
if (MouseButtonsVisible) if (value == _canToggleType)
SetMouseBind(); return;
else _canToggleType = value;
SetKeyBind(); NotifyOfPropertyChange(() => CanToggleType);
} }
private void MapModelToView()
{
PropertyChanged -= MapViewToModel;
if (LayerKeybindModel.MouseButtons != null)
MouseButtons = LayerKeybindModel.MouseButtons.Value;
HotKey = LayerKeybindModel.HotKey;
ToggleType = LayerKeybindModel.ToggleType;
PropertyChanged += MapViewToModel;
} }
public LayerKeybindModel LayerKeybindModel { get; set; } public LayerKeybindModel LayerKeybindModel { get; set; }
@ -88,6 +79,48 @@ namespace Artemis.ViewModels.Profiles
} }
} }
/// <summary>
/// Responds to the EventPropertiesViewModel being changed
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void EditorViewModelOnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName != "EventPropertiesViewModel")
return;
if (_editorViewModel.ProposedLayer.IsEvent)
{
CanToggleType = false;
ToggleType = ToggleType.Enable;
}
else
CanToggleType = true;
}
private void MapViewToModel(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "MouseButtonsVisible" || e.PropertyName == "HotkeyVisible")
return;
if (MouseButtonsVisible)
SetMouseBind();
else
SetKeyBind();
}
private void MapModelToView()
{
PropertyChanged -= MapViewToModel;
if (LayerKeybindModel.MouseButtons != null)
MouseButtons = LayerKeybindModel.MouseButtons.Value;
HotKey = LayerKeybindModel.HotKey;
ToggleType = LayerKeybindModel.ToggleType;
PropertyChanged += MapViewToModel;
}
public void ToggleBindType() public void ToggleBindType()
{ {
if (MouseButtonsVisible) if (MouseButtonsVisible)

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:sys="clr-namespace:System;assembly=mscorlib" xmlns:sys="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d" mc:Ignorable="d"
Title="Artemis | Edit Layer" Height="600" Width="1100" Title="Artemis | Edit Layer" Height="640" Width="1100"
xmlns:cal="http://www.caliburnproject.org" xmlns:cal="http://www.caliburnproject.org"
xmlns:converters="clr-namespace:Artemis.Utilities.Converters" xmlns:converters="clr-namespace:Artemis.Utilities.Converters"
xmlns:models="clr-namespace:Artemis.Profiles.Layers.Models" xmlns:models="clr-namespace:Artemis.Profiles.Layers.Models"
@ -96,7 +96,7 @@
<ListBox Height="138" x:Name="LayerConditionVms" ScrollViewer.VerticalScrollBarVisibility="Visible"> <ListBox Height="138" x:Name="LayerConditionVms" ScrollViewer.VerticalScrollBarVisibility="Visible">
<ListBox.Template> <ListBox.Template>
<ControlTemplate> <ControlTemplate>
<ScrollViewer> <ScrollViewer HorizontalScrollBarVisibility="Disabled">
<ItemsPresenter /> <ItemsPresenter />
</ScrollViewer> </ScrollViewer>
</ControlTemplate> </ControlTemplate>

View File

@ -32,7 +32,7 @@
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<!-- Type --> <!-- Type -->
<ComboBox Grid.Column="0" ItemsSource="{Binding Source={StaticResource ToggleTypeEnumValues}}" SelectedItem="{Binding Path=ToggleType}"> <ComboBox Grid.Column="0" ItemsSource="{Binding Source={StaticResource ToggleTypeEnumValues}}" SelectedItem="{Binding Path=ToggleType}" IsEnabled="{Binding Path=CanToggleType}">
<ComboBox.ItemTemplate> <ComboBox.ItemTemplate>
<DataTemplate> <DataTemplate>
<TextBlock Text="{Binding Converter={StaticResource HEnumDescriptionConverter}}" /> <TextBlock Text="{Binding Converter={StaticResource HEnumDescriptionConverter}}" />