From 32a651ffec76634ce850deb77a5445495cd1b651 Mon Sep 17 00:00:00 2001 From: SpoinkyNL Date: Wed, 27 Apr 2016 19:11:56 +0200 Subject: [PATCH] Implemented keyboard preview, added logging --- Artemis/Artemis/Artemis.csproj | 11 + Artemis/Artemis/Managers/EffectManager.cs | 77 +- Artemis/Artemis/Managers/KeyboardManager.cs | 20 +- Artemis/Artemis/Managers/MainManager.cs | 41 +- Artemis/Artemis/Models/GameModel.cs | 5 +- Artemis/Artemis/Models/Profiles/LayerModel.cs | 14 +- .../Artemis/Models/Profiles/ProfileModel.cs | 4 +- .../Modules/Effects/Debug/DebugEffectModel.cs | 1 + .../ProfilePreview/ProfilePreviewModel.cs | 62 + .../Games/CounterStrike/CounterStrikeModel.cs | 5 +- .../CounterStrike/CounterStrikeViewModel.cs | 22 +- .../Modules/Games/Dota2/Dota2DataModel.cs | 2 +- .../Artemis/Modules/Games/Dota2/Dota2Model.cs | 114 +- .../Modules/Games/Dota2/Dota2ViewModel.cs | 52 +- .../Games/RocketLeague/RocketLeagueModel.cs | 5 +- .../RocketLeague/RocketLeagueViewModel.cs | 27 +- .../Games/TheDivision/TheDivisionModel.cs | 5 +- .../Games/TheDivision/TheDivisionViewModel.cs | 15 +- .../Modules/Games/Witcher3/Witcher3Model.cs | 5 +- .../Games/Witcher3/Witcher3ViewModel.cs | 9 +- Artemis/Artemis/NLog.config | 18 + Artemis/Artemis/NLog.xsd | 2601 +++++++++++++++++ .../ViewModels/Abstract/GameViewModel.cs | 82 +- .../ViewModels/ProfileEditorViewModel.cs | 8 +- Artemis/Artemis/packages.config | 3 + 25 files changed, 3015 insertions(+), 193 deletions(-) create mode 100644 Artemis/Artemis/Modules/Effects/ProfilePreview/ProfilePreviewModel.cs create mode 100644 Artemis/Artemis/NLog.config create mode 100644 Artemis/Artemis/NLog.xsd diff --git a/Artemis/Artemis/Artemis.csproj b/Artemis/Artemis/Artemis.csproj index a0da17063..cc6511ec3 100644 --- a/Artemis/Artemis/Artemis.csproj +++ b/Artemis/Artemis/Artemis.csproj @@ -175,6 +175,10 @@ ..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll True + + ..\packages\NLog.4.3.2\lib\net45\NLog.dll + True + ..\packages\SharpDX.3.0.2\lib\net45\SharpDX.dll True @@ -299,6 +303,7 @@ + TypeWave.settings @@ -529,6 +534,12 @@ SettingsSingleFileGenerator VolumeDisplay.Designer.cs + + Always + + + Designer + diff --git a/Artemis/Artemis/Managers/EffectManager.cs b/Artemis/Artemis/Managers/EffectManager.cs index f7b639406..5c81fc0ec 100644 --- a/Artemis/Artemis/Managers/EffectManager.cs +++ b/Artemis/Artemis/Managers/EffectManager.cs @@ -1,29 +1,45 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading; using Artemis.Events; using Artemis.Models; +using Artemis.Modules.Effects.ProfilePreview; using Artemis.Settings; using Caliburn.Micro; +using NLog; +using LogManager = NLog.LogManager; namespace Artemis.Managers { public class EffectManager { + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); private readonly IEventAggregator _events; private readonly MainManager _mainManager; - private bool _clearing; - private EffectModel _pauseEffect; private EffectModel _activeEffect; + private bool _clearing; + public EffectModel PauseEffect { get; set; } public EffectManager(MainManager mainManager, IEventAggregator events) { + Logger.Info("Intializing EffectManager"); _mainManager = mainManager; _events = events; EffectModels = new List(); + ProfilePreviewModel = new ProfilePreviewModel(_mainManager); + Logger.Info("Intialized EffectManager"); } + /// + /// Used by ViewModels to show a preview of the profile currently being edited + /// + public ProfilePreviewModel ProfilePreviewModel { get; set; } + + /// + /// Holds all the effects the program has + /// public List EffectModels { get; set; } public EffectModel ActiveEffect @@ -36,11 +52,17 @@ namespace Artemis.Managers } } + /// + /// Returns all enabled overlays + /// public IEnumerable EnabledOverlays { get { return EffectModels.OfType().Where(o => o.Enabled); } } + /// + /// Returns all enabled games + /// public IEnumerable EnabledGames { get { return EffectModels.OfType().Where(g => g.Enabled); } @@ -52,13 +74,14 @@ namespace Artemis.Managers /// Whether enabling was successful or not. public EffectModel GetLastEffect() { + Logger.Debug("Getting last effect: {0}", General.Default.LastEffect); if (General.Default.LastEffect == null) return null; var effect = EffectModels.FirstOrDefault(e => e.Name == General.Default.LastEffect); // Fall back to the first effect found, in case settings are messed up - return effect ?? EffectModels.First(); + return effect; } /// @@ -81,6 +104,7 @@ namespace Artemis.Managers if (effectModel.Name == ActiveEffect.Name && !force) return; + Logger.Debug("Changing effect to: {0}, force: {1}", effectModel?.Name, force); // If the main manager is running, pause it and safely change the effect if (_mainManager.Running) { @@ -94,27 +118,40 @@ namespace Artemis.Managers private void ChangeEffectWithPause(EffectModel effectModel) { - if (_pauseEffect != null) - return; + var tryCount = 0; + while (PauseEffect != null) + { + Thread.Sleep(100); + tryCount++; + if (tryCount > 20) + throw new Exception("Couldn't change effect before the time expired"); + } - _pauseEffect = effectModel; + // Don't interrupt an ongoing effect change + if (PauseEffect != null) + { + Logger.Debug("Change effect with pause cancelled"); + return; + } + Logger.Debug("Changing effect with pause: {0}", effectModel?.Name); + + PauseEffect = effectModel; _mainManager.Pause(); _mainManager.PauseCallback += ChangeEffectPauseCallback; } private void ChangeEffectPauseCallback() { + _mainManager.PauseCallback -= ChangeEffectPauseCallback; + // Change effect logic ActiveEffect?.Dispose(); - ActiveEffect = _pauseEffect; + ActiveEffect = PauseEffect; ActiveEffect.Enable(); - // Let the ViewModels know - //_events.PublishOnUIThread(new ActiveEffectChanged(ActiveEffect.Name)); - _mainManager.Unpause(); - _pauseEffect = null; + PauseEffect = null; if (ActiveEffect is GameModel) return; @@ -122,6 +159,8 @@ namespace Artemis.Managers // Non-game effects are stored as the new LastEffect. General.Default.LastEffect = ActiveEffect.Name; General.Default.Save(); + + Logger.Debug("Finishing change effect with pause"); } /// @@ -133,29 +172,36 @@ namespace Artemis.Managers return; // Don't mess with the ActiveEffect if in the process of changing the effect. - if (_pauseEffect != null) + if (PauseEffect != null) return; if (ActiveEffect == null) return; _clearing = true; - + Logger.Debug("Clearing active effect"); _mainManager.Pause(); _mainManager.PauseCallback += ClearEffectPauseCallback; } private void ClearEffectPauseCallback() { + _mainManager.PauseCallback -= ClearEffectPauseCallback; + if (PauseEffect != null) + { + Logger.Debug("Cancelling clearing effect"); + return; + } + ActiveEffect.Dispose(); ActiveEffect = null; General.Default.LastEffect = null; General.Default.Save(); - //_events.PublishOnUIThread(new ActiveEffectChanged("")); - _clearing = false; + + Logger.Debug("Finishing clearing active effect"); _mainManager.Unpause(); } @@ -165,6 +211,7 @@ namespace Artemis.Managers /// public void DisableGame(EffectModel activeEffect) { + Logger.Debug("Disabling game: {0}", activeEffect?.Name); if (GetLastEffect() == null) ClearEffect(); else diff --git a/Artemis/Artemis/Managers/KeyboardManager.cs b/Artemis/Artemis/Managers/KeyboardManager.cs index cc0463332..b298785f2 100644 --- a/Artemis/Artemis/Managers/KeyboardManager.cs +++ b/Artemis/Artemis/Managers/KeyboardManager.cs @@ -4,20 +4,25 @@ using Artemis.Events; using Artemis.KeyboardProviders; using Artemis.Settings; using Caliburn.Micro; +using NLog; +using LogManager = NLog.LogManager; namespace Artemis.Managers { public class KeyboardManager { + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); private readonly IEventAggregator _events; private readonly MainManager _mainManager; private KeyboardProvider _activeKeyboard; public KeyboardManager(MainManager mainManager, IEventAggregator events) { + Logger.Info("Intializing KeyboardManager"); _mainManager = mainManager; _events = events; KeyboardProviders = ProviderHelper.GetKeyboardProviders(); + Logger.Info("Intialized KeyboardManager"); } public List KeyboardProviders { get; set; } @@ -33,11 +38,14 @@ namespace Artemis.Managers } } + public bool CanDisable { get; set; } + /// /// Enables the last keyboard according to the settings file /// public void EnableLastKeyboard() { + Logger.Debug("Enabling last keyboard: {0}", General.Default.LastKeyboard); if (General.Default.LastKeyboard == null) return; if (General.Default.LastKeyboard == "") @@ -53,6 +61,7 @@ namespace Artemis.Managers /// public void EnableKeyboard(KeyboardProvider keyboardProvider) { + Logger.Debug("Enabling keyboard: {0}", keyboardProvider?.Name); ReleaseActiveKeyboard(); if (keyboardProvider == null) @@ -69,22 +78,25 @@ namespace Artemis.Managers return; } + CanDisable = false; ActiveKeyboard = keyboardProvider; - ActiveKeyboard.Enable(); + keyboardProvider.Enable(); General.Default.LastKeyboard = ActiveKeyboard.Name; General.Default.Save(); + CanDisable = true; } /// - /// Releases the active keyboard + /// Releases the active keyboard, if CanDisable is true /// public void ReleaseActiveKeyboard() { - if (ActiveKeyboard == null) + if (ActiveKeyboard == null || !CanDisable) return; ActiveKeyboard.Disable(); + Logger.Debug("Released keyboard: {0}", ActiveKeyboard?.Name); ActiveKeyboard = null; } @@ -94,12 +106,14 @@ namespace Artemis.Managers /// public void ChangeKeyboard(KeyboardProvider keyboardProvider) { + Logger.Debug("Changing active keyboard"); if (keyboardProvider == ActiveKeyboard) return; General.Default.LastKeyboard = keyboardProvider?.Name; General.Default.Save(); + Logger.Debug("Restarting for keyboard change"); _mainManager.Restart(); } } diff --git a/Artemis/Artemis/Managers/MainManager.cs b/Artemis/Artemis/Managers/MainManager.cs index 381795d2e..88351ed71 100644 --- a/Artemis/Artemis/Managers/MainManager.cs +++ b/Artemis/Artemis/Managers/MainManager.cs @@ -9,6 +9,8 @@ using Artemis.Utilities.GameState; using Artemis.Utilities.Keyboard; using Artemis.Utilities.LogitechDll; using Caliburn.Micro; +using NLog; +using LogManager = NLog.LogManager; namespace Artemis.Managers { @@ -16,12 +18,16 @@ namespace Artemis.Managers { public delegate void PauseCallbackHandler(); + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + private readonly int _fps; private bool _paused; private bool _restarting; public MainManager(IEventAggregator events, MetroDialogService dialogService) { + Logger.Info("Intializing MainManager"); + Events = events; DialogService = dialogService; @@ -52,6 +58,8 @@ namespace Artemis.Managers // Start the named pipe PipeServer = new PipeServer(); PipeServer.Start("artemis"); + + Logger.Info("Intialized MainManager"); } public PipeServer PipeServer { get; set; } @@ -80,6 +88,7 @@ namespace Artemis.Managers /// Whether starting was successful or not public bool Start(EffectModel effect = null) { + Logger.Debug("Starting MainManager"); // Can't take control when not enabled if (!ProgramEnabled || UpdateWorker.CancellationPending || UpdateWorker.IsBusy || _paused) return false; @@ -109,6 +118,7 @@ namespace Artemis.Managers /// public void Stop() { + Logger.Debug("Stopping MainManager"); if (!Running || UpdateWorker.CancellationPending || _paused) return; @@ -123,6 +133,7 @@ namespace Artemis.Managers KeyboardManager.ReleaseActiveKeyboard(); Running = false; + Logger.Debug("Stopped MainManager"); if (e.Error != null || !_restarting) return; @@ -135,6 +146,7 @@ namespace Artemis.Managers if (!Running || UpdateWorker.CancellationPending || _paused) return; + Logger.Debug("Pausing MainManager"); _paused = true; } @@ -143,23 +155,26 @@ namespace Artemis.Managers if (!_paused) return; + Logger.Debug("Unpausing MainManager"); _paused = false; - PauseCallback = null; } public void Shutdown() { + Logger.Debug("Shutting down MainManager"); Stop(); ProcessWorker.CancelAsync(); ProcessWorker.CancelAsync(); GameStateWebServer.Stop(); - //NamedPipeServer.StopServer(); + PipeServer.Stop(); } public void Restart() { if (_restarting) return; + + Logger.Debug("Restarting MainManager"); if (!Running) { Start(); @@ -175,6 +190,7 @@ namespace Artemis.Managers /// public void EnableProgram() { + Logger.Debug("Enabling program"); ProgramEnabled = true; Start(EffectManager.GetLastEffect()); Events.PublishOnUIThread(new ToggleEnabled(ProgramEnabled)); @@ -185,6 +201,7 @@ namespace Artemis.Managers /// public void DisableProgram() { + Logger.Debug("Disabling program"); Stop(); ProgramEnabled = false; Events.PublishOnUIThread(new ToggleEnabled(ProgramEnabled)); @@ -209,7 +226,15 @@ namespace Artemis.Managers if (KeyboardManager.ActiveKeyboard == null || EffectManager.ActiveEffect == null) { Thread.Sleep(1000/_fps); - Stop(); + Logger.Debug("No active effect/keyboard, stopping"); + + if (EffectManager.PauseEffect != null) + { + PauseCallback?.Invoke(); + Thread.Sleep(1000/_fps); + } + else + Stop(); continue; } @@ -257,8 +282,11 @@ namespace Artemis.Managers private void BackgroundWorkerExceptionCatcher(object sender, RunWorkerCompletedEventArgs e) { - if (e.Error != null) - throw e.Error; + if (e.Error == null) + return; + + Logger.Error(e.Error, "Exception in the BackgroundWorker"); + throw e.Error; } private void ProcessWorker_DoWork(object sender, DoWorkEventArgs e) @@ -285,7 +313,8 @@ namespace Artemis.Managers // Look for running games, stopping on the first one that's found. var newGame = EffectManager.EnabledGames - .FirstOrDefault(g => runningProcesses.Any(p => p.ProcessName == g.ProcessName && p.HasExited == false)); + .FirstOrDefault( + g => runningProcesses.Any(p => p.ProcessName == g.ProcessName && p.HasExited == false)); // If it's not already enabled, do so. if (newGame != null && EffectManager.ActiveEffect != newGame) diff --git a/Artemis/Artemis/Models/GameModel.cs b/Artemis/Artemis/Models/GameModel.cs index 8500747fc..5e4fcebd8 100644 --- a/Artemis/Artemis/Models/GameModel.cs +++ b/Artemis/Artemis/Models/GameModel.cs @@ -1,18 +1,21 @@ using Artemis.Managers; using Artemis.Models.Interfaces; using Artemis.Models.Profiles; +using Artemis.Modules.Games.Witcher3; namespace Artemis.Models { public abstract class GameModel : EffectModel { + public GameSettings Settings { get; set; } public bool Enabled { get; set; } public string ProcessName { get; set; } public IGameDataModel GameDataModel { get; set; } public ProfileModel Profile { get; set; } - protected GameModel(MainManager mainManager) : base(mainManager) + protected GameModel(MainManager mainManager, GameSettings settings) : base(mainManager) { + Settings = settings; } } } \ No newline at end of file diff --git a/Artemis/Artemis/Models/Profiles/LayerModel.cs b/Artemis/Artemis/Models/Profiles/LayerModel.cs index 23dc597b9..bea0e4f51 100644 --- a/Artemis/Artemis/Models/Profiles/LayerModel.cs +++ b/Artemis/Artemis/Models/Profiles/LayerModel.cs @@ -64,10 +64,12 @@ namespace Artemis.Models.Profiles _mustDraw = false; } - public void Draw(IGameDataModel dataModel, DrawingContext c) + public void Draw(IGameDataModel dataModel, DrawingContext c, bool preview = false) { - if (!ConditionsMet(dataModel)) - return; + // Conditions aren't checked during a preview because there is no game data to base them on + if (!preview) + if (!ConditionsMet(dataModel)) + return; if (LayerType == LayerType.Folder) foreach (var layerModel in Children.OrderByDescending(l => l.Order)) @@ -82,7 +84,7 @@ namespace Artemis.Models.Profiles _drawer.UpdateHeadset(); } - public void Update(IGameDataModel dataModel) + public void Update(IGameDataModel dataModel, bool preview = false) { if (LayerType == LayerType.Folder) { @@ -92,6 +94,10 @@ namespace Artemis.Models.Profiles } GeneralHelpers.CopyProperties(CalcProps, UserProps); + + // Dynamic properties aren't applied during preview because there is no game data to base them on + if (preview) + return; foreach (var dynamicProperty in LayerProperties) dynamicProperty.ApplyProperty(dataModel, UserProps, CalcProps); } diff --git a/Artemis/Artemis/Models/Profiles/ProfileModel.cs b/Artemis/Artemis/Models/Profiles/ProfileModel.cs index 546dd1c37..27edc4e12 100644 --- a/Artemis/Artemis/Models/Profiles/ProfileModel.cs +++ b/Artemis/Artemis/Models/Profiles/ProfileModel.cs @@ -106,7 +106,7 @@ namespace Artemis.Models.Profiles Layers[i].Order = i; } - public Bitmap GenerateBitmap(Rect keyboardRect, IGameDataModel gameDataModel) + public Bitmap GenerateBitmap(Rect keyboardRect, IGameDataModel gameDataModel, bool preview = false) { Bitmap bitmap = null; DrawingVisual.Dispatcher.Invoke(delegate @@ -120,7 +120,7 @@ namespace Artemis.Models.Profiles // Draw the layers foreach (var layerModel in Layers.OrderByDescending(l => l.Order)) - layerModel.Draw(gameDataModel, c); + layerModel.Draw(gameDataModel, c, preview); // Remove the clip c.Pop(); diff --git a/Artemis/Artemis/Modules/Effects/Debug/DebugEffectModel.cs b/Artemis/Artemis/Modules/Effects/Debug/DebugEffectModel.cs index 034f96077..d8e6fc79f 100644 --- a/Artemis/Artemis/Modules/Effects/Debug/DebugEffectModel.cs +++ b/Artemis/Artemis/Modules/Effects/Debug/DebugEffectModel.cs @@ -7,6 +7,7 @@ using Artemis.Utilities.Keyboard; namespace Artemis.Modules.Effects.Debug { + // TODO: Remove internal class DebugEffectModel : EffectModel { public DebugEffectModel(MainManager mainManager, DebugEffectSettings settings) : base(mainManager) diff --git a/Artemis/Artemis/Modules/Effects/ProfilePreview/ProfilePreviewModel.cs b/Artemis/Artemis/Modules/Effects/ProfilePreview/ProfilePreviewModel.cs new file mode 100644 index 000000000..ece8fae49 --- /dev/null +++ b/Artemis/Artemis/Modules/Effects/ProfilePreview/ProfilePreviewModel.cs @@ -0,0 +1,62 @@ +using System.Drawing; +using Artemis.Managers; +using Artemis.Models; +using Artemis.Models.Interfaces; +using Artemis.Models.Profiles; + +namespace Artemis.Modules.Effects.ProfilePreview +{ + public class ProfilePreviewModel : EffectModel + { + private readonly ProfilePreviewDataModel _previewDataModel; + + public ProfilePreviewModel(MainManager mainManager) : base(mainManager) + { + Name = "Profile Preview"; + _previewDataModel = new ProfilePreviewDataModel(); + } + + public ProfileModel SelectedProfile { get; set; } + + public override void Dispose() + { + Initialized = false; + SelectedProfile = null; + } + + public override void Enable() + { + Initialized = true; + } + + public override void Update() + { + if (SelectedProfile == null) + return; + + foreach (var layerModel in SelectedProfile.Layers) + layerModel.Update(_previewDataModel, true); + } + + public override Bitmap GenerateBitmap() + { + var bitmap = MainManager.KeyboardManager.ActiveKeyboard.KeyboardBitmap(4); + + if (SelectedProfile == null) + return bitmap; + + var keyboardRect = MainManager.KeyboardManager.ActiveKeyboard.KeyboardRectangle(4); + var image = SelectedProfile.GenerateBitmap(keyboardRect, _previewDataModel, true); + + // Draw on top of everything else + using (var g = Graphics.FromImage(bitmap)) + g.DrawImage(image, 0, 0); + + return bitmap; + } + } + + public class ProfilePreviewDataModel : IGameDataModel + { + } +} \ No newline at end of file diff --git a/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrikeModel.cs b/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrikeModel.cs index 4bf2f6d78..304b71e5e 100644 --- a/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrikeModel.cs +++ b/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrikeModel.cs @@ -9,9 +9,8 @@ namespace Artemis.Modules.Games.CounterStrike { public class CounterStrikeModel : GameModel { - public CounterStrikeModel(MainManager mainManager, CounterStrikeSettings settings) : base(mainManager) + public CounterStrikeModel(MainManager mainManager, CounterStrikeSettings settings) : base(mainManager, settings) { - Settings = settings; Name = "CounterStrike"; ProcessName = "csgo"; Scale = 4; @@ -19,8 +18,6 @@ namespace Artemis.Modules.Games.CounterStrike Initialized = false; } - public CounterStrikeSettings Settings { get; set; } - public int Scale { get; set; } public override void Dispose() diff --git a/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrikeViewModel.cs b/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrikeViewModel.cs index 982bb1136..5d9188c1e 100644 --- a/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrikeViewModel.cs +++ b/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrikeViewModel.cs @@ -8,33 +8,15 @@ using Artemis.ViewModels.Abstract; namespace Artemis.Modules.Games.CounterStrike { - public class CounterStrikeViewModel : GameViewModel + public class CounterStrikeViewModel : GameViewModel { - public CounterStrikeViewModel(MainManager mainManager) + public CounterStrikeViewModel(MainManager mainManager) : base(mainManager, new CounterStrikeModel(mainManager, new CounterStrikeSettings())) { - MainManager = mainManager; - - // Settings are loaded from file by class - GameSettings = new CounterStrikeSettings(); - // Create effect model and add it to MainManager - GameModel = new CounterStrikeModel(mainManager, (CounterStrikeSettings) GameSettings); MainManager.EffectManager.EffectModels.Add(GameModel); PlaceConfigFile(); - - ProfileEditor = new ProfileEditorViewModel(MainManager, GameModel); - ProfileEditor.PropertyChanged += ProfileUpdater; - GameModel.Profile = ProfileEditor.SelectedProfile; } - private void ProfileUpdater(object sender, PropertyChangedEventArgs e) - { - if (e.PropertyName == "SelectedProfile") - GameModel.Profile = ProfileEditor.SelectedProfile; - } - - public ProfileEditorViewModel ProfileEditor { get; set; } - public static string Name => "CS:GO"; public string Content => "Counter-Strike: GO Content"; diff --git a/Artemis/Artemis/Modules/Games/Dota2/Dota2DataModel.cs b/Artemis/Artemis/Modules/Games/Dota2/Dota2DataModel.cs index 39bacb414..28299d535 100644 --- a/Artemis/Artemis/Modules/Games/Dota2/Dota2DataModel.cs +++ b/Artemis/Artemis/Modules/Games/Dota2/Dota2DataModel.cs @@ -1,6 +1,6 @@ namespace Artemis.Modules.Games.Dota2 { - class Dota2DataModel + public class Dota2DataModel { public class Rootobject { diff --git a/Artemis/Artemis/Modules/Games/Dota2/Dota2Model.cs b/Artemis/Artemis/Modules/Games/Dota2/Dota2Model.cs index fb7d07885..bd99b08c2 100644 --- a/Artemis/Artemis/Modules/Games/Dota2/Dota2Model.cs +++ b/Artemis/Artemis/Modules/Games/Dota2/Dota2Model.cs @@ -3,8 +3,6 @@ using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; using System.Linq; -using System.Windows.Forms.VisualStyles; -using System.Windows.Media; using Artemis.KeyboardProviders; using Artemis.Managers; using Artemis.Models; @@ -12,26 +10,26 @@ using Artemis.Utilities; using Artemis.Utilities.GameState; using Artemis.Utilities.Keyboard; using Newtonsoft.Json; -using Color = System.Drawing.Color; namespace Artemis.Modules.Games.Dota2 { internal class Dota2Model : GameModel { - private KeyboardRegion _keyPad; private KeyboardRegion _abilityKeys; + private KeyboardRegion _keyPad; private KeyboardRegion _topRow; - public Dota2Model(MainManager mainManager, Dota2Settings settings) : base(mainManager) + public Dota2Model(MainManager mainManager, Dota2Settings settings) : base(mainManager, settings) { - Settings = settings; Name = "Dota2"; ProcessName = "dota2"; + Settings = settings; Enabled = Settings.Enabled; Initialized = false; Scale = 4; } + public new Dota2Settings Settings { get; set; } public override void Dispose() { @@ -72,7 +70,7 @@ namespace Artemis.Modules.Games.Dota2 DayCycleRectangle = new KeyboardRectangle(MainManager.KeyboardManager.ActiveKeyboard , _keyPad.TopLeft.X*Scale - , _keyPad.TopLeft.Y* Scale + , _keyPad.TopLeft.Y*Scale , new List() , LinearGradientMode.Horizontal) { @@ -89,19 +87,20 @@ namespace Artemis.Modules.Games.Dota2 private void SetAbilityKeys() { #region Long Switch Statement for Keys + switch (Settings.KeyboardLayout) { case "0": case "Default": //default case "4": //Heroes of newearth case "3": //League of Legends - for (int i = 0; i < AbilityKeysRectangles.Length; i++) + for (var i = 0; i < AbilityKeysRectangles.Length; i++) { AbilityKeysRectangles[i] = new KeyboardRectangle(MainManager.KeyboardManager.ActiveKeyboard, - (_abilityKeys.TopLeft.X + i) * Scale - 2, - _abilityKeys.TopLeft.Y * Scale, - new List(), - LinearGradientMode.Horizontal) + (_abilityKeys.TopLeft.X + i)*Scale - 2, + _abilityKeys.TopLeft.Y*Scale, + new List(), + LinearGradientMode.Horizontal) { Height = Scale, Width = Scale @@ -110,37 +109,37 @@ namespace Artemis.Modules.Games.Dota2 break; case "2": AbilityKeysRectangles[0] = new KeyboardRectangle(MainManager.KeyboardManager.ActiveKeyboard, - (_abilityKeys.TopLeft.X * Scale) - 2, - _abilityKeys.TopLeft.Y * Scale, - new List(), - LinearGradientMode.Horizontal) + _abilityKeys.TopLeft.X*Scale - 2, + _abilityKeys.TopLeft.Y*Scale, + new List(), + LinearGradientMode.Horizontal) { Height = Scale, Width = Scale }; AbilityKeysRectangles[1] = new KeyboardRectangle(MainManager.KeyboardManager.ActiveKeyboard, - ((_abilityKeys.TopLeft.X + 2) * Scale) - 2, - _abilityKeys.TopLeft.Y * Scale, - new List(), - LinearGradientMode.Horizontal) + (_abilityKeys.TopLeft.X + 2)*Scale - 2, + _abilityKeys.TopLeft.Y*Scale, + new List(), + LinearGradientMode.Horizontal) { Height = Scale, Width = Scale }; AbilityKeysRectangles[2] = new KeyboardRectangle(MainManager.KeyboardManager.ActiveKeyboard, - ((_abilityKeys.TopLeft.X +3) * Scale) - 2, - _abilityKeys.TopLeft.Y * Scale, - new List(), - LinearGradientMode.Horizontal) + (_abilityKeys.TopLeft.X + 3)*Scale - 2, + _abilityKeys.TopLeft.Y*Scale, + new List(), + LinearGradientMode.Horizontal) { Height = Scale, Width = Scale }; AbilityKeysRectangles[3] = new KeyboardRectangle(MainManager.KeyboardManager.ActiveKeyboard, - ((_abilityKeys.TopLeft.X +3)* Scale) - 2, - (_abilityKeys.TopLeft.Y +1)* Scale, - new List(), - LinearGradientMode.Horizontal) + (_abilityKeys.TopLeft.X + 3)*Scale - 2, + (_abilityKeys.TopLeft.Y + 1)*Scale, + new List(), + LinearGradientMode.Horizontal) { Height = Scale, Width = Scale @@ -148,22 +147,22 @@ namespace Artemis.Modules.Games.Dota2 break; case "1": //MMO case "5": //Smite - for (int i = 0; i < AbilityKeysRectangles.Length; i++) + for (var i = 0; i < AbilityKeysRectangles.Length; i++) { AbilityKeysRectangles[i] = new KeyboardRectangle(MainManager.KeyboardManager.ActiveKeyboard, - (_abilityKeys.TopLeft.X + i) * Scale - 3, - (_abilityKeys.TopLeft.Y-1) * Scale, - new List(), - LinearGradientMode.Horizontal) + (_abilityKeys.TopLeft.X + i)*Scale - 3, + (_abilityKeys.TopLeft.Y - 1)*Scale, + new List(), + LinearGradientMode.Horizontal) { Height = Scale, Width = Scale }; } break; - } - #endregion + + #endregion } public override void Update() @@ -184,7 +183,6 @@ namespace Artemis.Modules.Games.Dota2 UpdateHealth(); if (Settings.ShowMana) UpdateMana(); - } private void UpdateMainColor() @@ -202,18 +200,18 @@ namespace Artemis.Modules.Games.Dota2 { List list = null; if (!D2Json.hero.alive) - list = new List { Color.LightGray }; + list = new List {Color.LightGray}; else if (D2Json.hero.disarmed) - list = new List { Color.Yellow }; + list = new List {Color.Yellow}; else if (D2Json.hero.hexed) - list = new List { Color.Yellow }; + list = new List {Color.Yellow}; else if (D2Json.hero.silenced) - list = new List { Color.Yellow }; + list = new List {Color.Yellow}; else if (D2Json.hero.stunned) - list = new List { Color.Yellow }; + list = new List {Color.Yellow}; else if (D2Json.hero.magicimmune) - list = new List { Color.Lime }; - if(list == null) + list = new List {Color.Lime}; + if (list == null) return; EventRectangle.Colors = list; @@ -257,15 +255,23 @@ namespace Artemis.Modules.Games.Dota2 { if (AbilityKeysRectangles == null) return; - - AbilityKeysRectangles[0].Colors = D2Json?.abilities?.ability0?.can_cast == true ? new List - { ColorHelpers.ToDrawingColor(Settings.AbilityReadyColor) } : new List { ColorHelpers.ToDrawingColor(Settings.AbilityCooldownColor) }; - AbilityKeysRectangles[1].Colors = D2Json?.abilities?.ability1?.can_cast == true ? new List - { ColorHelpers.ToDrawingColor(Settings.AbilityReadyColor) } : new List { ColorHelpers.ToDrawingColor(Settings.AbilityCooldownColor) }; - AbilityKeysRectangles[2].Colors = D2Json?.abilities?.ability2?.can_cast == true ? new List - { ColorHelpers.ToDrawingColor(Settings.AbilityReadyColor) } : new List { ColorHelpers.ToDrawingColor(Settings.AbilityCooldownColor) }; - AbilityKeysRectangles[3].Colors = D2Json?.abilities?.ability3?.can_cast == true ? new List - { ColorHelpers.ToDrawingColor(Settings.AbilityReadyColor) } : new List { ColorHelpers.ToDrawingColor(Settings.AbilityCooldownColor) }; + + AbilityKeysRectangles[0].Colors = D2Json?.abilities?.ability0?.can_cast == true + ? new List + {ColorHelpers.ToDrawingColor(Settings.AbilityReadyColor)} + : new List {ColorHelpers.ToDrawingColor(Settings.AbilityCooldownColor)}; + AbilityKeysRectangles[1].Colors = D2Json?.abilities?.ability1?.can_cast == true + ? new List + {ColorHelpers.ToDrawingColor(Settings.AbilityReadyColor)} + : new List {ColorHelpers.ToDrawingColor(Settings.AbilityCooldownColor)}; + AbilityKeysRectangles[2].Colors = D2Json?.abilities?.ability2?.can_cast == true + ? new List + {ColorHelpers.ToDrawingColor(Settings.AbilityReadyColor)} + : new List {ColorHelpers.ToDrawingColor(Settings.AbilityCooldownColor)}; + AbilityKeysRectangles[3].Colors = D2Json?.abilities?.ability3?.can_cast == true + ? new List + {ColorHelpers.ToDrawingColor(Settings.AbilityReadyColor)} + : new List {ColorHelpers.ToDrawingColor(Settings.AbilityCooldownColor)}; } @@ -301,7 +307,6 @@ namespace Artemis.Modules.Games.Dota2 item.Draw(g); } DayCycleRectangle.Draw(g); - } return bitmap; } @@ -321,7 +326,6 @@ namespace Artemis.Modules.Games.Dota2 #region Variables - public Dota2Settings Settings { get; set; } public Dota2DataModel.Rootobject D2Json { get; set; } public int Scale { get; set; } public KeyboardRectangle HealthRectangle { get; set; } @@ -329,7 +333,7 @@ namespace Artemis.Modules.Games.Dota2 public KeyboardRectangle DayCycleRectangle { get; set; } public KeyboardRectangle ManaRectangle { get; set; } public KeyboardRectangle[] AbilityKeysRectangles = new KeyboardRectangle[4]; - #endregion + #endregion } } \ No newline at end of file diff --git a/Artemis/Artemis/Modules/Games/Dota2/Dota2ViewModel.cs b/Artemis/Artemis/Modules/Games/Dota2/Dota2ViewModel.cs index 452be09c7..b7885c311 100644 --- a/Artemis/Artemis/Modules/Games/Dota2/Dota2ViewModel.cs +++ b/Artemis/Artemis/Modules/Games/Dota2/Dota2ViewModel.cs @@ -1,46 +1,41 @@ -using System; -using System.IO; +using System.IO; using System.Windows.Forms; using Artemis.Managers; -using Artemis.Models; using Artemis.Properties; using Artemis.ViewModels.Abstract; using Caliburn.Micro; namespace Artemis.Modules.Games.Dota2 { - public class Dota2ViewModel : GameViewModel + public class Dota2ViewModel : GameViewModel { - public Dota2ViewModel(MainManager mainManager) + public Dota2ViewModel(MainManager mainManager) : base(mainManager, new Dota2Model(mainManager, new Dota2Settings())) { - - MainManager = mainManager; - GameSettings = new Dota2Settings(); - - GameModel = new Dota2Model(mainManager, (Dota2Settings) GameSettings); MainManager.EffectManager.EffectModels.Add(GameModel); PlaceConfigFile(); } - public BindableCollection KeyboardLayouts + public BindableCollection KeyboardLayouts => new BindableCollection(new[] { - get - { - return new BindableCollection(new[] {"Default","MMO","WASD","League of Legends","Heros of Newearth","Smite"}); - } - } + "Default", + "MMO", + "WASD", + "League of Legends", + "Heros of Newearth", + "Smite" + }); public static string Name => "Dota 2"; public string Content => "Dota 2 Content"; public void BrowseDirectory() { - var dialog = new FolderBrowserDialog { SelectedPath = ((Dota2Settings)GameSettings).GameDirectory }; + var dialog = new FolderBrowserDialog {SelectedPath = ((Dota2Settings) GameSettings).GameDirectory}; var result = dialog.ShowDialog(); if (result != DialogResult.OK) return; - ((Dota2Settings)GameSettings).GameDirectory = dialog.SelectedPath; + ((Dota2Settings) GameSettings).GameDirectory = dialog.SelectedPath; NotifyOfPropertyChange(() => GameSettings); GameSettings.Save(); @@ -49,33 +44,36 @@ namespace Artemis.Modules.Games.Dota2 public void PlaceConfigFile() { - if (((Dota2Settings)GameSettings).GameDirectory == string.Empty) + if (((Dota2Settings) GameSettings).GameDirectory == string.Empty) return; - if (Directory.Exists(((Dota2Settings)GameSettings).GameDirectory + "/game/dota/cfg")) + if (Directory.Exists(((Dota2Settings) GameSettings).GameDirectory + "/game/dota/cfg")) { var cfgFile = Resources.dotaGamestateConfiguration.Replace("{{port}}", MainManager.GameStateWebServer.Port.ToString()); try { File.WriteAllText( - ((Dota2Settings)GameSettings).GameDirectory + "/game/dota/cfg/gamestate_integration/gamestate_integration_artemis.cfg", - cfgFile); + ((Dota2Settings) GameSettings).GameDirectory + + "/game/dota/cfg/gamestate_integration/gamestate_integration_artemis.cfg", + cfgFile); } catch (DirectoryNotFoundException) { - Directory.CreateDirectory(((Dota2Settings) GameSettings).GameDirectory + "/game/dota/cfg/gamestate_integration/"); + Directory.CreateDirectory(((Dota2Settings) GameSettings).GameDirectory + + "/game/dota/cfg/gamestate_integration/"); File.WriteAllText( - ((Dota2Settings)GameSettings).GameDirectory + "/game/dota/cfg/gamestate_integration/gamestate_integration_artemis.cfg", - cfgFile); + ((Dota2Settings) GameSettings).GameDirectory + + "/game/dota/cfg/gamestate_integration/gamestate_integration_artemis.cfg", + cfgFile); } - + return; } MainManager.DialogService.ShowErrorMessageBox("Please select a valid Dota 2 directory\n\n" + @"By default Dota 2 is in \SteamApps\common\dota 2 beta"); - ((Dota2Settings)GameSettings).GameDirectory = string.Empty; + ((Dota2Settings) GameSettings).GameDirectory = string.Empty; NotifyOfPropertyChange(() => GameSettings); GameSettings.Save(); diff --git a/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueModel.cs b/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueModel.cs index 089552d02..fdccbda9a 100644 --- a/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueModel.cs +++ b/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueModel.cs @@ -15,9 +15,8 @@ namespace Artemis.Modules.Games.RocketLeague private Memory _memory; private GamePointersCollection _pointer; - public RocketLeagueModel(MainManager mainManager, RocketLeagueSettings settings) : base(mainManager) + public RocketLeagueModel(MainManager mainManager, RocketLeagueSettings settings) : base(mainManager, settings) { - Settings = settings; Name = "RocketLeague"; ProcessName = "RocketLeague"; Scale = 4; @@ -25,8 +24,6 @@ namespace Artemis.Modules.Games.RocketLeague Initialized = false; } - public RocketLeagueSettings Settings { get; set; } - public int Scale { get; set; } public override void Dispose() diff --git a/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueViewModel.cs b/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueViewModel.cs index d91f9a4d3..8332abfc7 100644 --- a/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueViewModel.cs +++ b/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueViewModel.cs @@ -1,37 +1,22 @@ -using System.ComponentModel; -using Artemis.Managers; +using Artemis.Managers; using Artemis.Settings; using Artemis.Utilities; using Artemis.Utilities.Memory; -using Artemis.ViewModels; using Artemis.ViewModels.Abstract; using Newtonsoft.Json; namespace Artemis.Modules.Games.RocketLeague { - public class RocketLeagueViewModel : GameViewModel + public class RocketLeagueViewModel : GameViewModel { private string _versionText; - public RocketLeagueViewModel(MainManager mainManager) + public RocketLeagueViewModel(MainManager mainManager) : base(mainManager, new RocketLeagueModel(mainManager, new RocketLeagueSettings())) { - MainManager = mainManager; - - // Settings are loaded from file by class - GameSettings = new RocketLeagueSettings(); - - // Create effect model and add it to MainManager - GameModel = new RocketLeagueModel(mainManager, (RocketLeagueSettings) GameSettings); MainManager.EffectManager.EffectModels.Add(GameModel); SetVersionText(); - - ProfileEditor = new ProfileEditorViewModel(MainManager, GameModel); - ProfileEditor.PropertyChanged += ProfileUpdater; - GameModel.Profile = ProfileEditor.SelectedProfile; } - public ProfileEditorViewModel ProfileEditor { get; set; } - public static string Name => "Rocket League"; public string VersionText @@ -47,12 +32,6 @@ namespace Artemis.Modules.Games.RocketLeague public RocketLeagueModel RocketLeagueModel { get; set; } - private void ProfileUpdater(object sender, PropertyChangedEventArgs e) - { - if (e.PropertyName == "SelectedProfile") - GameModel.Profile = ProfileEditor.SelectedProfile; - } - private void SetVersionText() { if (!General.Default.EnablePointersUpdate) diff --git a/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionModel.cs b/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionModel.cs index 906ab4980..5b39771fd 100644 --- a/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionModel.cs +++ b/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionModel.cs @@ -22,9 +22,8 @@ namespace Artemis.Modules.Games.TheDivision private StickyValue _stickyHp; private int _trans; - public TheDivisionModel(MainManager mainManager, TheDivisionSettings settings) : base(mainManager) + public TheDivisionModel(MainManager mainManager, TheDivisionSettings settings) : base(mainManager, settings) { - Settings = settings; Name = "TheDivision"; ProcessName = "TheDivision"; Scale = 4; @@ -32,8 +31,6 @@ namespace Artemis.Modules.Games.TheDivision Initialized = false; } - public TheDivisionSettings Settings { get; set; } - public int Scale { get; set; } public override void Dispose() diff --git a/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionViewModel.cs b/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionViewModel.cs index 6038755bd..bfeecf47d 100644 --- a/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionViewModel.cs +++ b/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionViewModel.cs @@ -4,24 +4,13 @@ using Artemis.ViewModels.Abstract; namespace Artemis.Modules.Games.TheDivision { - public class TheDivisionViewModel : GameViewModel + public class TheDivisionViewModel : GameViewModel { - public TheDivisionViewModel(MainManager mainManager) + public TheDivisionViewModel(MainManager mainManager) : base(mainManager, new TheDivisionModel(mainManager, new TheDivisionSettings())) { - MainManager = mainManager; - - // Settings are loaded from file by class - GameSettings = new TheDivisionSettings(); - - // Create effect model and add it to MainManager - GameModel = new TheDivisionModel(mainManager, (TheDivisionSettings) GameSettings); MainManager.EffectManager.EffectModels.Add(GameModel); - - ProfileEditor = new ProfileEditorViewModel(MainManager, GameModel); } - public ProfileEditorViewModel ProfileEditor { get; set; } - public static string Name => "The Division"; } } \ No newline at end of file diff --git a/Artemis/Artemis/Modules/Games/Witcher3/Witcher3Model.cs b/Artemis/Artemis/Modules/Games/Witcher3/Witcher3Model.cs index 07fd28af4..693429d74 100644 --- a/Artemis/Artemis/Modules/Games/Witcher3/Witcher3Model.cs +++ b/Artemis/Artemis/Modules/Games/Witcher3/Witcher3Model.cs @@ -18,9 +18,8 @@ namespace Artemis.Modules.Games.Witcher3 private KeyboardRectangle _signRect; private string _witcherSettings; - public Witcher3Model(MainManager mainManager, Witcher3Settings settings) : base(mainManager) + public Witcher3Model(MainManager mainManager, Witcher3Settings settings) : base(mainManager, settings) { - Settings = settings; Name = "Witcher3"; ProcessName = "witcher3"; Scale = 4; @@ -31,8 +30,6 @@ namespace Artemis.Modules.Games.Witcher3 _signRegex = new Regex("ActiveSign=(.*)", RegexOptions.Compiled); } - public Witcher3Settings Settings { get; set; } - public int Scale { get; set; } public override void Dispose() diff --git a/Artemis/Artemis/Modules/Games/Witcher3/Witcher3ViewModel.cs b/Artemis/Artemis/Modules/Games/Witcher3/Witcher3ViewModel.cs index 8fcbc1405..0384fd04f 100644 --- a/Artemis/Artemis/Modules/Games/Witcher3/Witcher3ViewModel.cs +++ b/Artemis/Artemis/Modules/Games/Witcher3/Witcher3ViewModel.cs @@ -4,14 +4,15 @@ using System.IO; using System.Linq; using System.Windows.Forms; using Artemis.Managers; +using Artemis.Models.Interfaces; using Artemis.Properties; using Artemis.ViewModels.Abstract; namespace Artemis.Modules.Games.Witcher3 { - public class Witcher3ViewModel : GameViewModel + public class Witcher3ViewModel : GameViewModel { - public Witcher3ViewModel(MainManager mainManager) + public Witcher3ViewModel(MainManager mainManager) : base(mainManager, new Witcher3Model(mainManager, new Witcher3Settings())) { MainManager = mainManager; @@ -109,4 +110,8 @@ namespace Artemis.Modules.Games.Witcher3 MainManager.DialogService.ShowMessageBox("Success", "The mod was successfully installed!"); } } + + public class Witcher3DataModel : IGameDataModel + { + } } \ No newline at end of file diff --git a/Artemis/Artemis/NLog.config b/Artemis/Artemis/NLog.config new file mode 100644 index 000000000..d32c52835 --- /dev/null +++ b/Artemis/Artemis/NLog.config @@ -0,0 +1,18 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/Artemis/Artemis/NLog.xsd b/Artemis/Artemis/NLog.xsd new file mode 100644 index 000000000..dc821bc0d --- /dev/null +++ b/Artemis/Artemis/NLog.xsd @@ -0,0 +1,2601 @@ + + + + + + + + + + + + + + + Watch config file for changes and reload automatically. + + + + + Print internal NLog messages to the console. Default value is: false + + + + + Print internal NLog messages to the console error output. Default value is: false + + + + + Write internal NLog messages to the specified file. + + + + + Log level threshold for internal log messages. Default value is: Info. + + + + + Global log level threshold for application log messages. Messages below this level won't be logged.. + + + + + Pass NLog internal exceptions to the application. Default value is: false. + + + + + Write internal NLog messages to the the System.Diagnostics.Trace. Default value is: false + + + + + + + + + + + + + + Make all targets within this section asynchronous (creates additional threads but the calling thread isn't blocked by any target writes). + + + + + + + + + + + + + + + + + Prefix for targets/layout renderers/filters/conditions loaded from this assembly. + + + + + Load NLog extensions from the specified file (*.dll) + + + + + Load NLog extensions from the specified assembly. Assembly name should be fully qualified. + + + + + + + + + + Name of the logger. May include '*' character which acts like a wildcard. Allowed forms are: *, Name, *Name, Name* and *Name* + + + + + Comma separated list of levels that this rule matches. + + + + + Minimum level that this rule matches. + + + + + Maximum level that this rule matches. + + + + + Level that this rule matches. + + + + + Comma separated list of target names. + + + + + Ignore further rules if this one matches. + + + + + Enable or disable logging rule. Disabled rules are ignored. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the file to be included. The name is relative to the name of the current config file. + + + + + Ignore any errors in the include file. + + + + + + + Variable name. + + + + + Variable value. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + Indicates whether to add <!-- --> comments around all written texts. + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Number of log events that should be processed in a batch by the lazy writer thread. + + + + + Action to be taken when the lazy writer thread request queue count exceeds the set limit. + + + + + Limit on the number of requests in the lazy writer thread request queue. + + + + + Time in milliseconds to sleep between batches. + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + + + + + + + + + + + + + Name of the target. + + + + + Number of log events to be buffered. + + + + + Timeout (in milliseconds) after which the contents of buffer will be flushed if there's no write in the specified period of time. Use -1 to disable timed flushes. + + + + + Indicates whether to use sliding timeout. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Encoding to be used. + + + + + Instance of that is used to format log messages. + + + + + Maximum message size in bytes. + + + + + Indicates whether to append newline at the end of log message. + + + + + Action that should be taken if the will be more connections than . + + + + + Action that should be taken if the message is larger than maxMessageSize. + + + + + Indicates whether to keep connection open whenever possible. + + + + + Size of the connection cache (number of connections which are kept alive). + + + + + Maximum current connections. 0 = no maximum. + + + + + Network address. + + + + + Maximum queue size. + + + + + Indicates whether to include source info (file name and line number) in the information sent over the network. + + + + + NDC item separator. + + + + + Indicates whether to include stack contents. + + + + + Indicates whether to include call site (class and method name) in the information sent over the network. + + + + + AppInfo field. By default it's the friendly name of the current AppDomain. + + + + + Indicates whether to include NLog-specific extensions to log4j schema. + + + + + Indicates whether to include dictionary contents. + + + + + + + + + + + + + + + + + + + + + + + + + + + Layout that should be use to calcuate the value for the parameter. + + + + + Viewer parameter name. + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Text to be rendered. + + + + + Header. + + + + + Footer. + + + + + Indicates whether to use default row highlighting rules. + + + + + The encoding for writing messages to the . + + + + + Indicates whether the error stream (stderr) should be used instead of the output stream (stdout). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Condition that must be met in order to set the specified foreground and background color. + + + + + Background color. + + + + + Foreground color. + + + + + + + + + + + + + + + + Indicates whether to ignore case when comparing texts. + + + + + Regular expression to be matched. You must specify either text or regex. + + + + + Text to be matched. You must specify either text or regex. + + + + + Indicates whether to match whole words only. + + + + + Compile the ? This can improve the performance, but at the costs of more memory usage. If false, the Regex Cache is used. + + + + + Background color. + + + + + Foreground color. + + + + + + + + + + + + + + + + + Name of the target. + + + + + Text to be rendered. + + + + + Header. + + + + + Footer. + + + + + Indicates whether to send the log messages to the standard error instead of the standard output. + + + + + The encoding for writing messages to the . + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Connection string. When provided, it overrides the values specified in DBHost, DBUserName, DBPassword, DBDatabase. + + + + + Name of the connection string (as specified in <connectionStrings> configuration section. + + + + + Database name. If the ConnectionString is not provided this value will be used to construct the "Database=" part of the connection string. + + + + + Database host name. If the ConnectionString is not provided this value will be used to construct the "Server=" part of the connection string. + + + + + Database password. If the ConnectionString is not provided this value will be used to construct the "Password=" part of the connection string. + + + + + Name of the database provider. + + + + + Database user name. If the ConnectionString is not provided this value will be used to construct the "User ID=" part of the connection string. + + + + + Indicates whether to keep the database connection open between the log events. + + + + + Obsolete - value will be ignored! The logging code always runs outside of transaction. Gets or sets a value indicating whether to use database transactions. Some data providers require this. + + + + + Connection string using for installation and uninstallation. If not provided, regular ConnectionString is being used. + + + + + Text of the SQL command to be run on each log level. + + + + + Type of the SQL command to be run on each log level. + + + + + + + + + + + + + + + + + + + + + + + Type of the command. + + + + + Connection string to run the command against. If not provided, connection string from the target is used. + + + + + Indicates whether to ignore failures. + + + + + Command text. + + + + + + + + + + + + + + Layout that should be use to calcuate the value for the parameter. + + + + + Database parameter name. + + + + + Database parameter precision. + + + + + Database parameter scale. + + + + + Database parameter size. + + + + + + + + + + + + + + + Name of the target. + + + + + Text to be rendered. + + + + + Header. + + + + + Footer. + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + Layout that renders event Category. + + + + + Layout that renders event ID. + + + + + Name of the Event Log to write to. This can be System, Application or any user-defined name. + + + + + Name of the machine on which Event Log service is running. + + + + + Value to be used as the event Source. + + + + + Action to take if the message is larger than the option. + + + + + Optional entrytype. When not set, or when not convertable to then determined by + + + + + Message length limit to write to the Event Log. + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Indicates whether to return to the first target after any successful write. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Text to be rendered. + + + + + Header. + + + + + Footer. + + + + + File encoding. + + + + + Line ending mode. + + + + + Way file archives are numbered. + + + + + Name of the file to be used for an archive. + + + + + Indicates whether to automatically archive log files every time the specified time passes. + + + + + Size in bytes above which log files will be automatically archived. Warning: combining this with isn't supported. We cannot create multiple archive files, if they should have the same name. Choose: + + + + + Maximum number of archive files that should be kept. + + + + + Indicates whether to compress archive files into the zip archive format. + + + + + Gets or set a value indicating whether a managed file stream is forced, instead of used the native implementation. + + + + + Cleanup invalid values in a filename, e.g. slashes in a filename. If set to true, this can impact the performance of massive writes. If set to false, nothing gets written when the filename is wrong. + + + + + Name of the file to write to. + + + + + Value specifying the date format to use when archiving files. + + + + + Indicates whether to archive old log file on startup. + + + + + Indicates whether to create directories if they do not exist. + + + + + Indicates whether to enable log file(s) to be deleted. + + + + + File attributes (Windows only). + + + + + Indicates whether to delete old log file on startup. + + + + + Indicates whether to replace file contents on each write instead of appending log message at the end. + + + + + Indicates whether concurrent writes to the log file by multiple processes on the same host. + + + + + Delay in milliseconds to wait before attempting to write to the file again. + + + + + Maximum number of log filenames that should be stored as existing. + + + + + Indicates whether concurrent writes to the log file by multiple processes on different network hosts. + + + + + Number of files to be kept open. Setting this to a higher value may improve performance in a situation where a single File target is writing to many files (such as splitting by level or by logger). + + + + + Maximum number of seconds that files are kept open. If this number is negative the files are not automatically closed after a period of inactivity. + + + + + Log file buffer size in bytes. + + + + + Indicates whether to automatically flush the file buffers after each log message. + + + + + Number of times the write is appended on the file before NLog discards the log message. + + + + + Indicates whether to keep log file open instead of opening and closing it on each logging event. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Condition expression. Log events who meet this condition will be forwarded to the wrapped target. + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Windows domain name to change context to. + + + + + Required impersonation level. + + + + + Type of the logon provider. + + + + + Logon Type. + + + + + User account password. + + + + + Indicates whether to revert to the credentials of the process instead of impersonating another user. + + + + + Username to change context to. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Endpoint address. + + + + + Name of the endpoint configuration in WCF configuration file. + + + + + Indicates whether to use a WCF service contract that is one way (fire and forget) or two way (request-reply) + + + + + Client ID. + + + + + Indicates whether to include per-event properties in the payload sent to the server. + + + + + Indicates whether to use binary message encoding. + + + + + + + + + + + + + + Layout that should be use to calculate the value for the parameter. + + + + + Name of the parameter. + + + + + Type of the parameter. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Text to be rendered. + + + + + Header. + + + + + Footer. + + + + + Indicates whether to send message as HTML instead of plain text. + + + + + Encoding to be used for sending e-mail. + + + + + Indicates whether to add new lines between log entries. + + + + + CC email addresses separated by semicolons (e.g. john@domain.com;jane@domain.com). + + + + + Recipients' email addresses separated by semicolons (e.g. john@domain.com;jane@domain.com). + + + + + BCC email addresses separated by semicolons (e.g. john@domain.com;jane@domain.com). + + + + + Mail message body (repeated for each log message send in one mail). + + + + + Mail subject. + + + + + Sender's email address (e.g. joe@domain.com). + + + + + Indicates whether NewLine characters in the body should be replaced with tags. + + + + + Priority used for sending mails. + + + + + Indicates the SMTP client timeout. + + + + + SMTP Server to be used for sending. + + + + + SMTP Authentication mode. + + + + + Username used to connect to SMTP server (used when SmtpAuthentication is set to "basic"). + + + + + Password used to authenticate against SMTP server (used when SmtpAuthentication is set to "basic"). + + + + + Indicates whether SSL (secure sockets layer) should be used when communicating with SMTP server. + + + + + Port number that SMTP Server is listening on. + + + + + Indicates whether the default Settings from System.Net.MailSettings should be used. + + + + + Folder where applications save mail messages to be processed by the local SMTP server. + + + + + Specifies how outgoing email messages will be handled. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + Encoding to be used when writing text to the queue. + + + + + Indicates whether to use the XML format when serializing message. This will also disable creating queues. + + + + + Indicates whether to check if a queue exists before writing to it. + + + + + Indicates whether to create the queue if it doesn't exists. + + + + + Label to associate with each message. + + + + + Name of the queue to write to. + + + + + Indicates whether to use recoverable messages (with guaranteed delivery). + + + + + + + + + + + + + + + + + Name of the target. + + + + + Class name. + + + + + Method name. The method must be public and static. Use the AssemblyQualifiedName , https://msdn.microsoft.com/en-us/library/system.type.assemblyqualifiedname(v=vs.110).aspx e.g. + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + Encoding to be used. + + + + + Maximum message size in bytes. + + + + + Indicates whether to append newline at the end of log message. + + + + + Action that should be taken if the will be more connections than . + + + + + Action that should be taken if the message is larger than maxMessageSize. + + + + + Network address. + + + + + Size of the connection cache (number of connections which are kept alive). + + + + + Indicates whether to keep connection open whenever possible. + + + + + Maximum current connections. 0 = no maximum. + + + + + Maximum queue size. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Encoding to be used. + + + + + Instance of that is used to format log messages. + + + + + Maximum message size in bytes. + + + + + Indicates whether to append newline at the end of log message. + + + + + Action that should be taken if the will be more connections than . + + + + + Action that should be taken if the message is larger than maxMessageSize. + + + + + Indicates whether to keep connection open whenever possible. + + + + + Size of the connection cache (number of connections which are kept alive). + + + + + Maximum current connections. 0 = no maximum. + + + + + Network address. + + + + + Maximum queue size. + + + + + Indicates whether to include source info (file name and line number) in the information sent over the network. + + + + + NDC item separator. + + + + + Indicates whether to include stack contents. + + + + + Indicates whether to include call site (class and method name) in the information sent over the network. + + + + + AppInfo field. By default it's the friendly name of the current AppDomain. + + + + + Indicates whether to include NLog-specific extensions to log4j schema. + + + + + Indicates whether to include dictionary contents. + + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + Indicates whether to perform layout calculation. + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Indicates whether performance counter should be automatically created. + + + + + Name of the performance counter category. + + + + + Counter help text. + + + + + Name of the performance counter. + + + + + Performance counter type. + + + + + The value by which to increment the counter. + + + + + Performance counter instance name. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Default filter to be applied when no specific rule matches. + + + + + + + + + + + + + Condition to be tested. + + + + + Resulting filter to be applied when the condition matches. + + + + + + + + + + + + Name of the target. + + + + + + + + + + + + + + + Name of the target. + + + + + Number of times to repeat each log message. + + + + + + + + + + + + + + + + Name of the target. + + + + + Number of retries that should be attempted on the wrapped target in case of a failure. + + + + + Time to wait between retries in milliseconds. + + + + + + + + + + + + + + Name of the target. + + + + + + + + + + + + + + Name of the target. + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Should we include the BOM (Byte-order-mark) for UTF? Influences the property. This will only work for UTF-8. + + + + + Encoding. + + + + + Web service method name. Only used with Soap. + + + + + Web service namespace. Only used with Soap. + + + + + Protocol to be used when calling web service. + + + + + Web service URL. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Footer layout. + + + + + Header layout. + + + + + Body layout (can be repeated multiple times). + + + + + Custom column delimiter value (valid when ColumnDelimiter is set to 'Custom'). + + + + + Column delimiter. + + + + + Quote Character. + + + + + Quoting mode. + + + + + Indicates whether CVS should include header. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Layout of the column. + + + + + Name of the column. + + + + + + + + + + + + + Option to suppress the extra spaces in the output json + + + + + + + + + + + + + + Determines wether or not this attribute will be Json encoded. + + + + + Layout that will be rendered as the attribute's value. + + + + + Name of the attribute. + + + + + + + + + + + + + + Footer layout. + + + + + Header layout. + + + + + Body layout (can be repeated multiple times). + + + + + + + + + + + + + + + + + + + + + Layout text. + + + + + + + + + + + + + + + Action to be taken when filter matches. + + + + + Condition expression. + + + + + + + + + + + + + + + + + + + + + + + + + + Action to be taken when filter matches. + + + + + Indicates whether to ignore case when comparing strings. + + + + + Layout to be used to filter log messages. + + + + + Substring to be matched. + + + + + + + + + + + + + + + + + Action to be taken when filter matches. + + + + + String to compare the layout to. + + + + + Indicates whether to ignore case when comparing strings. + + + + + Layout to be used to filter log messages. + + + + + + + + + + + + + + + + + Action to be taken when filter matches. + + + + + Indicates whether to ignore case when comparing strings. + + + + + Layout to be used to filter log messages. + + + + + Substring to be matched. + + + + + + + + + + + + + + + + + Action to be taken when filter matches. + + + + + String to compare the layout to. + + + + + Indicates whether to ignore case when comparing strings. + + + + + Layout to be used to filter log messages. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Artemis/Artemis/ViewModels/Abstract/GameViewModel.cs b/Artemis/Artemis/ViewModels/Abstract/GameViewModel.cs index ba58d6dc6..ef4c9563c 100644 --- a/Artemis/Artemis/ViewModels/Abstract/GameViewModel.cs +++ b/Artemis/Artemis/ViewModels/Abstract/GameViewModel.cs @@ -1,17 +1,38 @@ using System.ComponentModel; +using System.Threading; +using System.Threading.Tasks; using Artemis.Managers; using Artemis.Models; +using Artemis.Modules.Effects.ProfilePreview; +using Artemis.Modules.Games.Witcher3; using Caliburn.Micro; namespace Artemis.ViewModels.Abstract { - public abstract class GameViewModel : Screen + public abstract class GameViewModel : Screen { + private bool _doActivate; + + private bool _editorShown; private GameSettings _gameSettings; + private EffectModel _lastEffect; + + protected GameViewModel(MainManager mainManager, GameModel gameModel) + { + MainManager = mainManager; + GameModel = gameModel; + GameSettings = gameModel.Settings; + + ProfileEditor = new ProfileEditorViewModel(MainManager, GameModel); + GameModel.Profile = ProfileEditor.SelectedProfile; + ProfileEditor.PropertyChanged += ProfileUpdater; + } + + public ProfileEditorViewModel ProfileEditor { get; set; } public GameModel GameModel { get; set; } public MainManager MainManager { get; set; } - public event OnLayersUpdatedCallback OnLayersUpdatedCallback; + public GameSettings GameSettings { get { return _gameSettings; } @@ -54,6 +75,63 @@ namespace Artemis.ViewModels.Abstract SaveSettings(); } + + protected override void OnActivate() + { + base.OnActivate(); + + // OnActive is triggered at odd moments, only activate the profile + // preview if OnDeactivate isn't called right after it + _doActivate = true; + Task.Factory.StartNew(() => + { + Thread.Sleep(100); + if (_doActivate) + SetEditorShown(true); + }); + } + + protected override void OnDeactivate(bool close) + { + base.OnDeactivate(close); + + _doActivate = false; + SetEditorShown(false); + } + + public void SetEditorShown(bool enable) + { + if (enable == _editorShown) + return; + + if (enable) + { + // Store the current effect so it can be restored later + if (!(MainManager.EffectManager.ActiveEffect is ProfilePreviewModel)) + _lastEffect = MainManager.EffectManager.ActiveEffect; + + MainManager.EffectManager.ProfilePreviewModel.SelectedProfile = ProfileEditor.SelectedProfile; + MainManager.EffectManager.ChangeEffect(MainManager.EffectManager.ProfilePreviewModel); + } + else + { + if (_lastEffect != null) + MainManager.EffectManager.ChangeEffect(_lastEffect, true); + else + MainManager.EffectManager.ClearEffect(); + } + + _editorShown = enable; + } + + private void ProfileUpdater(object sender, PropertyChangedEventArgs e) + { + if (e.PropertyName != "SelectedProfile") + return; + + GameModel.Profile = ProfileEditor.SelectedProfile; + MainManager.EffectManager.ProfilePreviewModel.SelectedProfile = ProfileEditor.SelectedProfile; + } } public delegate void OnLayersUpdatedCallback(object sender); diff --git a/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs b/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs index 5bf104d05..7d1ddab4a 100644 --- a/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs +++ b/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs @@ -9,7 +9,6 @@ using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; -using System.Xml.Serialization; using Artemis.DAL; using Artemis.Events; using Artemis.KeyboardProviders; @@ -51,6 +50,10 @@ namespace Artemis.ViewModels LoadProfiles(); } + public ProfileEditorViewModel() + { + } + public BindableCollection Profiles { get { return _profiles; } @@ -105,7 +108,8 @@ namespace Artemis.ViewModels _selectedProfile = value; Layers.Clear(); - Layers.AddRange(_selectedProfile?.Layers); + if (_selectedProfile != null) + Layers.AddRange(_selectedProfile.Layers); NotifyOfPropertyChange(() => SelectedProfile); NotifyOfPropertyChange(() => CanAddLayer); diff --git a/Artemis/Artemis/packages.config b/Artemis/Artemis/packages.config index 137cbc49a..ede4bf51d 100644 --- a/Artemis/Artemis/packages.config +++ b/Artemis/Artemis/packages.config @@ -14,6 +14,9 @@ + + +