diff --git a/Artemis/Artemis.sln b/Artemis/Artemis.sln index 9e2a09e30..7fe9f29c7 100644 --- a/Artemis/Artemis.sln +++ b/Artemis/Artemis.sln @@ -11,6 +11,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnrealTournament2Artemis", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ColorBox", "ColorBox\ColorBox.csproj", "{40085232-ACED-4CBE-945B-90BA8153C151}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LogiLed2Artemis", "LogiLed2Artemis\LogiLed2Artemis.vcxproj", "{D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution CD_ROM|Any CPU = CD_ROM|Any CPU @@ -146,6 +148,34 @@ Global {40085232-ACED-4CBE-945B-90BA8153C151}.SingleImage|x64.Build.0 = Release|Any CPU {40085232-ACED-4CBE-945B-90BA8153C151}.SingleImage|x86.ActiveCfg = Release|Any CPU {40085232-ACED-4CBE-945B-90BA8153C151}.SingleImage|x86.Build.0 = Release|Any CPU + {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.CD_ROM|Any CPU.ActiveCfg = Release|x64 + {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.CD_ROM|Any CPU.Build.0 = Release|x64 + {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.CD_ROM|x64.ActiveCfg = Release|x64 + {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.CD_ROM|x64.Build.0 = Release|x64 + {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.CD_ROM|x86.ActiveCfg = Release|Win32 + {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.CD_ROM|x86.Build.0 = Release|Win32 + {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.Debug|x64.ActiveCfg = Debug|x64 + {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.Debug|x64.Build.0 = Debug|x64 + {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.Debug|x86.ActiveCfg = Debug|Win32 + {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.Debug|x86.Build.0 = Debug|Win32 + {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.DVD-5|Any CPU.ActiveCfg = Release|x64 + {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.DVD-5|Any CPU.Build.0 = Release|x64 + {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.DVD-5|x64.ActiveCfg = Debug|x64 + {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.DVD-5|x64.Build.0 = Debug|x64 + {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.DVD-5|x86.ActiveCfg = Debug|Win32 + {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.DVD-5|x86.Build.0 = Debug|Win32 + {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.Release|Any CPU.ActiveCfg = Release|Win32 + {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.Release|x64.ActiveCfg = Release|x64 + {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.Release|x64.Build.0 = Release|x64 + {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.Release|x86.ActiveCfg = Release|Win32 + {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.Release|x86.Build.0 = Release|Win32 + {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.SingleImage|Any CPU.ActiveCfg = Release|x64 + {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.SingleImage|Any CPU.Build.0 = Release|x64 + {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.SingleImage|x64.ActiveCfg = Release|x64 + {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.SingleImage|x64.Build.0 = Release|x64 + {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.SingleImage|x86.ActiveCfg = Release|Win32 + {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.SingleImage|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Artemis/Artemis/Artemis.csproj b/Artemis/Artemis/Artemis.csproj index dbc607650..3158bbcb6 100644 --- a/Artemis/Artemis/Artemis.csproj +++ b/Artemis/Artemis/Artemis.csproj @@ -367,6 +367,13 @@ EurotruckSimulator2View.xaml + + + + + GtaVView.xaml + + @@ -763,6 +770,10 @@ MSBuild:Compile Designer + + Designer + MSBuild:Compile + Designer MSBuild:Compile diff --git a/Artemis/Artemis/InjectionModules/BaseModules.cs b/Artemis/Artemis/InjectionModules/BaseModules.cs index 8ad841238..4aa9b6494 100644 --- a/Artemis/Artemis/InjectionModules/BaseModules.cs +++ b/Artemis/Artemis/InjectionModules/BaseModules.cs @@ -1,9 +1,10 @@ using Artemis.Modules.Effects.ProfilePreview; using Artemis.Services; +using Artemis.Utilities.DataReaders; +using Artemis.Utilities.GameState; using Artemis.ViewModels; using Artemis.ViewModels.Abstract; using Artemis.ViewModels.Profiles; -using Caliburn.Micro; using Ninject.Modules; namespace Artemis.InjectionModules @@ -13,15 +14,15 @@ namespace Artemis.InjectionModules public override void Load() { // ViewModels - Bind().To().InSingletonScope(); + Bind().ToSelf(); Bind().ToSelf(); Bind().ToSelf(); Bind().ToSelf().InSingletonScope(); - Bind().To().InSingletonScope(); - Bind().To().InSingletonScope(); - Bind().To().InSingletonScope(); - Bind().To().InSingletonScope(); + Bind().To(); + Bind().To(); + Bind().To(); + Bind().To(); // Models Bind().ToSelf().InSingletonScope(); @@ -29,6 +30,10 @@ namespace Artemis.InjectionModules // Services Bind().ToSelf().InSingletonScope(); Bind().ToSelf().InSingletonScope(); + + // Servers + Bind().ToSelf().InSingletonScope(); + Bind().ToSelf().InSingletonScope(); } } } \ No newline at end of file diff --git a/Artemis/Artemis/InjectionModules/EffectModules.cs b/Artemis/Artemis/InjectionModules/EffectModules.cs index 91022f09a..387b85ba7 100644 --- a/Artemis/Artemis/InjectionModules/EffectModules.cs +++ b/Artemis/Artemis/InjectionModules/EffectModules.cs @@ -16,26 +16,16 @@ namespace Artemis.InjectionModules .SelectAllClasses() .InheritedFrom() .BindBase() - .Configure(b => b.InSingletonScope()); + .Configure((b, c) => b.InSingletonScope().Named(c.Name)); }); + // View models Kernel.Bind(x => { x.FromThisAssembly() .SelectAllClasses() .InheritedFrom() - .BindBase() - .Configure(b => b.InSingletonScope()); - }); - - // Games - Kernel.Bind(x => - { - x.FromThisAssembly() - .SelectAllClasses() - .InheritedFrom() - .BindBase() - .Configure(b => b.InSingletonScope()); + .BindBase(); }); Kernel.Bind(x => @@ -43,27 +33,14 @@ namespace Artemis.InjectionModules x.FromThisAssembly() .SelectAllClasses() .InheritedFrom() - .BindBase() - .Configure(b => b.InSingletonScope()); + .BindBase(); }); - - // Overlays - Kernel.Bind(x => - { - x.FromThisAssembly() - .SelectAllClasses() - .InheritedFrom() - .BindBase() - .Configure(b => b.InSingletonScope()); - }); - Kernel.Bind(x => { x.FromThisAssembly() .SelectAllClasses() .InheritedFrom() - .BindBase() - .Configure(b => b.InSingletonScope()); + .BindBase(); }); } } diff --git a/Artemis/Artemis/Managers/EffectManager.cs b/Artemis/Artemis/Managers/EffectManager.cs index ab23035e9..e8ef40679 100644 --- a/Artemis/Artemis/Managers/EffectManager.cs +++ b/Artemis/Artemis/Managers/EffectManager.cs @@ -21,14 +21,24 @@ namespace Artemis.Managers private EffectModel _waitEffect; private readonly GeneralSettings _generalSettings; - public EffectManager(ILogger logger, DeviceManager deviceManager) + public EffectManager(ILogger logger, DeviceManager deviceManager, List effectModels, + List gameModels, List overlayModels) { - EffectModels = new List(); - _generalSettings = DAL.SettingsProvider.Load(); _logger = logger; _deviceManager = deviceManager; + var models = new List(); + // Add regular effects + models.AddRange(effectModels); + // Add overlays + models.AddRange(overlayModels); + // Add games, exclude WoW if needed + models.AddRange(_generalSettings.GamestatePort != 62575 + ? gameModels.Where(e => e.Name != "WoW") + : gameModels); + + EffectModels = models; _logger.Info("Intialized EffectManager"); } diff --git a/Artemis/Artemis/Managers/MainManager.cs b/Artemis/Artemis/Managers/MainManager.cs index 3c28c588e..f9a8adb04 100644 --- a/Artemis/Artemis/Managers/MainManager.cs +++ b/Artemis/Artemis/Managers/MainManager.cs @@ -23,7 +23,8 @@ namespace Artemis.Managers private readonly Timer _processTimer; public MainManager(ILogger logger, LoopManager loopManager, DeviceManager deviceManager, - EffectManager effectManager, ProfileManager profileManager, PipeServer pipeServer) + EffectManager effectManager, ProfileManager profileManager, PipeServer pipeServer, + GameStateWebServer gameStateWebServer) { Logger = logger; LoopManager = loopManager; @@ -40,7 +41,7 @@ namespace Artemis.Managers Running = false; // Create and start the web server - GameStateWebServer = new GameStateWebServer(logger); + GameStateWebServer = gameStateWebServer; GameStateWebServer.Start(); // Start the named pipe diff --git a/Artemis/Artemis/Models/EffectModel.cs b/Artemis/Artemis/Models/EffectModel.cs index ee14df07a..478884cdb 100644 --- a/Artemis/Artemis/Models/EffectModel.cs +++ b/Artemis/Artemis/Models/EffectModel.cs @@ -3,14 +3,17 @@ using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Windows; +using Artemis.DAL; +using Artemis.Events; using Artemis.Managers; using Artemis.Models.Interfaces; using Artemis.Profiles; using Artemis.Profiles.Layers.Interfaces; using Artemis.Profiles.Layers.Models; -using Artemis.Profiles.Lua; using Artemis.Settings; using Newtonsoft.Json; +using Ninject; +using Ninject.Extensions.Logging; namespace Artemis.Models { @@ -20,25 +23,37 @@ namespace Artemis.Models protected DateTime LastTrace; - protected EffectModel(MainManager mainManager, EffectSettings settings, IDataModel dataModel) + protected EffectModel(DeviceManager deviceManager, EffectSettings settings, IDataModel dataModel) { - MainManager = mainManager; + DeviceManager = deviceManager; Settings = settings; DataModel = dataModel; - MainManager.EffectManager.EffectModels.Add(this); + // If set, load the last profile from settings + if (!string.IsNullOrEmpty(Settings?.LastProfile)) + Profile = ProfileProvider.GetProfile(DeviceManager.ActiveKeyboard, this, Settings.LastProfile); + + DeviceManager.OnKeyboardChangedEvent += DeviceManagerOnOnKeyboardChangedEvent; + } + + private void DeviceManagerOnOnKeyboardChangedEvent(object sender, KeyboardChangedEventArgs args) + { + if (!string.IsNullOrEmpty(Settings?.LastProfile)) + Profile = ProfileProvider.GetProfile(DeviceManager.ActiveKeyboard, this, Settings.LastProfile); } public bool Initialized { get; set; } - public MainManager MainManager { get; set; } + public DeviceManager DeviceManager { get; set; } public EffectSettings Settings { get; set; } public string Name { get; set; } public int KeyboardScale { get; set; } = 4; - // Used by profile system public IDataModel DataModel { get; set; } public ProfileModel Profile { get; set; } + [Inject] + public ILogger Logger { get; set; } + public virtual void Dispose() { Profile?.Deactivate(); @@ -58,7 +73,7 @@ namespace Artemis.Models /// public virtual void Render(RenderFrame frame, bool keyboardOnly) { - if (Profile == null || DataModel == null || MainManager.DeviceManager.ActiveKeyboard == null) + if ((Profile == null) || (DataModel == null) || (DeviceManager.ActiveKeyboard == null)) return; lock (DataModel) @@ -68,10 +83,10 @@ namespace Artemis.Models // If the profile has no active LUA wrapper, create one if (!string.IsNullOrEmpty(Profile.LuaScript)) - Profile.Activate(MainManager.DeviceManager.ActiveKeyboard); + Profile.Activate(DeviceManager.ActiveKeyboard); // Render the keyboard layer-by-layer - var keyboardRect = MainManager.DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale); + var keyboardRect = DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale); using (var g = Graphics.FromImage(frame.KeyboardBitmap)) { Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Keyboard), @@ -104,15 +119,15 @@ namespace Artemis.Models } // Trace debugging - if (DateTime.Now.AddSeconds(-2) <= LastTrace) + if (DateTime.Now.AddSeconds(-2) <= LastTrace || Logger == null) return; + LastTrace = DateTime.Now; - MainManager.Logger.Trace("Effect datamodel as JSON: \r\n{0}", - JsonConvert.SerializeObject(DataModel, Formatting.Indented)); - MainManager.Logger.Trace("Effect {0} has to render {1} layers", Name, renderLayers.Count); + var dmJson = JsonConvert.SerializeObject(DataModel, Formatting.Indented); + Logger.Trace("Effect datamodel as JSON: \r\n{0}", dmJson); + Logger.Trace("Effect {0} has to render {1} layers", Name, renderLayers.Count); foreach (var renderLayer in renderLayers) - MainManager.Logger.Trace("- Layer name: {0}, layer type: {1}", renderLayer.Name, - renderLayer.LayerType); + Logger.Trace("- Layer name: {0}, layer type: {1}", renderLayer.Name, renderLayer.LayerType); } } diff --git a/Artemis/Artemis/Models/GameModel.cs b/Artemis/Artemis/Models/GameModel.cs index fc63cd2ca..3d9d02204 100644 --- a/Artemis/Artemis/Models/GameModel.cs +++ b/Artemis/Artemis/Models/GameModel.cs @@ -6,7 +6,7 @@ namespace Artemis.Models { public abstract class GameModel : EffectModel { - protected GameModel(MainManager mainManager, GameSettings settings, IDataModel dataModel): base(mainManager, settings, dataModel) + protected GameModel(DeviceManager deviceManager, GameSettings settings, IDataModel dataModel): base(deviceManager, settings, dataModel) { // Override settings to the GameSettings type Settings = settings; diff --git a/Artemis/Artemis/Models/OverlayModel.cs b/Artemis/Artemis/Models/OverlayModel.cs index e5a58c602..3e7d4aba8 100644 --- a/Artemis/Artemis/Models/OverlayModel.cs +++ b/Artemis/Artemis/Models/OverlayModel.cs @@ -8,7 +8,7 @@ namespace Artemis.Models private bool _enabled; public string ProcessName; - protected OverlayModel(MainManager mainManager, OverlaySettings settings) : base(mainManager, settings, null) + protected OverlayModel(DeviceManager deviceManager, OverlaySettings settings) : base(deviceManager, settings, null) { Settings = settings; Enabled = settings.Enabled; diff --git a/Artemis/Artemis/Modules/Effects/AudioVisualizer/AudioVisualizerViewModel.cs b/Artemis/Artemis/Modules/Effects/AudioVisualizer/AudioVisualizerViewModel.cs index 702d6610d..3cdf11f9b 100644 --- a/Artemis/Artemis/Modules/Effects/AudioVisualizer/AudioVisualizerViewModel.cs +++ b/Artemis/Artemis/Modules/Effects/AudioVisualizer/AudioVisualizerViewModel.cs @@ -1,12 +1,14 @@ using Artemis.Managers; +using Artemis.Models; using Artemis.Modules.Effects.ProfilePreview; using Artemis.ViewModels.Abstract; +using Ninject; namespace Artemis.Modules.Effects.AudioVisualizer { public sealed class AudioVisualizerViewModel : EffectViewModel { - public AudioVisualizerViewModel(MainManager main, ProfilePreviewModel model) : base(main, model) + public AudioVisualizerViewModel(MainManager main, [Named("ProfilePreviewModel")] EffectModel model) : base(main, model) { DisplayName = "Audio Visualization / Key waves"; } diff --git a/Artemis/Artemis/Modules/Effects/Bubbles/BubblesModel.cs b/Artemis/Artemis/Modules/Effects/Bubbles/BubblesModel.cs index eeaefde49..fbbfcb1d2 100644 --- a/Artemis/Artemis/Modules/Effects/Bubbles/BubblesModel.cs +++ b/Artemis/Artemis/Modules/Effects/Bubbles/BubblesModel.cs @@ -15,7 +15,7 @@ namespace Artemis.Modules.Effects.Bubbles { #region Constructors - public BubblesModel(MainManager mainManager) : base(mainManager, SettingsProvider.Load(), null) + public BubblesModel(DeviceManager deviceManager) : base(deviceManager, SettingsProvider.Load(), null) { Name = "Bubbles"; Initialized = false; @@ -40,8 +40,7 @@ namespace Artemis.Modules.Effects.Bubbles { KeyboardScale = Settings.Smoothness; - var rect = MainManager.DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale); - + var rect = DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale); var scaleFactor = Settings.Smoothness/25.0; for (var i = 0; i < Settings.BubbleCount; i++) @@ -74,7 +73,7 @@ namespace Artemis.Modules.Effects.Bubbles public override void Update() { - var keyboardRectangle = MainManager.DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale); + var keyboardRectangle = DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale); foreach (var bubble in _bubbles) { if (Settings.IsShiftColors) diff --git a/Artemis/Artemis/Modules/Effects/Bubbles/BubblesViewModel.cs b/Artemis/Artemis/Modules/Effects/Bubbles/BubblesViewModel.cs index a0d2cb304..5d34270ea 100644 --- a/Artemis/Artemis/Modules/Effects/Bubbles/BubblesViewModel.cs +++ b/Artemis/Artemis/Modules/Effects/Bubbles/BubblesViewModel.cs @@ -1,6 +1,8 @@ using System.Windows.Media; using Artemis.Managers; +using Artemis.Models; using Artemis.ViewModels.Abstract; +using Ninject; namespace Artemis.Modules.Effects.Bubbles { @@ -9,11 +11,11 @@ namespace Artemis.Modules.Effects.Bubbles private readonly BubblesModel _model; private SolidColorBrush _bubbleColor; - public BubblesViewModel(MainManager main, BubblesModel model) : base(main, model) + public BubblesViewModel(MainManager main, [Named("BubblesModel")] EffectModel model) : base(main, model) { - _model = model; + _model = (BubblesModel) model; DisplayName = "Bubbles"; - BubbleColor = new SolidColorBrush(model.Settings.BubbleColor); + BubbleColor = new SolidColorBrush(_model.Settings.BubbleColor); } /// diff --git a/Artemis/Artemis/Modules/Effects/ProfilePreview/ProfilePreviewModel.cs b/Artemis/Artemis/Modules/Effects/ProfilePreview/ProfilePreviewModel.cs index d25ce2bf5..2fb32ec1b 100644 --- a/Artemis/Artemis/Modules/Effects/ProfilePreview/ProfilePreviewModel.cs +++ b/Artemis/Artemis/Modules/Effects/ProfilePreview/ProfilePreviewModel.cs @@ -16,7 +16,8 @@ namespace Artemis.Modules.Effects.ProfilePreview { public class ProfilePreviewModel : EffectModel { - public ProfilePreviewModel(MainManager mainManager) : base(mainManager, null, new ProfilePreviewDataModel()) + public ProfilePreviewModel(DeviceManager deviceManager) + : base(deviceManager, null, new ProfilePreviewDataModel()) { Name = "Profile Preview"; } @@ -45,7 +46,7 @@ namespace Artemis.Modules.Effects.ProfilePreview public override void Render(RenderFrame frame, bool keyboardOnly) { - if (Profile == null || DataModel == null || MainManager.DeviceManager.ActiveKeyboard == null) + if ((Profile == null) || (DataModel == null) || (DeviceManager.ActiveKeyboard == null)) return; lock (DataModel) @@ -54,11 +55,11 @@ namespace Artemis.Modules.Effects.ProfilePreview var renderLayers = GetRenderLayers(keyboardOnly); // If the profile has no active LUA wrapper, create one - if (!string.IsNullOrEmpty(Profile.LuaScript)) - Profile.Activate(MainManager.DeviceManager.ActiveKeyboard); + if (!Equals(LuaWrapper.ProfileModel, Profile)) + Profile.Activate(DeviceManager.ActiveKeyboard); // Render the keyboard layer-by-layer - var keyboardRect = MainManager.DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale); + var keyboardRect = DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale); using (var g = Graphics.FromImage(frame.KeyboardBitmap)) { Profile.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Keyboard), diff --git a/Artemis/Artemis/Modules/Effects/WindowsProfile/WindowsProfileModel.cs b/Artemis/Artemis/Modules/Effects/WindowsProfile/WindowsProfileModel.cs index 53fe4b775..c428ea084 100644 --- a/Artemis/Artemis/Modules/Effects/WindowsProfile/WindowsProfileModel.cs +++ b/Artemis/Artemis/Modules/Effects/WindowsProfile/WindowsProfileModel.cs @@ -9,25 +9,22 @@ using Artemis.Managers; using Artemis.Models; using Artemis.Profiles.Layers.Models; using Newtonsoft.Json; -using Ninject.Extensions.Logging; using SpotifyAPI.Local; namespace Artemis.Modules.Effects.WindowsProfile { public class WindowsProfileModel : EffectModel { - private readonly ILogger _logger; private List _cores; private int _cpuFrames; + private DateTime _lastMusicUpdate; private PerformanceCounter _overallCpu; private SpotifyLocalAPI _spotify; private bool _spotifySetupBusy; - private DateTime _lastMusicUpdate; - public WindowsProfileModel(ILogger logger, MainManager mainManager) - : base(mainManager, SettingsProvider.Load(), new WindowsProfileDataModel()) + public WindowsProfileModel(DeviceManager deviceManager) + : base(deviceManager, SettingsProvider.Load(), new WindowsProfileDataModel()) { - _logger = logger; _lastMusicUpdate = DateTime.Now; Name = "WindowsProfile"; @@ -85,7 +82,7 @@ namespace Artemis.Modules.Effects.WindowsProfile } catch (InvalidOperationException) { - _logger.Warn("Failed to setup CPU information, try running \"lodctr /R\" as administrator."); + Logger?.Warn("Failed to setup CPU information, try running \"lodctr /R\" as administrator."); } } @@ -220,10 +217,8 @@ namespace Artemis.Modules.Effects.WindowsProfile } if (dataModel.Spotify.SongLength > 0) - { dataModel.Spotify.SongPercentCompleted = (int) (status.PlayingPosition/dataModel.Spotify.SongLength*100.0); - } } private void UpdateGooglePlayMusic(WindowsProfileDataModel dataModel) diff --git a/Artemis/Artemis/Modules/Effects/WindowsProfile/WindowsProfileViewModel.cs b/Artemis/Artemis/Modules/Effects/WindowsProfile/WindowsProfileViewModel.cs index 026436cba..15bfb1467 100644 --- a/Artemis/Artemis/Modules/Effects/WindowsProfile/WindowsProfileViewModel.cs +++ b/Artemis/Artemis/Modules/Effects/WindowsProfile/WindowsProfileViewModel.cs @@ -1,5 +1,6 @@ using System.ComponentModel; using Artemis.Managers; +using Artemis.Models; using Artemis.Modules.Effects.ProfilePreview; using Artemis.ViewModels.Abstract; using Artemis.ViewModels.Profiles; @@ -12,7 +13,7 @@ namespace Artemis.Modules.Effects.WindowsProfile public sealed class WindowsProfileViewModel : EffectViewModel { public WindowsProfileViewModel(MainManager main, IKernel kernel, ProfilePreviewModel profilePreviewModel, - WindowsProfileModel model) : base(main, model) + [Named("WindowsProfileModel")] EffectModel model) : base(main, model) { DisplayName = "Windows Profile"; ProfilePreviewModel = profilePreviewModel; @@ -25,10 +26,7 @@ namespace Artemis.Modules.Effects.WindowsProfile new ConstructorArgument("lastProfile", ((WindowsProfileSettings) EffectSettings).LastProfile) }; ProfileEditor = kernel.Get(args); - ProfilePreviewModel.Profile = ProfileEditor.SelectedProfile; ProfileEditor.PropertyChanged += ProfileUpdater; - - MainManager.EffectManager.EffectModels.Add(EffectModel); } public ProfileEditorViewModel ProfileEditor { get; set; } @@ -44,6 +42,7 @@ namespace Artemis.Modules.Effects.WindowsProfile if ((e.PropertyName != "SelectedProfile") || !ProfileEditor.ProfileViewModel.Activated || (ProfileEditor.ProfileViewModel.SelectedProfile == null)) return; + ((WindowsProfileSettings) EffectSettings).LastProfile = ProfileEditor.ProfileViewModel.SelectedProfile.Name; EffectSettings.Save(); } diff --git a/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrikeModel.cs b/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrikeModel.cs index bbbd5a5cc..452f2d51e 100644 --- a/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrikeModel.cs +++ b/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrikeModel.cs @@ -1,48 +1,57 @@ using System; using System.Collections.Generic; +using System.IO; using Artemis.DAL; using Artemis.Managers; using Artemis.Models; using Artemis.Profiles.Layers.Models; +using Artemis.Properties; +using Artemis.Services; +using Artemis.Utilities; using Artemis.Utilities.GameState; using Newtonsoft.Json; -using Ninject.Extensions.Logging; namespace Artemis.Modules.Games.CounterStrike { public class CounterStrikeModel : GameModel { + private readonly MetroDialogService _dialogService; + private readonly GameStateWebServer _gameStateWebServer; private DateTime _lastHeadshot; private int _lastHeadshots; private DateTime _lastKill; private int _lastKills; - public CounterStrikeModel(MainManager mainManager) - : base(mainManager, SettingsProvider.Load(), new CounterStrikeDataModel()) + public CounterStrikeModel(DeviceManager deviceManager, GameStateWebServer gameStateWebServer, + MetroDialogService dialogService) + : base(deviceManager, SettingsProvider.Load(), new CounterStrikeDataModel()) { + _gameStateWebServer = gameStateWebServer; + _dialogService = dialogService; + Name = "CounterStrike"; ProcessName = "csgo"; Scale = 4; Enabled = Settings.Enabled; Initialized = false; + + FindGameDir(); + PlaceConfigFile(); } - public ILogger Logger { get; set; } public int Scale { get; set; } public override void Dispose() { Initialized = false; - MainManager.GameStateWebServer.GameDataReceived -= HandleGameData; + _gameStateWebServer.GameDataReceived -= HandleGameData; + base.Dispose(); } public override void Enable() { - Initialized = false; - - MainManager.GameStateWebServer.GameDataReceived += HandleGameData; - + _gameStateWebServer.GameDataReceived += HandleGameData; Initialized = true; } @@ -90,6 +99,42 @@ namespace Artemis.Modules.Games.CounterStrike DataModel = dm; } + public void FindGameDir() + { + var gameSettings = (CounterStrikeSettings) Settings; + // If already propertly set up, don't do anything + if ((gameSettings.GameDirectory != null) && File.Exists(gameSettings.GameDirectory + "csgo.exe") && + File.Exists(gameSettings.GameDirectory + "/csgo/cfg/gamestate_integration_artemis.cfg")) + return; + + var dir = GeneralHelpers.FindSteamGame(@"\Counter-Strike Global Offensive\csgo.exe"); + gameSettings.GameDirectory = dir ?? string.Empty; + gameSettings.Save(); + } + + public void PlaceConfigFile() + { + var gameSettings = (CounterStrikeSettings) Settings; + if (gameSettings.GameDirectory == string.Empty) + return; + + var path = gameSettings.GameDirectory; + if (Directory.Exists(path + "/csgo/cfg")) + { + var cfgFile = Resources.csgoGamestateConfiguration.Replace("{{port}}", + _gameStateWebServer.Port.ToString()); + File.WriteAllText(path + "/csgo/cfg/gamestate_integration_artemis.cfg", cfgFile); + + return; + } + + _dialogService.ShowErrorMessageBox("Please select a valid CS:GO directory\n\n" + + @"By default CS:GO is in \SteamApps\common\Counter-Strike Global Offensive"); + + gameSettings.GameDirectory = string.Empty; + gameSettings.Save(); + } + public void HandleGameData(object sender, GameDataReceivedEventArgs e) { var jsonString = e.Json.ToString(); @@ -112,6 +157,7 @@ namespace Artemis.Modules.Games.CounterStrike } } + public override List GetRenderLayers(bool keyboardOnly) { return Profile.GetRenderLayers(DataModel, keyboardOnly); diff --git a/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrikeViewModel.cs b/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrikeViewModel.cs index d32a9e759..f1f0b71ce 100644 --- a/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrikeViewModel.cs +++ b/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrikeViewModel.cs @@ -1,72 +1,22 @@ -using System.IO; -using System.Windows.Forms; -using Ninject; -using Artemis.Managers; -using Artemis.Properties; -using Artemis.Utilities; +using Artemis.Managers; +using Artemis.Models; using Artemis.ViewModels.Abstract; +using Ninject; namespace Artemis.Modules.Games.CounterStrike { public sealed class CounterStrikeViewModel : GameViewModel { - public CounterStrikeViewModel(MainManager main, IKernel kernel, CounterStrikeModel model) + public CounterStrikeViewModel(MainManager main, IKernel kernel, [Named("CounterStrikeModel")] GameModel model) : base(main, model, kernel) { DisplayName = "CS:GO"; - - FindGameDir(); - PlaceConfigFile(); - } - - public void FindGameDir() - { - var gameSettings = (CounterStrikeSettings) GameSettings; - // If already propertly set up, don't do anything - if ((gameSettings.GameDirectory != null) && File.Exists(gameSettings.GameDirectory + "csgo.exe") && - File.Exists(gameSettings.GameDirectory + "/csgo/cfg/gamestate_integration_artemis.cfg")) - return; - - var dir = GeneralHelpers.FindSteamGame(@"\Counter-Strike Global Offensive\csgo.exe"); - gameSettings.GameDirectory = dir ?? string.Empty; - gameSettings.Save(); } public void BrowseDirectory() { - var dialog = new FolderBrowserDialog {SelectedPath = ((CounterStrikeSettings) GameSettings).GameDirectory}; - var result = dialog.ShowDialog(); - if (result != DialogResult.OK) - return; - - ((CounterStrikeSettings) GameSettings).GameDirectory = Path.GetDirectoryName(dialog.SelectedPath); + ((CounterStrikeModel) GameModel).PlaceConfigFile(); NotifyOfPropertyChange(() => GameSettings); - - GameSettings.Save(); - PlaceConfigFile(); - } - - public void PlaceConfigFile() - { - if (((CounterStrikeSettings) GameSettings).GameDirectory == string.Empty) - return; - - var path = ((CounterStrikeSettings) GameSettings).GameDirectory; - if (Directory.Exists(path + "/csgo/cfg")) - { - var cfgFile = Resources.csgoGamestateConfiguration.Replace("{{port}}", - MainManager.GameStateWebServer.Port.ToString()); - File.WriteAllText(path + "/csgo/cfg/gamestate_integration_artemis.cfg", cfgFile); - - return; - } - - DialogService.ShowErrorMessageBox("Please select a valid CS:GO directory\n\n" + - @"By default CS:GO is in \SteamApps\common\Counter-Strike Global Offensive"); - - ((CounterStrikeSettings) GameSettings).GameDirectory = string.Empty; - NotifyOfPropertyChange(() => GameSettings); - GameSettings.Save(); } } } \ No newline at end of file diff --git a/Artemis/Artemis/Modules/Games/Dota2/Dota2Model.cs b/Artemis/Artemis/Modules/Games/Dota2/Dota2Model.cs index fb1ad8fa3..8029a5da3 100644 --- a/Artemis/Artemis/Modules/Games/Dota2/Dota2Model.cs +++ b/Artemis/Artemis/Modules/Games/Dota2/Dota2Model.cs @@ -1,8 +1,12 @@ using System.Collections.Generic; +using System.IO; using Artemis.DAL; using Artemis.Managers; using Artemis.Models; using Artemis.Profiles.Layers.Models; +using Artemis.Properties; +using Artemis.Services; +using Artemis.Utilities; using Artemis.Utilities.GameState; using Newtonsoft.Json; @@ -10,14 +14,24 @@ namespace Artemis.Modules.Games.Dota2 { public class Dota2Model : GameModel { - public Dota2Model(MainManager mainManager) - : base(mainManager, SettingsProvider.Load(), new Dota2DataModel()) + private readonly MetroDialogService _dialogService; + private readonly GameStateWebServer _gameStateWebServer; + + public Dota2Model(DeviceManager deviceManager, GameStateWebServer gameStateWebServer, + MetroDialogService dialogService) + : base(deviceManager, SettingsProvider.Load(), new Dota2DataModel()) { + _gameStateWebServer = gameStateWebServer; + _dialogService = dialogService; + Name = "Dota2"; ProcessName = "dota2"; Enabled = Settings.Enabled; Initialized = false; Scale = 4; + + FindGameDir(); + PlaceConfigFile(); } public int Scale { get; set; } @@ -25,13 +39,13 @@ namespace Artemis.Modules.Games.Dota2 public override void Dispose() { Initialized = false; - MainManager.GameStateWebServer.GameDataReceived -= HandleGameData; + _gameStateWebServer.GameDataReceived -= HandleGameData; base.Dispose(); } public override void Enable() { - MainManager.GameStateWebServer.GameDataReceived += HandleGameData; + _gameStateWebServer.GameDataReceived += HandleGameData; Initialized = true; } @@ -40,6 +54,55 @@ namespace Artemis.Modules.Games.Dota2 UpdateDay(); } + public void FindGameDir() + { + var gameSettings = (Dota2Settings) Settings; + // If already propertly set up, don't do anything + if ((gameSettings.GameDirectory != null) && File.Exists(gameSettings.GameDirectory + "csgo.exe") && + File.Exists(gameSettings.GameDirectory + "/csgo/cfg/gamestate_integration_artemis.cfg")) + return; + + var dir = GeneralHelpers.FindSteamGame(@"\dota 2 beta\game\bin\win32\dota2.exe"); + // Remove subdirectories where they stuck the executable + dir = dir?.Substring(0, dir.Length - 15); + + gameSettings.GameDirectory = dir ?? string.Empty; + gameSettings.Save(); + } + + public void PlaceConfigFile() + { + var gameSettings = (Dota2Settings) Settings; + if (gameSettings.GameDirectory == string.Empty) + return; + if (Directory.Exists(gameSettings.GameDirectory + "/game/dota/cfg")) + { + var cfgFile = Resources.dotaGamestateConfiguration.Replace("{{port}}", + _gameStateWebServer.Port.ToString()); + try + { + File.WriteAllText( + gameSettings.GameDirectory + + "/game/dota/cfg/gamestate_integration/gamestate_integration_artemis.cfg", cfgFile); + } + catch (DirectoryNotFoundException) + { + Directory.CreateDirectory(gameSettings.GameDirectory + "/game/dota/cfg/gamestate_integration/"); + File.WriteAllText( + gameSettings.GameDirectory + + "/game/dota/cfg/gamestate_integration/gamestate_integration_artemis.cfg", + cfgFile); + } + + return; + } + + _dialogService.ShowErrorMessageBox("Please select a valid Dota 2 directory\n\n" + + @"By default Dota 2 is in \SteamApps\common\dota 2 beta"); + gameSettings.GameDirectory = string.Empty; + gameSettings.Save(); + } + private void UpdateDay() { var dataModel = DataModel as Dota2DataModel; diff --git a/Artemis/Artemis/Modules/Games/Dota2/Dota2ViewModel.cs b/Artemis/Artemis/Modules/Games/Dota2/Dota2ViewModel.cs index 2965c8ab3..1513ff9ca 100644 --- a/Artemis/Artemis/Modules/Games/Dota2/Dota2ViewModel.cs +++ b/Artemis/Artemis/Modules/Games/Dota2/Dota2ViewModel.cs @@ -1,88 +1,22 @@ -using System.IO; -using System.Windows.Forms; -using Ninject; -using Artemis.Managers; -using Artemis.Properties; -using Artemis.Utilities; +using Artemis.Managers; +using Artemis.Models; using Artemis.ViewModels.Abstract; +using Ninject; namespace Artemis.Modules.Games.Dota2 { public sealed class Dota2ViewModel : GameViewModel { - public Dota2ViewModel(MainManager main, IKernel kernel, Dota2Model model) + public Dota2ViewModel(MainManager main, IKernel kernel, [Named("Dota2Model")] GameModel model) : base(main, model, kernel) { DisplayName = "Dota 2"; - - FindGameDir(); - PlaceConfigFile(); - } - - public void FindGameDir() - { - var gameSettings = (Dota2Settings) GameSettings; - // If already propertly set up, don't do anything - if ((gameSettings.GameDirectory != null) && File.Exists(gameSettings.GameDirectory + "csgo.exe") && - File.Exists(gameSettings.GameDirectory + "/csgo/cfg/gamestate_integration_artemis.cfg")) - return; - - var dir = GeneralHelpers.FindSteamGame(@"\dota 2 beta\game\bin\win32\dota2.exe"); - // Remove subdirectories where they stuck the executable - dir = dir?.Substring(0, dir.Length - 15); - - gameSettings.GameDirectory = dir ?? string.Empty; - gameSettings.Save(); - } - - public void BrowseDirectory() - { - var dialog = new FolderBrowserDialog {SelectedPath = ((Dota2Settings) GameSettings).GameDirectory}; - var result = dialog.ShowDialog(); - if (result != DialogResult.OK) - return; - - ((Dota2Settings) GameSettings).GameDirectory = dialog.SelectedPath; - NotifyOfPropertyChange(() => GameSettings); - - GameSettings.Save(); - PlaceConfigFile(); } public void PlaceConfigFile() { - if (((Dota2Settings) GameSettings).GameDirectory == string.Empty) - return; - 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); - } - catch (DirectoryNotFoundException) - { - 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); - } - - return; - } - - 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; + ((Dota2Model) GameModel).PlaceConfigFile(); NotifyOfPropertyChange(() => GameSettings); - - GameSettings.Save(); } } } \ No newline at end of file diff --git a/Artemis/Artemis/Modules/Games/EurotruckSimulator2/EurotruckSimulator2Model.cs b/Artemis/Artemis/Modules/Games/EurotruckSimulator2/EurotruckSimulator2Model.cs index 481e80f89..2df7313e9 100644 --- a/Artemis/Artemis/Modules/Games/EurotruckSimulator2/EurotruckSimulator2Model.cs +++ b/Artemis/Artemis/Modules/Games/EurotruckSimulator2/EurotruckSimulator2Model.cs @@ -1,27 +1,37 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.IO; using Artemis.DAL; using Artemis.Managers; using Artemis.Models; using Artemis.Modules.Games.EurotruckSimulator2.Data; using Artemis.Profiles.Layers.Models; +using Artemis.Properties; +using Artemis.Services; +using Artemis.Settings; +using Artemis.Utilities; using Ninject.Extensions.Logging; namespace Artemis.Modules.Games.EurotruckSimulator2 { public class EurotruckSimulator2Model : GameModel { - public EurotruckSimulator2Model(MainManager mainManager) - : base(mainManager, SettingsProvider.Load(), new EurotruckSimulator2DataModel() - ) + private readonly MetroDialogService _dialogService; + + public EurotruckSimulator2Model(DeviceManager deviceManager, MetroDialogService dialogService) + : base( + deviceManager, SettingsProvider.Load(), new EurotruckSimulator2DataModel()) { + _dialogService = dialogService; Name = "EurotruckSimulator2"; ProcessName = "eurotrucks2"; Scale = 4; Enabled = Settings.Enabled; Initialized = false; + + FindGameDir(); } - public ILogger Logger { get; set; } public int Scale { get; set; } public override void Dispose() @@ -47,6 +57,66 @@ namespace Artemis.Modules.Games.EurotruckSimulator2 dataModel.Truck = telemetryData.Truck; } + public void FindGameDir() + { + var gameSettings = (EurotruckSimulator2Settings) Settings; + // Demo is also supported but resides in a different directory, the full game can also be 64-bits + var dir = GeneralHelpers.FindSteamGame(@"\Euro Truck Simulator 2\bin\win_x64\eurotrucks2.exe") ?? + GeneralHelpers.FindSteamGame(@"\Euro Truck Simulator 2\bin\win_x86\eurotrucks2.exe") ?? + GeneralHelpers.FindSteamGame(@"\Euro Truck Simulator 2 Demo\bin\win_x86\eurotrucks2.exe"); + + if (string.IsNullOrEmpty(dir)) + return; + + gameSettings.GameDirectory = dir; + gameSettings.Save(); + + if (!File.Exists(dir + "/plugins/ets2-telemetry-server.dll")) + PlacePlugin(); + } + + public void PlacePlugin() + { + var gameSettings = (EurotruckSimulator2Settings) Settings; + if (gameSettings.GameDirectory == string.Empty) + return; + + var path = gameSettings.GameDirectory; + + // Ensure the selected directory exists + if (!Directory.Exists(path)) + { + _dialogService.ShowErrorMessageBox($"Directory '{path}' not found."); + return; + } + // Ensure it's the ETS2 directory by looking for the executable + if (!File.Exists(path + "/eurotrucks2.exe")) + { + _dialogService.ShowErrorMessageBox("Please select a valid Eurotruck Simulator 2 directory\n\n" + + @"By default ETS2 is in \SteamApps\common\Euro Truck Simulator 2\bin\win_x64"); + return; + } + + // Create the plugins folder if it's not already there + Directory.CreateDirectory(path + "/plugins"); + + // Place either the 64-bits or 32-bits DLL + try + { + if (path.Contains("win_x64")) + File.WriteAllBytes(path + "/plugins/ets2-telemetry-server.dll", Resources.ets2_telemetry_server_x64); + else + File.WriteAllBytes(path + "/plugins/ets2-telemetry-server.dll", Resources.ets2_telemetry_server_x86); + + Logger?.Debug("Installed ETS2 plugin in {0}", path); + } + catch (Exception e) + { + Logger?.Error(e, "Failed to install ETS2 plugin in {0}", path); + throw; + } + } + public override List GetRenderLayers(bool keyboardOnly) { return Profile.GetRenderLayers(DataModel, keyboardOnly); diff --git a/Artemis/Artemis/Modules/Games/EurotruckSimulator2/EurotruckSimulator2ViewModel.cs b/Artemis/Artemis/Modules/Games/EurotruckSimulator2/EurotruckSimulator2ViewModel.cs index 99f7ec9b0..26e69f4fb 100644 --- a/Artemis/Artemis/Modules/Games/EurotruckSimulator2/EurotruckSimulator2ViewModel.cs +++ b/Artemis/Artemis/Modules/Games/EurotruckSimulator2/EurotruckSimulator2ViewModel.cs @@ -1,40 +1,18 @@ -using System; -using System.IO; +using System.IO; using System.Windows.Forms; -using Ninject; using Artemis.Managers; -using Artemis.Properties; -using Artemis.Utilities; +using Artemis.Models; using Artemis.ViewModels.Abstract; +using Ninject; namespace Artemis.Modules.Games.EurotruckSimulator2 { public sealed class EurotruckSimulator2ViewModel : GameViewModel { public EurotruckSimulator2ViewModel(MainManager main, IKernel kernel, - EurotruckSimulator2Model model) : base(main, model, kernel) + [Named("EurotruckSimulator2Model")] GameModel model) : base(main, model, kernel) { DisplayName = "ETS 2"; - - FindGameDir(); - } - - public void FindGameDir() - { - var gameSettings = (EurotruckSimulator2Settings) GameSettings; - // Demo is also supported but resides in a different directory, the full game can also be 64-bits - var dir = GeneralHelpers.FindSteamGame(@"\Euro Truck Simulator 2\bin\win_x64\eurotrucks2.exe") ?? - GeneralHelpers.FindSteamGame(@"\Euro Truck Simulator 2\bin\win_x86\eurotrucks2.exe") ?? - GeneralHelpers.FindSteamGame(@"\Euro Truck Simulator 2 Demo\bin\win_x86\eurotrucks2.exe"); - - if (string.IsNullOrEmpty(dir)) - return; - - gameSettings.GameDirectory = dir; - gameSettings.Save(); - - if (!File.Exists(dir + "/plugins/ets2-telemetry-server.dll")) - PlacePlugin(); } public void BrowseDirectory() @@ -51,49 +29,7 @@ namespace Artemis.Modules.Games.EurotruckSimulator2 NotifyOfPropertyChange(() => GameSettings); GameSettings.Save(); - PlacePlugin(); - } - - public void PlacePlugin() - { - if (((EurotruckSimulator2Settings) GameSettings).GameDirectory == string.Empty) - return; - - var path = ((EurotruckSimulator2Settings) GameSettings).GameDirectory; - - // Ensure the selected directory exists - if (!Directory.Exists(path)) - { - DialogService.ShowErrorMessageBox($"Directory '{path}' not found."); - return; - } - // Ensure it's the ETS2 directory by looking for the executable - if (!File.Exists(path + "/eurotrucks2.exe")) - { - DialogService.ShowErrorMessageBox("Please select a valid Eurotruck Simulator 2 directory\n\n" + - @"By default ETS2 is in \SteamApps\common\Euro Truck Simulator 2\bin\win_x64"); - return; - } - - // Create the plugins folder if it's not already there - Directory.CreateDirectory(path + "/plugins"); - - // Place either the 64-bits or 32-bits DLL - try - { - if (path.Contains("win_x64")) - File.WriteAllBytes(path + "/plugins/ets2-telemetry-server.dll", Resources.ets2_telemetry_server_x64); - else - File.WriteAllBytes(path + "/plugins/ets2-telemetry-server.dll", Resources.ets2_telemetry_server_x86); - - MainManager.Logger.Debug("Installed ETS2 plugin in {0}", path); - } - catch (Exception e) - { - MainManager.Logger.Error(e, "Failed to install ETS2 plugin in {0}", path); - throw; - } - + ((EurotruckSimulator2Model) GameModel).PlacePlugin(); } } } \ No newline at end of file diff --git a/Artemis/Artemis/Modules/Games/GtaV/GtaVDataModel.cs b/Artemis/Artemis/Modules/Games/GtaV/GtaVDataModel.cs new file mode 100644 index 000000000..dd0ed94a3 --- /dev/null +++ b/Artemis/Artemis/Modules/Games/GtaV/GtaVDataModel.cs @@ -0,0 +1,12 @@ +using Artemis.Models.Interfaces; +using MoonSharp.Interpreter; + +namespace Artemis.Modules.Games.GtaV +{ + [MoonSharpUserData] + public class GtaVDataModel : IDataModel + { + public bool IsWanted { get; set; } + public string Color { get; set; } + } +} \ No newline at end of file diff --git a/Artemis/Artemis/Modules/Games/GtaV/GtaVModel.cs b/Artemis/Artemis/Modules/Games/GtaV/GtaVModel.cs new file mode 100644 index 000000000..703dd740e --- /dev/null +++ b/Artemis/Artemis/Modules/Games/GtaV/GtaVModel.cs @@ -0,0 +1,88 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Media; +using Artemis.DAL; +using Artemis.Managers; +using Artemis.Models; +using Artemis.Profiles.Layers.Models; +using Artemis.Utilities; +using Artemis.Utilities.DataReaders; + +namespace Artemis.Modules.Games.GtaV +{ + public class GtaVModel : GameModel + { + private readonly PipeServer _pipeServer; + + public GtaVModel(DeviceManager deviceManager, PipeServer pipeServer) + : base(deviceManager, SettingsProvider.Load(), new GtaVDataModel()) + { + _pipeServer = pipeServer; + Name = "GTAV"; + ProcessName = "GTA5"; + Enabled = Settings.Enabled; + Initialized = false; + } + + public override void Enable() + { + DllManager.PlaceLogitechDll(); + _pipeServer.PipeMessage += PipeServerOnPipeMessage; + Initialized = true; + } + + public override void Dispose() + { + Initialized = false; + + // Delay restoring the DLL to allow GTA to release it + Task.Factory.StartNew(() => + { + Thread.Sleep(2000); + DllManager.RestoreLogitechDll(); + }); + + _pipeServer.PipeMessage -= PipeServerOnPipeMessage; + base.Dispose(); + } + + public override void Update() + { + // DataModel updating is done whenever a pipe message is received + } + + public override List GetRenderLayers(bool keyboardOnly) + { + return Profile.GetRenderLayers(DataModel, keyboardOnly); + } + + private void PipeServerOnPipeMessage(string reply) + { + if (!Initialized) + return; + + // Convert the given string to a list of ints + var stringParts = reply.Split(' '); + var parts = new string[stringParts.Length]; + for (var i = 0; i < stringParts.Length; i++) + parts[i] = stringParts[i]; + + if (parts[0] == "0") + InterpertrateLighting(parts); + } + + private void InterpertrateLighting(string[] parts) + { + var gameDataModel = (GtaVDataModel) DataModel; + + var custom = parts[1]; + gameDataModel.IsWanted = custom.StartsWith("ff"); + + var rPer = byte.Parse(parts[2]); + var gPer = byte.Parse(parts[3]); + var bPer = byte.Parse(parts[4]); + gameDataModel.Color = Color.FromArgb(255, rPer, gPer, bPer).ToHex(); + } + } +} \ No newline at end of file diff --git a/Artemis/Artemis/Modules/Games/GtaV/GtaVSettings.cs b/Artemis/Artemis/Modules/Games/GtaV/GtaVSettings.cs new file mode 100644 index 000000000..d147628f9 --- /dev/null +++ b/Artemis/Artemis/Modules/Games/GtaV/GtaVSettings.cs @@ -0,0 +1,8 @@ +using Artemis.Settings; + +namespace Artemis.Modules.Games.GtaV +{ + public class GtaVSettings : GameSettings + { + } +} \ No newline at end of file diff --git a/Artemis/Artemis/Modules/Games/GtaV/GtaVView.xaml b/Artemis/Artemis/Modules/Games/GtaV/GtaVView.xaml new file mode 100644 index 000000000..d90fccd1e --- /dev/null +++ b/Artemis/Artemis/Modules/Games/GtaV/GtaVView.xaml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public async void AddProfile() { - if (_mainManager.DeviceManager.ActiveKeyboard == null) + if (_deviceManager.ActiveKeyboard == null) { DialogService.ShowMessageBox("Cannot add profile.", "To add a profile, please select a keyboard in the options menu first."); @@ -503,9 +494,9 @@ namespace Artemis.ViewModels.Profiles var profile = new ProfileModel { Name = name, - KeyboardSlug = _mainManager.DeviceManager.ActiveKeyboard.Slug, - Width = _mainManager.DeviceManager.ActiveKeyboard.Width, - Height = _mainManager.DeviceManager.ActiveKeyboard.Height, + KeyboardSlug = _deviceManager.ActiveKeyboard.Slug, + Width = _deviceManager.ActiveKeyboard.Width, + Height = _deviceManager.ActiveKeyboard.Height, GameName = _gameModel.Name }; @@ -601,7 +592,7 @@ namespace Artemis.ViewModels.Profiles public async void ImportProfile() { - if (_mainManager.DeviceManager.ActiveKeyboard == null) + if (_deviceManager.ActiveKeyboard == null) { DialogService.ShowMessageBox("Cannot import profile.", "To import a profile, please select a keyboard in the options menu first."); @@ -629,7 +620,7 @@ namespace Artemis.ViewModels.Profiles } // Verify the keyboard - var deviceManager = _mainManager.DeviceManager; + var deviceManager = _deviceManager; if (profile.KeyboardSlug != deviceManager.ActiveKeyboard.Slug) { var adjustKeyboard = await DialogService.ShowQuestionMessageBox("Profile not inteded for this keyboard", @@ -687,7 +678,7 @@ namespace Artemis.ViewModels.Profiles return; try { - SelectedProfile?.Activate(_mainManager.DeviceManager.ActiveKeyboard); + SelectedProfile?.Activate(_deviceManager.ActiveKeyboard); LuaWrapper.OpenEditor(); } catch (Exception e) diff --git a/Artemis/Artemis/ViewModels/ShellViewModel.cs b/Artemis/Artemis/ViewModels/ShellViewModel.cs index d8d2568d2..c4fc3a190 100644 --- a/Artemis/Artemis/ViewModels/ShellViewModel.cs +++ b/Artemis/Artemis/ViewModels/ShellViewModel.cs @@ -1,6 +1,5 @@ -using System.Linq; -using Artemis.Managers; -using Artemis.Services; +using System; +using System.Linq; using Artemis.ViewModels.Abstract; using Artemis.ViewModels.Flyouts; using Caliburn.Micro; @@ -10,17 +9,18 @@ namespace Artemis.ViewModels { public sealed class ShellViewModel : Conductor.Collection.OneActive { - private readonly BaseViewModel[] _viewModels; + private readonly IKernel _kernel; - public ShellViewModel(IKernel kernel, BaseViewModel[] viewModels) + public ShellViewModel(IKernel kernel, FlyoutSettingsViewModel flyoutSettings) { - _viewModels = viewModels; + _kernel = kernel; // Setup UI DisplayName = "Artemis"; + Flyouts = new BindableCollection { - kernel.Get() + flyoutSettings }; } @@ -29,10 +29,16 @@ namespace Artemis.ViewModels protected override void OnActivate() { base.OnActivate(); - foreach (var screen in _viewModels) - ActivateItem(screen); + Items.Clear(); - ActiveItem = _viewModels.FirstOrDefault(); + var vms = _kernel.GetAll(); + Items.AddRange(vms); + } + + protected override void OnDeactivate(bool close) + { + base.OnDeactivate(close); + Items.Clear(); } public void Settings() diff --git a/Artemis/Artemis/ViewModels/SystemTrayViewModel.cs b/Artemis/Artemis/ViewModels/SystemTrayViewModel.cs index 9847678e7..b5adfcf72 100644 --- a/Artemis/Artemis/ViewModels/SystemTrayViewModel.cs +++ b/Artemis/Artemis/ViewModels/SystemTrayViewModel.cs @@ -14,18 +14,16 @@ namespace Artemis.ViewModels { public class SystemTrayViewModel : Screen { - private readonly ShellViewModel _shellViewModel; - private readonly IWindowManager _windowManager; + private readonly WindowService _windowService; + private ShellViewModel _shellViewModel; private string _activeIcon; private bool _checked; private bool _enabled; private string _toggleText; - public SystemTrayViewModel(IWindowManager windowManager, MetroDialogService dialogService, - ShellViewModel shellViewModel, MainManager mainManager) + public SystemTrayViewModel(WindowService windowService, MetroDialogService dialogService, MainManager mainManager) { - _windowManager = windowManager; - _shellViewModel = shellViewModel; + _windowService = windowService; DialogService = dialogService; MainManager = mainManager; @@ -43,8 +41,17 @@ namespace Artemis.ViewModels public MainManager MainManager { get; set; } - public bool CanShowWindow => !_shellViewModel.IsActive; - public bool CanHideWindow => _shellViewModel.IsActive && !MainManager.DeviceManager.ChangingKeyboard; + public bool CanShowWindow + { + get + { + if (_shellViewModel == null) + return true; + return !_shellViewModel.IsActive; + } + } + + public bool CanHideWindow => (_shellViewModel?.IsActive == true) && !MainManager.DeviceManager.ChangingKeyboard; public bool CanToggleEnabled => !MainManager.DeviceManager.ChangingKeyboard; public bool Enabled @@ -111,7 +118,7 @@ namespace Artemis.ViewModels return; // manually show the next window view-model - _windowManager.ShowWindow(_shellViewModel); + _shellViewModel = _windowService.ShowWindow(); NotifyOfPropertyChange(() => CanShowWindow); NotifyOfPropertyChange(() => CanHideWindow); diff --git a/Artemis/LogiLed2Artemis/LogiLed2Artemis.vcxproj b/Artemis/LogiLed2Artemis/LogiLed2Artemis.vcxproj index 670478206..e41b51302 100644 --- a/Artemis/LogiLed2Artemis/LogiLed2Artemis.vcxproj +++ b/Artemis/LogiLed2Artemis/LogiLed2Artemis.vcxproj @@ -104,6 +104,7 @@ Disabled WIN32;_DEBUG;_WINDOWS;_USRDLL;LOGILEDCORSAIR_EXPORTS;%(PreprocessorDefinitions) %(AdditionalIncludeDirectories) + true Windows @@ -111,6 +112,9 @@ LogiLed2Artemis.def %(AdditionalDependencies) + + true + @@ -151,12 +155,10 @@ - - diff --git a/Artemis/LogiLed2Artemis/LogiLed2Artemis.vcxproj.filters b/Artemis/LogiLed2Artemis/LogiLed2Artemis.vcxproj.filters index 34a553926..00ff5943c 100644 --- a/Artemis/LogiLed2Artemis/LogiLed2Artemis.vcxproj.filters +++ b/Artemis/LogiLed2Artemis/LogiLed2Artemis.vcxproj.filters @@ -21,17 +21,11 @@ Header Files - - Header Files - Source Files - - Source Files - diff --git a/Artemis/LogiLed2Artemis/main.cpp b/Artemis/LogiLed2Artemis/main.cpp index c224e7daf..23e25b587 100644 --- a/Artemis/LogiLed2Artemis/main.cpp +++ b/Artemis/LogiLed2Artemis/main.cpp @@ -30,69 +30,50 @@ #include "LogiLedDefs.h" #define WIN32_LEAN_AND_MEAN #include -#include "Logger.h" - #include #include - +#include +using namespace std; static bool g_hasInitialised = false; +static bool mustLog = false; const char* game = ""; -void cleanup() -{ - CLogger::EndLogging(); -} BOOL WINAPI DllMain(HINSTANCE hInst, DWORD fdwReason, LPVOID) { - switch (fdwReason) + if (fdwReason == DLL_PROCESS_ATTACH) { - case DLL_PROCESS_ATTACH: + // Get the process that loaded the DLL + TCHAR divisionFind[] = _T("Division"); + TCHAR gtaFind[] = _T("GTA"); + TCHAR szPath[MAX_PATH]; + GetModuleFileName(NULL, szPath, MAX_PATH); + + if (_tcscmp(szPath, divisionFind) != 0) + game = "division"; + else if (_tcscmp(szPath, gtaFind) != 0) + game = "gta"; + + if (mustLog) { - atexit(cleanup); - - CLogger::InitLogging("Log.txt"); - CLogger::SetLogLevel(LogLevel::None); - - // Get the process that loaded the DLL - TCHAR divisionFind[] = _T("Division"); - TCHAR gtaFind[] = _T("GTA"); - TCHAR szPath[MAX_PATH]; - GetModuleFileName(NULL, szPath, MAX_PATH); - - if (_tcscmp(szPath, divisionFind) != 0) - game = "division"; - else if (_tcscmp(szPath, gtaFind) != 0) - game = "gta"; - - CLogger::OutputLog("Attached to process.", LogLevel::Debug); + ofstream myfile; + myfile.open("log.txt", ios::out | ios::app); + myfile << "Main called, DLL loaded into " << szPath << "\n"; + myfile.close(); } - break; - - case DLL_PROCESS_DETACH: - { - cleanup(); - - CLogger::OutputLog_s("Detached from process.", LogLevel::Debug); - } - break; } - return true; } bool LogiLedInit() { - CLogger::OutputLog_s("Logitech LED init called.", LogLevel::Debug); g_hasInitialised = true; return true; } bool LogiLedGetSdkVersion(int* majorNum, int* minorNum, int* buildNum) { - CLogger::OutputLog("LogiLedGetSdkVersion called.", LogLevel::Debug); - // Mimic the SDK version *majorNum = 8; *minorNum = 81; @@ -103,15 +84,12 @@ bool LogiLedGetSdkVersion(int* majorNum, int* minorNum, int* buildNum) bool LogiLedSetTargetDevice(int targetDevice) { - CLogger::OutputLog("LogiLedSetTargetDevice called (%i)", LogLevel::Debug, targetDevice); - // Logitech SDK says this function returns false if LogiLedInit hasn't been called return g_hasInitialised; } bool LogiLedSaveCurrentLighting() { - CLogger::OutputLog("LogiLedSaveCurrentLighting called (%i)", LogLevel::Debug); return true; } @@ -125,21 +103,39 @@ void Transmit(const char* msg) hPipe1 = CreateFile(lpszPipename1, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if (hPipe1 == NULL || hPipe1 == INVALID_HANDLE_VALUE) { - CLogger::OutputLog("Could not open the pipe - (error %i)", LogLevel::Debug, GetLastError()); + if (mustLog) + { + ofstream myfile; + myfile.open("log.txt", ios::out | ios::app); + myfile << "Could not open the pipe - " << GetLastError() << "\n"; + myfile.close(); + } return; } DWORD cbWritten; WriteFile(hPipe1, msg, strlen(msg), &cbWritten, NULL); - CLogger::OutputLog_s("Transmitted to pipe", LogLevel::Debug); } -bool LogiLedSetLighting(int redPercentage, int greenPercentage, int bluePercentage) +// LogiLedSetLighting appears to have an undocumented extra argument +bool LogiLedSetLighting(int redPercentage, int greenPercentage, int bluePercentage, int custom = 0) { - CLogger::OutputLog("LogiLedSetLighting called (%i %i %i)", LogLevel::Debug, redPercentage, greenPercentage, bluePercentage); - - std::ostringstream os; - os << "0 0 " << redPercentage << " " << greenPercentage << " " << bluePercentage; + if (mustLog) + { + ofstream myfile; + myfile.open("log.txt", ios::out | ios::app); + if (custom == 0) + { + myfile << "LogiLedSetLighting called\n"; + } + else + { + myfile << "LogiLedSetLighting called with custom " << custom << "\n"; + } + myfile.close(); + } + ostringstream os; + os << "0 " << hex << custom << " " << dec << redPercentage << " " << greenPercentage << " " << bluePercentage; Transmit(os.str().c_str()); return true; @@ -147,108 +143,209 @@ bool LogiLedSetLighting(int redPercentage, int greenPercentage, int bluePercenta bool LogiLedRestoreLighting() { - CLogger::OutputLog("LogiLedRestoreLighting called", LogLevel::Debug); + if (mustLog) + { + ofstream myfile; + myfile.open("log.txt", ios::out | ios::app); + myfile << "LogiLedRestoreLighting called\n"; + myfile.close(); + } + return true; } bool LogiLedFlashLighting(int redPercentage, int greenPercentage, int bluePercentage, int milliSecondsDuration, int milliSecondsInterval) { - CLogger::OutputLog("LogiLedFlashLighting called (%i %i %i %i %i)", LogLevel::Debug, redPercentage, greenPercentage, bluePercentage, milliSecondsDuration, milliSecondsInterval); + if (mustLog) + { + ofstream myfile; + myfile.open("log.txt", ios::out | ios::app); + myfile << "LogiLedFlashLighting called\n"; + myfile.close(); + } + return true; } bool LogiLedPulseLighting(int redPercentage, int greenPercentage, int bluePercentage, int milliSecondsDuration, int milliSecondsInterval) { - CLogger::OutputLog("LogiLedPulseLighting called (%i %i %i %i %i)", LogLevel::Debug, redPercentage, greenPercentage, bluePercentage, milliSecondsDuration, milliSecondsInterval); + if (mustLog) + { + ofstream myfile; + myfile.open("log.txt", ios::out | ios::app); + myfile << "LogiLedPulseLighting called\n"; + myfile.close(); + } + return true; } bool LogiLedStopEffects() { - CLogger::OutputLog_s("LogiLedStopEffects called", LogLevel::Debug); + if (mustLog) + { + ofstream myfile; + myfile.open("log.txt", ios::out | ios::app); + myfile << "LogiLedStopEffects called\n"; + myfile.close(); + } + return true; } bool LogiLedSetLightingFromBitmap(unsigned char bitmap[]) { - CLogger::OutputLog_s("LogiLedSetLightingFromBitmap called", LogLevel::Debug); + if (mustLog) + { + ofstream myfile; + myfile.open("log.txt", ios::out | ios::app); + myfile << "LogiLedSetLightingFromBitmap called\n"; + myfile.close(); + } + return true; } bool LogiLedSetLightingForKeyWithScanCode(int keyCode, int redPercentage, int greenPercentage, int bluePercentage) { - CLogger::OutputLog("LogiLedSetLightingForKeyWithScanCode called [Key: %i] (%i %i %i)", LogLevel::Debug, keyCode, redPercentage, greenPercentage, bluePercentage); + if (mustLog) + { + ofstream myfile; + myfile.open("log.txt", ios::out | ios::app); + myfile << "LogiLedSetLightingForKeyWithScanCode called\n"; + myfile.close(); + } + return true; } bool LogiLedSetLightingForKeyWithHidCode(int keyCode, int redPercentage, int greenPercentage, int bluePercentage) { - CLogger::OutputLog("LogiLedSetLightingForKeyWithHidCode called [Key: %i] (%i %i %i)", LogLevel::Debug, keyCode, redPercentage, greenPercentage, bluePercentage); + if (mustLog) + { + ofstream myfile; + myfile.open("log.txt", ios::out | ios::app); + myfile << "LogiLedSetLightingForKeyWithHidCode called\n"; + myfile.close(); + } + return true; } bool LogiLedSetLightingForKeyWithQuartzCode(int keyCode, int redPercentage, int greenPercentage, int bluePercentage) { - CLogger::OutputLog("LogiLedSetLightingForKeyWithQuartzCode called [Key: %i] (%i %i %i)", LogLevel::Debug, keyCode, redPercentage, greenPercentage, bluePercentage); + if (mustLog) + { + ofstream myfile; + myfile.open("log.txt", ios::out | ios::app); + myfile << "LogiLedSetLightingForKeyWithQuartzCode called\n"; + myfile.close(); + } + return true; } bool LogiLedSetLightingForKeyWithKeyName(LogiLed::KeyName keyName, int redPercentage, int greenPercentage, int bluePercentage) { - CLogger::OutputLog("LogiLedSetLightingForKeyWithKeyName called [Key: %i] (%i %i %i)", LogLevel::Debug, keyName, redPercentage, greenPercentage, bluePercentage); + if (mustLog) + { + ofstream myfile; + myfile.open("log.txt", ios::out | ios::app); + myfile << "LogiLedSetLightingForKeyWithKeyName called\n"; + myfile.close(); + } // Only transmit interesting keys. This can most likely be done prettier, but I'm no C++ dev. - if (game == "division" && - (keyName == LogiLed::F1 || - keyName == LogiLed::F2 || - keyName == LogiLed::F3 || - keyName == LogiLed::F4 || - keyName == LogiLed::R || - keyName == LogiLed::G || - keyName == LogiLed::V) - ) + if (game == "division" && (keyName == LogiLed::F1 || keyName == LogiLed::F2 || keyName == LogiLed::F3 || keyName == LogiLed::F4 || keyName == LogiLed::R || keyName == LogiLed::G || keyName == LogiLed::V)) { - std::ostringstream os; + ostringstream os; os << "1 " << keyName << " " << redPercentage << " " << greenPercentage << " " << bluePercentage; - std::string s = os.str(); + string s = os.str(); Transmit(os.str().c_str()); + return true; } + + ostringstream os; + os << "1 " << keyName << " " << redPercentage << " " << greenPercentage << " " << bluePercentage; + string s = os.str(); + Transmit(os.str().c_str()); return true; } bool LogiLedSaveLightingForKey(LogiLed::KeyName keyName) { - CLogger::OutputLog("LogiLedSaveLightingForKey called [Key: %i]", LogLevel::Debug, keyName); + if (mustLog) + { + ofstream myfile; + myfile.open("log.txt", ios::out | ios::app); + myfile << "LogiLedSaveLightingForKey called\n"; + myfile.close(); + } + return true; } bool LogiLedRestoreLightingForKey(LogiLed::KeyName keyName) { - CLogger::OutputLog("LogiLedRestoreLightingForKey called [Key: %i]", LogLevel::Debug, keyName); + if (mustLog) + { + ofstream myfile; + myfile.open("log.txt", ios::out | ios::app); + myfile << "LogiLedRestoreLightingForKey called\n"; + myfile.close(); + } + return true; } bool LogiLedFlashSingleKey(LogiLed::KeyName keyName, int redPercentage, int greenPercentage, int bluePercentage, int msDuration, int msInterval) { - CLogger::OutputLog("LogiLedFlashSingleKey called [Key: %i] (%i %i %i %i %i)", LogLevel::Debug, keyName, redPercentage, greenPercentage, bluePercentage, msDuration, msInterval); + if (mustLog) + { + ofstream myfile; + myfile.open("log.txt", ios::out | ios::app); + myfile << "LogiLedFlashSingleKey called\n"; + myfile.close(); + } + return true; } bool LogiLedPulseSingleKey(LogiLed::KeyName keyName, int startRedPercentage, int startGreenPercentage, int startBluePercentage, int finishRedPercentage, int finishGreenPercentage, int finishBluePercentage, int msDuration, bool isInfinite) { - CLogger::OutputLog("LogiLedPulseSingleKey called [Key: %i] (%i %i %i %i %i %i %i %i)", LogLevel::Debug, keyName, startRedPercentage, startGreenPercentage, startBluePercentage, finishRedPercentage, finishGreenPercentage, finishBluePercentage, msDuration, isInfinite); + if (mustLog) + { + ofstream myfile; + myfile.open("log.txt", ios::out | ios::app); + myfile << "LogiLedPulseSingleKey called\n"; + myfile.close(); + } + return true; } bool LogiLedStopEffectsOnKey(LogiLed::KeyName keyName) { - CLogger::OutputLog("LogiLedStopEffectsOnKey called [Key: %i]", LogLevel::Debug, keyName); + if (mustLog) + { + ofstream myfile; + myfile.open("log.txt", ios::out | ios::app); + myfile << "LogiLedStopEffectsOnKey called\n"; + myfile.close(); + } + return true; } void LogiLedShutdown() { - CLogger::OutputLog_s("LogiLedShutdown called.", LogLevel::Debug); + if (mustLog) + { + ofstream myfile; + myfile.open("log.txt", ios::out | ios::app); + myfile << "LogiLedShutdown called\n"; + myfile.close(); + } + g_hasInitialised = false; } -